你好基本上在Laravel你可以做这样的事情
User::get();
而且我知道场景背后的laravel通过调用一个名为__callStatic()
的魔术方法并从中返回new static
来实现这一点。
但 __callStatic
仅适用于无法访问或不存在的方法。
所以我的问题是,当User::get()
实际上是get()
时,你如何才能做到public function
?
修改
鉴于我在这里有这个简单的代码
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
答案 0 :(得分:2)
它无法正常工作,因为您无法静态调用非静态方法。
它与get()
等方法一起使用的原因是因为这些调用被委托给查询实例 - 它们实际上并不存在于模型本身上。
如果你检查__call
方法,它应该变得更加清晰:
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement'])) {
return $this->$method(...$parameters);
}
return $this->newQuery()->$method(...$parameters);
}
所以即使默认的__callStatic
方法实现调用非静态方法:
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
您的代码会立即失败,因为您的模型实际上会包含具有相同名称的public
非静态方法。
您会看到__call
方法检查方法的名称是否在increment
和decrement
的数组中 - 如果是 - 它会调用它们。
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
,因此无论如何你都无法在模型的实例上调用它们 - 访问它们的唯一方法是使用魔术方法 - 在这种情况下,静态调用可以正常工作。
换句话说,如果您将方法的可见性更改为protected
并覆盖__call
方法以在阵列中包含您的方法名称,那么您的代码应该可以使用
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);
}
希望这有帮助。