常常在用 Eloquent 查詢的時候都會需要回頭追一些函式,
但 phpstorm 常常會認為有些呼叫鍊上的函式不存在,
其原因是因為大部分對 Eloquent/Builder 的呼叫都會透過 __Call
委託給 Query/Builder 執行。
所以大部分時候要查有哪些函式可以用,
往往是直接找 \Illuminate\Database\Query\Builder
這檔案即可。
大概翻了一下這個檔案,我發現我沒硬到能完整的講述整個檔案,
但重點提要還是可以的。
我一樣會從這檔案的 __call
講起,
不知道它的同學請去惡補一下 PHP 魔術函式
這檔案在開頭就引入了 Macroable 這個 trait。
進一步追蹤這個檔案的話(\Illuminate\Support\Traits\Macroable
),
會注意到它有一個 $macros
關聯陣列(以 function name 為 key;以 callable 為 value),
用來為引入這個 trait 的 class 動態擴充可執行的函式。
你可以試著在 AppServiceProvider 的 boot()
裡面這樣做:
底下為 Query/Builder 新增了一個,
一次可以新增好幾筆排序條件的,強化版 orderBy
。
其中 macro()
的參數分別是:
其中 Callable 的參數便是你在呼叫這個函式時需要傳入的參數,不多不少。
<?php
$keys = ['name', 'created_at'];
$sorts = ['asc', 'desc'];
Builder::macro('orderByMany', function ($keys, $sorts) {
$rules = array_combine($keys, $sorts);
foreach ($rules as $key => $rule) {
$this->orderBy($key, $rule);
}
});
根據 php 官方的介紹,
$this 通常會指向呼叫他的 method 所在的 Object。
所以因為如此,
在這個透過 macro 擴充的 function 之中呼叫 $this
,
也總是會指向一個 Class 是 Query/Builder 的物件。
所以才能透過它直接執行 orderBy
。
一般你在用 eloquent 串 sql 的時候,
如果是執行已經存在的函式那就直接執行沒問題。
但當你執行一個不存在的函式 ,
呼叫會首先被導到 __call
額外做處理。
首先它會檢查,你要執行的函式是不是透過 macro 擴充的,有則執行。
沒有就繼續檢查,你要執行的函式是不是以「where」作為開頭的,有則執行 dynamicWhere()
。
上面兩者都沒有,便會丟出一個 BadMethodCallException
。