7
votes

I am learning how some features are being implemented in laravel, because i want to understand some software design techniques and principles.

i understand that when a static method call such as "App\User::find(1) or App\User::whereId(1)" are made on an eloquent model that the abstract model class implements a magic method "__callStatic" like so :

/**
 * Handle dynamic static method calls into the method.
 *
 * @param  string  $method
 * @param  array  $parameters
 * @return mixed
 */
public static function __callStatic($method, $parameters)
{
    $instance = new static;
    return call_user_func_array([$instance, $method], $parameters);
}

I also understand that this line '$instance = new static;' makes an instance of whatever eloquent model in which the static call was made e.g App\User.

However i don't completely understand whats going on in the next line "call_user_func_array([$instance, $method], $parameters);".

From what i have learnt so far the function call_user_func_array() is suppose to call the $method(e.g find($parameters) ) on the eloquent model instance (e.g App\user).

But i dont understand why that is not the case,and i discovered that method do not exist on the eloquent model. i tried calling a none existing method like "blah()" :

App\User::blah();

But i get the exception "BadMethodCallException with message 'Call to undefined method Illuminate\Database\Query\Builder::fisd()'".

Please how is the class "Builder" entering the scene ?

why is the exception not ""BadMethodCallException with message 'Call to undefined method Illuminate\Database\Eloquent\Model::fisd()'"" ?

i cannot see the model class extending Builder Class.

1

1 Answers

8
votes

The reason this happens is because it then triggers the __call method on the class which will try and call the method using newQuery() which returns an instance of Builder.

__call, like __callStatic, is called when you try and call an inaccessible (or nonexistent) method on a class.

So, when you try and call find() statically it will get caught by __callStatic because it doesn't exist which in turn then tries calling find() on the new instance which again doesn't exist so it gets caught by __call and it finally tries to call that method on Builder.

Hope this helps!