Laravel很好地利用了PHP的一些神奇方法,特別是在這種情況下__call()
和__callStatic
。
http://php.net/manual/en/language.oop5.overloading.php#object.callstatic
隨着callStatic
,如果一個靜態方法調用時或者不存在,或者是不可訪問的,則呼叫將被委派給該類別的__callStatic()
方法(如果有的話)。 __call()
和實例方法也是如此。
如果您在Illuminate\Database\Eloquent\Model
看,你會發現:
/**
* Handle dynamic method calls into the model.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement'])) {
return call_user_func_array([$this, $method], $parameters);
}
$query = $this->newQuery();
return call_user_func_array([$query, $method], $parameters);
}
/**
* 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);
}
在上面,如果__callStatic
被調用,然後它會創建模型的實例new
並嘗試調用該實例的方法,所以當您撥打App\Customer::paginateAndOrder()
時,它會嘗試撥打paginateAndOrder()
作爲實例方法。
(不包括increment
和decrement
)模型上的__call()
方法將嘗試在Illuminate\Database\Eloquent\Builder
上調用該方法。 Builder
則有它自己的__call()
方法已在它下面:
if (method_exists($this->model, $scope = 'scope' . ucfirst($method))) {
return $this->callScope([$this->model, $scope], $parameters);
}
callScope
然後只需調用實際scopePaginateAndOrder
並傳遞Builder
通過。
希望這會有所幫助!
'我不必將查詢生成器對象作爲參數傳遞,'//查詢應該是查詢生成器'是不好的做法(應該/可以/ ...)。爲什麼函數不是這樣的:'public function scopePaginateAndOrder(QueryBuilder $ query = null)'?在'1.'上,它會在php'嚴格標準:非靜態方法'中拋出一個註釋/警告,但是這個方法將被調用。用'2'來表示什麼意思? – JustOnUnderMillions
順便說一句:一旦你談到'scopePaginateAndOrder'那麼關於'paginateAndOrder',就會有2個diff。方法調用,不一樣。所以當你嘗試調用scopePaginateAndOrder()時,你不能忽略'範圍'。你的邏輯中出現其他問題。 – JustOnUnderMillions
好吧,不是鍵入提示參數確實是一個不好的做法,我只是從上面的鏈接視頻做了一個複製和粘貼。是的,我必須使用paginateAndOrder()INSTEAD scopePaginateAndOrder(),否則它會拋出一個異常 – Qobus