PHP5.3: "Calling the undefined method" when calling a call from a class variable

I did some tests (to replace old code) using the __invoke magic method, and I'm not sure if this is an error or not:

Suppose we have a class:

class Calc { function __invoke($a,$b){ return $a*$b; } } 

Maybe it works without problems:

 $c = new Calc; $k = $c; echo $k(4,5); //outputs 20 

However, if I want to have another class to hold an instance of this object, this does not work:

 class Test { public $k; function __construct() { $c = new Calc; $this->k = $c; //Just to show a similar situation than before // $this-k = new Calc; produces the same error. } } 

The error occurs when we try to call it this:

 $t = new Test; echo $t->k(4,5); //Error: Call to undefined method Test::k() 

I know that the “solution” may be a function inside the Test class (named k) to “redirect” the call using call_user_func_array, but this is not elegant.

I need to save this instance inside a general class (for design purposes) and be able to call it as a function from other classes ... any suggestion?

Update:

I found something interesting (at least for my purposes):

If we assign a "class variable" to a local variable, it works:

 $t = new Test; $m = $t->k; echo $m(4,5); 
+6
methods php invoke
source share
4 answers

When you execute $test->k() , PHP thinks you are calling the method on the $test instance. Since there is no method named k() , PHP throws an exception. What you are trying to do is make PHP return the public property k and call it, but for this you need to first assign k variable. This is a dereferencing issue.

You can add the magic __call method to your Test class to check if there is a property with the name of the called method and call it instead:

 public function __call($method, $args) { if(property_exists($this, $method)) { $prop = $this->$method; return $prop(); } } 

I leave you arguments to call. You can also check if the is_callable property is_callable .

But anyway, you can do

 $test->k(); 
+5
source share

PHP thinks you want to call method k on an instance of $ t when you do this:

 $t->k(4, 5) 

which is quite reasonable. You can use an intermediate variable to call an object:

 $b = $t->k; $b(4, 5); 

See also error # 50029 , which describes your problem.

+6
source share

You cannot use method syntax (for example, $ foo-> bar ()) to call closures or objects with __invoke, since the engine always considers this to be a method call. You can simulate it via __call:

 function __call($name, $params) { if(is_callable($this->$name)) { call_user_func_array($this->$name, $params); } } 

but it will not work as is.

+2
source share

If you call $ test-> k (), PHP will look for a method named "k" in the instance of $ test and, obviously, will throw an exception.

To solve this problem, you can create a method for obtaining the property "k"

 class Test { public $k; function __construct() { $c = new Calc; $this->k = $c; //Just to show a similar situation than before // $this-k = new Calc; produces the same error. } public function getK() { return $this->k; } } 

So now you can use the functor as follows:

 $t = new Test(); echo $t->getK()(4,5); 
0
source share

All Articles