Page 1 of 1

Ghost Methods

Posted: Sun Jul 15, 2007 6:50 pm
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.

Posted: Sun Jul 15, 2007 6:52 pm
by feyd
That would be the __call magic method.

Posted: Sun Jul 15, 2007 7:03 pm
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');

Posted: Sun Jul 15, 2007 7:15 pm
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. :)

Posted: Sun Jul 15, 2007 7:43 pm
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?

Posted: Sun Jul 15, 2007 7:47 pm
by feyd
create_user_function()? I don't think so.... but maybe I don't understand what you're talking about now.

Posted: Sun Jul 15, 2007 7:51 pm
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.

Posted: Sun Jul 15, 2007 7:51 pm
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()

Posted: Sun Jul 15, 2007 7:54 pm
by feyd
Yeah, call_user_func() and call_user_func_array() are what you're looking to use.

Posted: Sun Jul 15, 2007 7:57 pm
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.

Posted: Sun Jul 15, 2007 8:19 pm
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.