2017-02-20 78 views
0

我的問題是基於Data Viewer with Laravel 5.3 and Vue.js此代碼的工作原理和原理?

這傢伙創建一個DataViewer的特點和它的代碼類似於以下內容:

trait DataViewer 
{ 
    // $query should be a Query Builder 
    public function scopePaginateAndOrder($query) 
    { 
     // Validation ... 

     // Where, Pagination, Order etc ... 
     return $query->where('foo', 'like', 'bar'); 
    } 
} 

現在你可以使用這個特質在任何雄辯模型添加搜索功能。

class Customer extends Model 
{ 
    use DataViewer; 
} 

一切平常的東西,沒有什麼特別的... 但後來有一些「神奇」餘did't PHP中呢。

在控制器他做類似

$model = App\Customer::paginateAndOrder(); 

最後的代碼片段確實有很多方面我無法理解。

  1. 我爲什麼不能把這種非靜態方法使用::一個靜態方法呢?
  2. 爲什麼我可以從方法名稱中省略範圍
  3. 我不必將Query Builder對象作爲參數傳遞。那麼特質如何「知道」我想要分頁/訂購的型號

感謝您的幫助!

+0

'我不必將查詢生成器對象作爲參數傳遞,'//查詢應該是查詢生成器'是不好的做法(應該/可以/ ...)。爲什麼函數不是這樣的:'public function scopePaginateAndOrder(QueryBuilder $ query = null)'?在'1.'上,它會在php'嚴格標準:非靜態方法'中拋出一個註釋/警告,但是這個方法將被調用。用'2'來表示什麼意思? – JustOnUnderMillions

+0

順便說一句:一旦你談到'scopePaginateAndOrder'那麼關於'paginateAndOrder',就會有2個diff。方法調用,不一樣。所以當你嘗試調用scopePaginateAndOrder()時,你不能忽略'範圍'。你的邏輯中出現其他問題。 – JustOnUnderMillions

+0

好吧,不是鍵入提示參數確實是一個不好的做法,我只是從上面的鏈接視頻做了一個複製和粘貼。是的,我必須使用paginateAndOrder()INSTEAD scopePaginateAndOrder(),否則它會拋出一個異常 – Qobus

回答

1

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()作爲實例方法。

(不包括incrementdecrement)模型上的__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通過。

希望這會有所幫助!

1

這是Laravel的魔力..不是php。

Laravel利用做什麼用magic functions

  1. 知道我爲什麼能稱之爲一個靜態方法使用方式::非靜態方法?

我只會列表中有兩個在這裏__call()__callStatic(),這些功能是,當你調用分別不存在非靜態的靜態函數調用..

所以Illuminate\Database\Eloquent\Model這是超類所有型號都這樣做,請檢查這個link

  1. 爲什麼我可以從方法名稱中省略範圍?

只需Laravel允許省略代表它做什麼函數名的前綴。例如。在你的情況下前綴scope ..並不斷添加前綴到特定的順序,直到它找到它。 如果您想仔細查看,請閱讀code

  • 我不必須通過查詢生成器對象作爲參數。那麼,如何特質「知道」上的模型,我想分頁/訂單
  • 我相信這是由於Laravel IoC容器和dependcy注射..

    注:Q3需要更多的研究來請務必當&如何注射。