Search

Laravel 5 Macros: Call and Callstatic

April 21, 2018 —John Koster

The Macroable trait implements PHP's magic __call method to intercept calls to methods when in object context that do not exist in the current class. If a macro with the given method name is found, it is evaluated and the result returned. If no macro is found with the given name, an instance of BadMethodCallException is thrown.

#Signature

The signature of the __call method is:

1public function __call(
2 $method,
3 $parameters
4);

#Macroable Implementation of PHP's Magic __callStatic Method

The Macroable trait implements PHP's magic __callStatic method to intercept calls to a methods when in static context that do not exist on the target class. If a macro with the given method name is found, it is evaluated and the result returned. If no macro is found with the given name, an instance of BadMethodCallException is thrown.

#Signature

The signature of the __callStatic method is:

1public static function __callStatic(
2 $method,
3 $parameters
4);

#Important Notes On __call and __callStatic

Because Macroable depends on both the __call and __callStatic methods to be available for its own use, it is currently not possible to use the Macroable trait in a class that also requires returning a value from either __call or __callStatic without modifying the parent class's __call or __callStatic methods to accommodate the macro features. However, accommodating the macro features in a class that requires one, or both of the above magic methods is quite simple:

1use Illuminate\Support\Macroable;
2 
3class ExampleClass
4{
5 use Macroable {
6 // Because this class also defines a '__call' method, a new
7 // name has to be given to the traits '__call' method. The
8 // new name in this case is 'macroCall'.
9 __call as macroCall;
10 }
11 
12 public function __call($method, $parameters)
13 {
14 // This will first check if a macro exists, and if it does
15 // the '__call' function will return the value of the
16 // 'macroCall' function (which is defined in the 'Macroable')
17 // trait.
18 if (static::hasMacro($method))
19 {
20 return $this->macroCall($method, $parameters);
21 }
22 
23 // If no macro exists, continue with class-specific
24 // implementation of '__call'.
25 }
26 
27}

The above example is actually utilized within the framework itself with the implementation of "\Illuminate\Cache\Repository".