iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 13
0
自我挑戰組

花式PHP系列 第 14

Laravel:深入Query/Builder

Query/Builder

為什麼要講它?

常常在用 Eloquent 查詢的時候都會需要回頭追一些函式,
phpstorm 常常會認為有些呼叫鍊上的函式不存在,
其原因是因為大部分對 Eloquent/Builder 的呼叫都會透過 __Call 委託給 Query/Builder 執行。

所以大部分時候要查有哪些函式可以用,
往往是直接找 \Illuminate\Database\Query\Builder 這檔案即可。

文章取向

大概翻了一下這個檔案,我發現我沒硬到能完整的講述整個檔案,
但重點提要還是可以的。

我一樣會從這檔案的 __call 講起,
不知道它的同學請去惡補一下 PHP 魔術函式

Marcroable

這檔案在開頭就引入了 Macroable 這個 trait。

進一步追蹤這個檔案的話(\Illuminate\Support\Traits\Macroable),
會注意到它有一個 $macros 關聯陣列(以 function name 為 key;以 callable 為 value),
用來為引入這個 trait 的 class 動態擴充可執行的函式。

擴充 Query/Builder

你可以試著在 AppServiceProvider 的 boot() 裡面這樣做:

底下為 Query/Builder 新增了一個,
一次可以新增好幾筆排序條件的,強化版 orderBy

其中 macro() 的參數分別是:

  1. Function name
  2. Callable

其中 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);
    }
});

$this ???

根據 php 官方的介紹
$this 通常會指向呼叫他的 method 所在的 Object

所以因為如此,
在這個透過 macro 擴充的 function 之中呼叫 $this
也總是會指向一個 Class 是 Query/Builder 的物件

所以才能透過它直接執行 orderBy

__call

一般你在用 eloquent 串 sql 的時候,
如果是執行已經存在的函式那就直接執行沒問題。

但當你執行一個不存在的函式
呼叫會首先被導到 __call 額外做處理。

首先它會檢查,你要執行的函式是不是透過 macro 擴充的,有則執行。
沒有就繼續檢查,你要執行的函式是不是以「where」作為開頭的,有則執行 dynamicWhere()

上面兩者都沒有,便會丟出一個 BadMethodCallException


上一篇
Laravel:深入config:cache
下一篇
Laravel:深入Collection
系列文
花式PHP31

尚未有邦友留言

立即登入留言