Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call parent magic method from override magic method in a trait

Tags:

php

traits

Problem

I am open sourcing a trait which includes the magic method __call(). During testing, I encountered a challenge when the parent class of the class using the trait contains the __call method.

What I Tried

trait SomeTrait {
    public function __call($method, array $parameters) {
        // ...
        return parent::__call($method, $parameters);
    }
}

This results in the fatal error: Cannot access parent:: when current class scope has no parent

I also tried the following, based on some other answers:

return call_user_func_array([$this, '__call'], [$method, $parameters]);

This results in a Segmentation fault: 11. I imagine because of an infinite call loop.

Question

How can I invoke the parent's __call method from within the __call method of the trait?

If it is not possible from within the trait directly, how might I invoke the parent's __call method otherwise?

like image 206
Jason McCreary Avatar asked May 26 '15 13:05

Jason McCreary


People also ask

What is __ call () in PHP?

When you call a method on an object of the Str class and that method doesn't exist e.g., length() , PHP will invoke the __call() method. The __call() method will raise a BadMethodCallException if the method is not supported. Otherwise, it'll add the string to the argument list before calling the corresponding function.

What is Megic method?

Magic methods are special methods which override PHP's default's action when certain actions are performed on an object. Caution. All methods names starting with __ are reserved by PHP. Therefore, it is not recommended to use such method names unless overriding PHP's behavior.

Can I use constructor in trait?

Unlike traits in Scala, traits in PHP can have a constructor but it must be declared public (an error will be thrown if is private or protected). Anyway, be cautious when using constructors in traits, though, because it may lead to unintended collisions in the composing classes.

Can traits be inherited PHP?

In PHP, a trait is a way to enable developers to reuse methods of independent classes that exist in different inheritance hierarchies. Simply put, traits allow you to create desirable methods in a class setting, using the trait keyword. You can then inherit this class through the use keyword.


1 Answers

Please check code below:

trait SomeTrait
{
    public function __call($method, array $parameters)
    {
        // ...
        return is_callable(['parent', '__call']) ? parent::__call($method, $parameters) : null;
    }
}

class GreatParentClass
{
    public function __call($method, array $parameters)
    {
        return 'bar';
    }
}

class ParenClassWithoutCall
{

}

class ProxyClass extends GreatParentClass
{

}

class FooClass extends ProxyClass
{
    use SomeTrait;
}

class BarClass extends GreatParentClass
{
    use SomeTrait;
}

class BazClass extends ParenClassWithoutCall
{
    use SomeTrait;
}

class SomeClassWithoutParent
{
    use SomeTrait;
}

$class = new FooClass();
var_dump($class->foobar());

$class = new BarClass();
var_dump($class->foobar());

$class = new BazClass();
var_dump($class->foobar());

$class = new SomeClassWithoutParent();
var_dump($class->foobar());

This will print:

string(3) "bar"
string(3) "bar"
NULL
NULL

Sandbox with the code to check: http://3v4l.org/R8hI3

EDIT: I think this will cover all possibilities.

like image 69
Arius Avatar answered Oct 13 '22 20:10

Arius