好吧,我們來談談查詢範圍。它們非常棒,毫無疑問它們使查詢更容易閱讀。但我討厭他們一件事:魔法。當你與一個並非每個人都是後端開發人員的團隊合作時,這可能會讓他們的生活變得悲慘。當然,您可以添加 PHPDocs,但總是有一些神奇的事情發生。如果您以前從未使用過瞄準鏡,不用擔心,請堅持住。
考慮這段程式碼:
use App\Models\User; $users = User::query() ->where('votes', '>', 100); ->where('active', 1); ->orderBy('created_at') ->get();
這是您通常編寫查詢的方式。但是當查詢變得太複雜或難以閱讀時,您可以將它們抽像到範圍中:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class User extends Model { public function scopePopular(Builder $query): void { $query->where('votes', '>', 100); } public function scopeActive(Builder $query): void { $query->where('active', 1); } }
現在你可以這樣做:
$users = User::query() ->popular() ->active() ->orderBy('created_at') ->get();
讀起來好多了,對吧?我知道。但問題是,你沒有得到任何自動完成功能。這對 IDE 來說是黑暗魔法。由於作用域在執行時間解析並以作用域為前綴,因此除非您提供協助,否則您的 IDE 無法了解它們。
一種方法是透過 PHPDocs,如下所示:
/** * @method static Builder popular() * @method static Builder active() */ class User extends Model
範圍的另一個缺點?最常用的模型最終會徒勞地增加大量的模型。我喜歡瀏覽我的模型並立即看到關係和核心邏輯,而不是一堆查詢抽象。
蘇?我們是否會放棄範圍並繼續前進?嗯,這是一個選項,或者您可以使用自訂查詢產生器。
顧名思義,自訂查詢產生器可讓您將所有查詢抽象移至專用類別中。程式碼將以某種方式變得更有組織性。
讓我們建立一個新類別 UserQueryBuilder:
<?php namespace App\Eloquent\QueryBuilders; use App\Models\User; use Illuminate\Database\Eloquent\Builder; class UserQueryBuilder extends Builder { public function popular(): self { return $this->where('votes', '>', 100); } public function active(): self { return $this->where('active', 1); } }
建構器應該放在哪裡?沒有指南,但我個人喜歡將它們放在 app/Eloquent/QueryBuilders 中。
現在讓我們在使用者模型中使用這個建構器:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; class User extends Model { public function newEloquentBuilder($query): UserQueryBuilder { return new UserQueryBuilder($query); } // for type hints public static function query(): UserQueryBuilder { return parent::query(); } }
就像這樣,您現在可以這樣做:
$users = User::query() ->popular() ->active() ->orderBy('created_at') ->get();
工作原理完全相同,並且您可以獲得完全自動補全。另外,程式碼導航功能完美,可以帶您到您需要去的地方?
另一個很酷的事情是您可以根據需要動態解析查詢建構器。
public function newEloquentBuilder($query): UserQueryBuilder { if ($this->status === State::Pending) { return new PendingUserQueryBuilder($query); // extends UserQueryBuilder } return new UserQueryBuilder($query); }
這樣,當您可以按上下文(如狀態)對查詢進行分組時,您就可以避免使用一個大型查詢建構器。
瞄準鏡很酷,如果我只有 2-3 個,我會堅持使用它們。但當事情開始失控時,自訂查詢建構器就是最佳選擇。它們值得付出額外的努力,讓您的程式碼保持乾淨、有組織且易於維護?
以上是Laravel 跨範圍的自訂查詢建構器的詳細內容。更多資訊請關注PHP中文網其他相關文章!