Ghost Methods

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Ghost Methods

Post by Benjamin »

I'm pretty sure this isn't possible but I wanted to ask anyway to see if there is a workaround or something.

Basically lets say I have an empty class such as..

Code: Select all

class foo
{

}
Now what I would like to do is put a method inside of this class which would detect the method that was called and act accordingly. A simple example:

Code: Select all

$x = new foo();

$y = $x->ghost_method('1', '2', '3');

echo $y;
So then $y would output "ghost_method() called with 3 parameters". I would also need to values of the parameters passed to it.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

That would be the __call magic method.
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Post by Benjamin »

Sweet! I totally forgot about that.

Code: Select all

<?php
class foo
{
	public function __call($method, $arguments)
    {
    	echo "$method() called with " . count($arguments) . ' arguments: <pre>' . print_r($arguments, true) . '</pre>';
    }
}

$x = new foo();

$x->ghost_method('1', '2', '3');
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

The following may be useful to you for this as well.

Code: Select all

function flash($var)
{
  if($var === null)
  {
    return 'null';
  }
  elseif(is_array($var))
  {
    $c = 0;
    $o = 'array(';
    foreach($var as $k => $v)
    {
      $o .= ($c > 0 ? ',' : '') . ($k == $c ? '' : flash($k) . '=>') . flash($v);
      $c++;
    }
    $o .= ')';
    return $o;
  }
  elseif(is_scalar($var))
  {
    return var_export($var,true);
  }
  elseif(is_object($var))
  {
    return 'object ' . get_class($var);
  }
  elseif(is_resource($var))
  {
    return 'resource ' . get_resource_type($var);
  }
  else
  {
    return 'unknown';
  }
}

function flashOver($aForetext = null, $aArgs = null)
{
  $trace = debug_backtrace();
  //var_dump($trace);
  if (isset($trace[1]))
  {
    $line = (isset($trace[1]['line']) ? intval($trace[1]['line']) : '??');
	$file = (isset($trace[1]['file']) ? $trace[1]['file'] : 'Unknown file');
	$prefix = '(' . $line . ')' . $file . ': ';
  }
  else
  {
    $prefix = '';
  }

  if (func_num_args() == 2 and is_string($aForetext) and is_array($aArgs))
  {
    $call = $aForetext;
	$args = $aArgs;
  }
  else
  {
    $call = (!empty($trace[1]['class']) ? $trace[1]['class'] . $trace[1]['type'] : '') . $trace[1]['function'];
    $args = $trace[1]['args'];
  }
  
  $args = '(' . implode(', ', array_map('flash', $args)) . ')';

  return $prefix . $call . $args;
}
Call flashOver(). Feel free to rename them. :)
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Post by Benjamin »

Yeah that will come in handy for sure.

The next step is for me to actually call the real ghost_method(), which will be in a different class. I'm thinking I'll have to use something like create_user_function in order to call it with the original arguments?
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

create_user_function()? I don't think so.... but maybe I don't understand what you're talking about now.
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Post by Benjamin »

Well basically I'll need to forward the requested method to another class once I have done some preprocessing.

I can use create_user_function to dynamically create a function that will get an instance of the class it is supposed to go to and the call the method, along with it's parameters.

I'm not currently aware of another way to dynamically assign parameters to a function call.

The number of parameters is variable, from none to say 3 or 4.
Last edited by Benjamin on Sun Jul 15, 2007 7:51 pm, edited 1 time in total.
Begby
Forum Regular
Posts: 575
Joined: Wed Dec 13, 2006 10:28 am

Post by Begby »

If the class already exists then you can use the call_user_func() function to call it. http://us.php.net/manual/en/function.call-user-func.php

But yeah, what are you trying to do exactly, this is getting weird.

Edit: nevermind, I just saw your post above. call_user_func() is what you want.

Edit2: whoops, for a variable number of arguments I think you want call_user_func_array()
Last edited by Begby on Sun Jul 15, 2007 7:54 pm, edited 1 time in total.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Yeah, call_user_func() and call_user_func_array() are what you're looking to use.
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Post by Benjamin »

Ok, thanks guys, I believe call_user_function_array() will do the trick. I'm not sure why it wants an indexed array but I'm sure that is trivial.
Begby
Forum Regular
Posts: 575
Joined: Wed Dec 13, 2006 10:28 am

Post by Begby »

astions wrote:Ok, thanks guys, I believe call_user_function_array() will do the trick. I'm not sure why it wants an indexed array but I'm sure that is trivial.
I think its indexed so it knows what order to pass the parameters.
Post Reply