[英]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.