__get, __call and __callStatic magic methods in PHP
Bài đăng này đã không được cập nhật trong 4 năm
In this post, I'll walk you through some concepts of PHP which are used as the fundamental building parts of the Laravel framework.
__get method
The __get() magic method is used in case you want to offer the the ability to access a non-existing property of an object. So the question is what will be returned? It depends on how we implement this __get() method. In the Container.php of the Laravel framework, we're using it to allow dynamically make
an instance of a registered binding. The implementation of it is:
public function __get($key)
{
return $this[$key];
}
The code can be read like so, If I call $container->config['providers']
, the $container
object doesn't have the $config
property, so the __get()
magic method will be called.
Next, it is the ArrayAccess
feature takes place, we're accessing an object as if it is an array. Which means the offsetGet method will be called. At the end of the functions call stack, what we will recieve is the instance of the registered config
binding.
__callStatic() method
The __callStatic() method is called when we try to call a non-existing method in the static context (non-existing doesn't only mean undefined, but also mean un-visible due to visibility declaration such as private, protected).
This is one of the best examples for such thing is deserved to be called "Magic". For all Laravel developers out there, we all familiar with a kind of magic which heavily relies on this magic method. For instance:
$users = User::all()
We're calling the all()
method through the User
class which is a model, in other words, we're calling the all()
method in a static context. And we also notice, the User
class doesn't has the all()
method, neither its parent class, Model
. So, what exactly is being called here? That's the __callStaic() method in the Model
class.
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
What this __callStatic method do is instanciating a new instance of the User
class via new static
(not the Model
class, you might want to look up to the static
keyword to know more about how it works). And then, calling the all()
method on that new instance.
So now, this is __call()
method turns, let's see how it works.
__call() method
The __call() method is pretty much like the __callStatic() method, the only difference is the calling context. This method is called in an object context. Don't be confused, be called in an object context is just simply be called through an instance, not through a class name.
For example:
$person = new Person;
$person->talk();
The talk()
method is called in an object context because $person
, in this example, is an object (or instance, the same).
Continue with the above example, when User::all()
is handled by __callStatic
, it starts to call all()
on the newly created User instance. But the User instance doesn't have the all()
method either. This is when the __call
method takes place:
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement'])) {
return $this->$method(...$parameters);
}
return $this->forwardCallTo($this->newQuery(), $method, $parameters);
}
I will not get into details of this implementation of the __call
method. Just to show you how we're chaining __callStatic
and __call
to perform the query functions that you might find very magic.
Conclusion
Hopefully this post give you some more information about how these magic method work and how they ared used in practice. Also have some ideas on how some features of Laravel works under the hood. See you in the next post. Peace!
All rights reserved