问题描述
你好,所以基本上在Laravel中你可以做这样的事情
Hello so basically in Laravel you can do something like this
User::get();
而且我知道laravel在后台通过调用名为__callStatic()
的魔术方法并从其中返回new static
来实现此目的.
And I know that behind the scene laravel does this by calling a magic method called __callStatic()
and returning a new static
out of it.
BUT __callStatic
仅适用于无法访问或不存在的方法.
BUT __callStatic
only works on inaccessible or non-existing methods.
所以我的问题是,当get()
实际上是public function
时,该怎么做?
So my question is that how you can do that User::get()
when get()
actually is a public function
?
修改
鉴于我在这里有这个简单的代码
Edit
Given I have this simple code here
class First
{
public function callThis()
{
return 'Yo';
}
public static function __callStatic($name, $arguments)
{
dd('This is not working');
}
}
First::callThis();
我明白了Non-static method First::callThis() should not be called statically
And I getNon-static method First::callThis() should not be called statically
推荐答案
它不能工作,因为您不能静态调用非静态方法.之所以可以使用get()
之类的方法,是因为这些调用被委派给查询实例-它们实际上并不存在于模型本身.
It will not work because you cannot call non static methods statically.The reason why it works with methods like get()
is because these calls are being delegated to the query instance - they don't actually exist on the model itself.
如果您检查__call
方法,则所有方法都应该变得更加清晰:
If you check __call
method, it should all become a bit more clear:
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement'])) {
return $this->$method(...$parameters);
}
return $this->newQuery()->$method(...$parameters);
}
因此,即使默认的__callStatic
方法实现本身调用了非静态方法:
So even though the default __callStatic
method implementation calls the non static method on itself:
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
您的代码将立即失败,因为您的模型实际上将包含具有相同名称的public
非静态方法.
Your code would fail straight away, because your model would actually contain the public
non-static method with the same name.
您将看到__call
方法检查该方法的名称是否在increment
和decrement
的数组内-如果存在-它将调用它们.
You'll see that the __call
method checks whether the name of the method is within the array of increment
and decrement
- and if it is - it calls them.
protected function increment($column, $amount = 1, array $extra = [])
{
return $this->incrementOrDecrement($column, $amount, $extra, 'increment');
}
protected function decrement($column, $amount = 1, array $extra = [])
{
return $this->incrementOrDecrement($column, $amount, $extra, 'decrement');
}
这两种方法实际上在模型实例上都是非静态的,但是它们的可见性设置为protected
,因此无论如何您都无法在模型实例上调用它们-唯一的方法使用魔术方法访问它们-在这种情况下,静态调用就可以正常工作.
Both of these methods are actually non-static on the instance of the model, but their visibility is set to protected
so you wouldn't be able to call them on the instance of the model anyway - the only way to access them is using magic methods - in this case static call will work just fine.
换句话说,如果您将方法的可见性更改为protected
并覆盖__call
方法以在数组中也包含您的方法名称,那么您的代码应该可以工作
In other words, if you change visibility of your method to protected
and overwrite the __call
method to also include your method name in the array, then your code should work
protected function callThis()
{
return 'Yo';
}
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement', 'callThis'])) {
return $this->$method(...$parameters);
}
return $this->newQuery()->$method(...$parameters);
}
希望这会有所帮助.
这篇关于使非静态变为静态(魔术方法)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!