鍍金池/ 問答/PHP  網絡安全/ Laravel 里為什么可以用Model::where(),卻不能用Model:

Laravel 里為什么可以用Model::where(),卻不能用Model::getTable()

我理解是:

調用 Model::where()
Model 里沒有靜態(tài)方法 where(),于是會觸發(fā) __callStatic(),
__callStatic() 中會試圖去調用實例方法 where()Model 也沒有 where(),于是觸發(fā) __call()
__call() 中實例化 \Illuminate\Database\Eloquent\Builder,然后調用 Builder 的實例方法 where()。

調用 Model::getTable()
Model 里沒有靜態(tài)方法 getTable(),于是會觸發(fā) __callStatic(),
__callStatic() 中會試圖去調用實例方法 getTable(),Model 有定義,所以應該直接調用getTable()。

但是卻報錯

Non-static method Illuminate\Database\Eloquent\Model::getTable() should not be called statically, assuming $this from incompatible context


查了一下錯誤的原因,鳥哥在這篇文章解釋了,PHP 的 Calling Scope


問題是,那為什么可以用 Model::where()?

回答
編輯回答
失魂人

getTable方法在Model里面定義的是非靜態(tài)方法

public function getTable()

直接調用PHP就會跳出了一個Strict錯誤。

而調用Model::where的時候,由于where沒有在Model里面定義,PHP會找Model里面的__callStatic,將where方法代理到目標類里面。

Model的__callStatic方法注釋也解釋的很清楚

/**
 * Handle dynamic static method calls into the method.
 *
 * @param  string  $method
 * @param  array  $parameters
 * @return mixed
 */
public static function __callStatic($method, $parameters)
{
    $instance = new static;

    return call_user_func_array([$instance, $method], $parameters);
}
2018年5月2日 21:45
編輯回答
莫小染

因為getTable 不是靜態(tài)的方法
public function getTable()
所以報

Non-static method Illuminate\Database\Eloquent\Model::getTable() should not be called statically, assuming $this from incompatible context

又因為,php 在檢查類的方法存不存在時不會考慮是否靜態(tài)類.所以又不會進__callStatic.

又看了一下,你的問題是為什么可以用 model::where ? 可以用modle::where的原因是 model類里沒有一個 where的方法所以進了 __callStatic. 請用getTablemodle里有這個類。所以進不了__callStatic.

回頭去看了一下鳥個說的那個文章, 下面是文章的例子。https://segmentfault.com/q/10...

<?php

class A
{
    public function __call($name, $args)
    {
        echo "NO\n";
    }

    public static function __callStatic($name, $args)
    {
        echo "YES\n";
    }
}

class B extends A
{
    public function test()
    {
        A::test();
    }

    public static function stest()
    {
        A::test();
    }
}

A::test();

$b = new B();
$b->test();

B::stest();

他有三個輸出

A::test();

$b = new B();
$b->test();

B::stest();

需要看清楚的是第一個用的是 A::test() .

2018年1月15日 07:49
編輯回答
拮據

因為我們定義的 Model 直接繼承于 Eloquent/Model

鳥哥在博客中這樣說

因為你在一個有 calling scope 的上下文中采用”靜態(tài)的形式”調用了一個類的非靜態(tài)方法所致.

我的理解是你在一個定義了 __callStatic 的類中(如 User)調用非靜態(tài)方法 User::getTable。

where 等方法是在 Builder 類中的,Eloquent/Model 不直接繼承 Builder。

2017年10月18日 11:27
編輯回答
初念

在Model中,where方法是不存在的,而getTable方法卻是存在的。之所以這么說,是php因為兼容性的考慮,在檢查方法是否存在的時候,并不會去檢查是不是靜態(tài)方法,只要方法存在,不管是靜態(tài)還是非靜態(tài),都認為是方法存在的,因此就不會調用__callStatic方法了。

這也就造成了調用Model::where的時候,由于where方法是在Illuminate\Database\Eloquent\Builder中定義的,__call將該方法的調用代理到了Builder上,因此可以調用。而getTable方法,則因為是Model中的實例方法,做方法存在性判斷的時候發(fā)現(xiàn)方法有了,就不會去調用__callStatic,直接對該方法進行靜態(tài)調用,所有就拋出了

Non-static method IlluminateDatabaseEloquentModel::getTable() should not be called statically, assuming $this from incompatible context

2017年6月23日 05:40