[英]PHP return object instance from __getStatic()
PHP有一个神奇的方法__getStatic()
,它允许重载静态方法调用。 我有一个带有流畅接口的类,可以执行完整性检查。 我这样称呼它:
$check = new CheckSomeCondition();
$check->forActive()->sites(array(1,2,3))->check();
但是,我想这样称呼它:
CheckSomeCondition::forActive()->sites(array(1,2,3))->check();
我以为在我的基类中拥有这个魔术方法将使我能够做到这一点:
public static function __callStatic($method, $args)
{
$instance = new self();
return call_user_func_array(array($instance, $method), $args);
}
但是new self()
会生成调用代码所在类的实例,而不是__callStatic()
存在的类的__callStatic()
,这是为什么? 我该如何解决呢?
我也尝试过new static
,这也做同样的事情。
我知道这是有可能的,因为Laravel的QueryBuilder具有类似DB::table()->...
的接口DB::table()->...
并且它使用方法链接,返回对象实例,而不是静态类。 我看过Laravel代码,但是我认为它们在应用程序的其他位置创建了实例,并将它们存储在准备返回的类成员中。
魔术方法__callStatic
仅针对不存在的方法调用,因此在这种情况下,它将根本无法运行。
考虑下面的简化示例:
class Foo
{
public function bar()
{
echo "Running instance method bar()";
}
public static function __callStatic($method, $args)
{
echo "__callStatic called for non-existent method $method";
}
}
Foo::bar();
如果运行此程序( 这是一个在线演示 ),您将看到被调用的是“真实” bar()
方法。
在类上只能有一个名为bar
方法,因此PHP的另一种选择是抱怨bar()
应该是static
-它确实是static
,但不是致命的。
您看到调用类实例的原因不是$instance
用错误的类$instance
化,而是因为当您的方法被非静态调用时, $this
从封闭范围中“泄漏”。
在下面的示例中, $this
最终成为Bar
的实例:
class Foo
{
public function doSomething()
{
echo get_class($this);
}
}
class Bar
{
public function doSomethingElse()
{
Foo::doSomething();
}
}
$bar = new Bar();
$bar->doSomethingElse();
正如@IMSoP所指出的, __getStatic()
仅在没有名称被调用的方法时才被调用-不仅是在没有名称静态方法的情况下也是如此。
因此,允许诸如CheckClass::forActive->sites()
调用的变通办法是为所有非静态方法名称赋予一个前缀,例如'_',并具有一个魔术方法__call()
来添加该前缀。
这意味着,如果我做CheckClass::forActive()
方法forActive()
不存在,所以__getStatic()
将被调用,将创建对象的实例,并尝试调用所需的方法。 但是该方法不存在,因为我们已经为其添加了前缀,因此PHP将调用__call()
魔术方法,该方法将添加前缀并调用带前缀的方法。
所以这两个函数是:
public static function __callStatic($method, $args)
{
$instance = new self;
return call_user_func_array(array($instance, $method), $args);
}
public static function __call($method, $args)
{
$method = 'prefix_' . $method;
return call_user_func_array(array($instance, $method), $args);
}
// Then all our method names need to be prefixed, like so:-
public static function prefix_SomeMethod($method, $args)
{
// Do something
return $this;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.