本文介绍了使非静态变为静态(魔术方法)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,所以基本上在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方法检查该方法的名称是否在incrementdecrement的数组内-如果存在-它将调用它们.

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);
}

希望这会有所帮助.

这篇关于使非静态变为静态(魔术方法)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 21:30
查看更多