使非静态变为静态(魔术方法) [英] Make static out of non-static (Magic Method)

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

问题描述

你好,所以基本上在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 get Non-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);
}

希望这会有所帮助.

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆