Laravel Eloquent 必備的實用技巧
1. 遞增與遞減
要取代以下實作:
$article = Article::find($article_id); $article->read_count++; $article->save();
你可以這樣做:
$article = Article::find($article_id); $article->increment('read_count');
以下這些方法也可以實現:
Article::find($article_id)->increment('read_count'); Article::find($article_id)->increment('read_count', 10); // +10 Product::find($produce_id)->decrement('stock'); // -1
2. 先執行X 方法,X 方法執行不成功則執行Y 方法
Eloquent 有相當一部分函數可以把兩個方法結合在一起使用, 例如‘ 請先執行X 方法, X 方法執行不成功則執行Y 方法’。
實例1 -- findOrFail():
要取代以下程式碼的實作:
$user = User::find($id); if (!$user) { abort (404); }
你可以這樣寫:
$user = User::findOrFail($id);
實例2 -- firstOrCreate():
要取代以下程式碼的實作:
$user = User::where('email', $email)->first(); if (!$user) { User::create([ 'email' => $email ]); }
這樣寫就可以了:
$user = User::firstOrCreate(['email' => $email]);
3. 模型的boot() 方法
在一個Eloquent 模型中,有個神奇的地方,叫boot(),在那裡,你可以覆寫預設的行為:
class User extends Model { public static function boot() { parent::boot(); static::updating(function($model) { // 写点日志啥的 // 覆盖一些属性,类似这样 $model->something = transform($something); }); } }
在建立模型物件時設定某些欄位的值,大概是最受歡迎的例子之一了。一起來看看在建立模型物件時,你想要產生 UUID 欄位 該怎麼做。
public static function boot() { parent::boot(); self::creating(function ($model) { $model->uuid = (string)Uuid::generate(); }); }
4. 帶條件與排序的關聯關係
定義關聯關係的一般方式:
public function users() { return $this->hasMany('App\User'); }
你知道嗎?也可以在上面的基礎上增加where 或orderBy,
舉個例子,如果你想關聯某些類型的用戶,同時使用email 欄位排序,你可以這樣做:
public function approvedUsers() { return $this->hasMany('App\User')->where('approved', 1)->orderBy('email'); }
5. 模型特性:時間、追加等
Eloquent 模型有些參數,使用類別的屬性形式。最常用是:
class User extends Model { protected $table = 'users'; protected $fillable = ['email', 'password']; // 可以被批量赋值字段,如 User::create() 新增时,可使用字段 protected $dates = ['created_at', 'deleted_at']; // 需要被Carbon维护的字段名 protected $appends = ['field1', 'field2']; // json返回时,附加的字段 }
不只這些,還有:
protected $primaryKey = 'uuid'; // 更换主键 public $incrementing = false; // 设置 不自增长 protected $perPage = 25; // 定义分页每页显示数量(默认15) const CREATED_AT = 'created_at'; const UPDATED_AT = 'updated_at'; //重写 时间字段名 public $timestamps = false; // 设置不需要维护时间字段
還有更多,我只列出了一些有意思的特性,具體參考文檔abstract Model class 了解所有特性.
6. 透過ID 查詢多筆記錄
所有人都知道find() 方法,對吧?
$user = User::find(1);
我十分意外竟然很少人知道這個方法可以接受多個ID 的陣列作為參數:
$users = User::find([1,2,3]);
7. WhereX
#有一種優雅的方式能將這種程式碼:
$users = User::where('approved', 1)->get();
轉換成這種:
$users = User::whereApproved(1)->get();
對,你沒有看錯,使用字段名稱作為後綴添加到where 後面,它就能通過魔術方法運行了。
另外,在 Eloquent 裡也有些和時間相關的預定義方法:
User::whereDate('created_at', date('Y-m-d')); User::whereDay('created_at', date('d')); User::whereMonth('created_at', date('m')); User::whereYear('created_at', date('Y'));
8. 透過關係排序
一個複雜一點的「技巧」。你想對論壇話題依照最新發布的貼文來排序?論壇中最新更新的主題在最前面是很常見的需求,對吧?
首先,為主題的最新貼文定義一個單獨的關係:
public function latestPost() { return $this->hasOne(\App\Post::class)->latest(); }
然後,在控制器中,我們可以實現這個「魔法」:
$users = Topic::with('latestPost')->get()->sortByDesc('latestPost.created_at');
9. Eloquent::when() -- 不再使用if-else
很多人都喜歡使用"if-else"來寫查詢條件,像這樣:
if (request('filter_by') == 'likes') { $query->where('likes', '>', request('likes_amount', 0)); } if (request('filter_by') == 'date') { $query->orderBy('created_at', request('ordering_rule', 'desc')); }
有一種更好的方法-- 使用when()
$query = Author::query(); $query->when(request('filter_by') == 'likes', function ($q) { return $q->where('likes', '>', request('likes_amount', 0)); }); $query->when(request('filter_by') == 'date', function ($q) { return $q->orderBy('created_at', request('ordering_rule', 'desc')); });
它可能看起來不是很優雅,但它強大的功能是傳遞參數:
$query = User::query(); $query->when(request('role', false), function ($q, $role) { return $q->where('role_id', $role); }); $authors = $query->get();
10. BelongsTo 預設模型
#假如有一個Post 模型附屬於Author 模型,在Blade 模板裡可以寫作如下程式碼:
{{ $post->author->name }}
但是如果作者被刪除了,或者因為某些原因未設定?你就會得到一個錯誤訊息,類似「不存在的物件屬性」。
那麼,你可以這麼避免它:
{{ $post->author->name ?? '' }}
但是你可以在Eloquent 關係模型層級做到這種效果:
public function author() { return $this->belongsTo('App\Author')->withDefault(); }
這個例子中,如果貼文沒有作者的話,author() 關係方法會回傳一個空的App\Author 模型物件。
此外,我們也可以為預設模型指派一個預設的屬性值。
public function author() { return $this->belongsTo('App\Author')->withDefault([ 'name' => 'Guest Author' ]); }
11. 透過賦值函數進行排序
想像你有這樣的程式碼:
function getFullNameAttribute() { return $this->attributes['first_name'] . ' ' . $this->attributes['last_name']; }
現在,你想要透過"full_name" 進行排序? 發現是沒有效果的:
$clients = Client::orderBy('full_name')->get(); //没有效果
解決辦法很簡單.我們需要在取得結果後對結果進行排序.
$clients = Client::get()->sortBy('full_name'); // 成功!
注意的是方法名稱是不相同的-- 它不是orderBy,而是sortBy
12. 全域作用域下的預設排序
如果你想要User::all() 總是按照name 欄位來排序呢?你可以給它一個全域作用域。讓我們回到 boot() 這個我們在上文提到的方法:
protected static function boot() { parent::boot(); // 按照 name 正序排序 static::addGlobalScope('order', function (Builder $builder) { $builder->orderBy('name', 'asc'); }); }
擴充閱讀 查詢作用域 。
13. 原生查詢方法
有時候,我們需要在 Eloquent 語句中加入原生查詢。幸運的是,確實有這樣的方法。
// whereRaw $orders = DB::table('orders') ->whereRaw('price > IF(state = "TX", ?, 100)', [200]) ->get(); // havingRaw Product::groupBy('category_id')->havingRaw('COUNT(*) > 1')->get(); // orderByRaw User::where('created_at', '>', '2016-01-01') ->orderByRaw('(updated_at - created_at) desc') ->get();
14. 複製:複製一行的副本
很簡單。說明不是很深入,以下是複製資料庫實體(一條資料)的最佳方法:
$task = Tasks::find(1); $newTask = $task->replicate(); $newTask->save();
15. Chunk() 方法之大塊資料
與Eloquent 不完全相關,它更多的關於Collection (集合),但是對於處理大數據集合,仍然是很有用的。你可以使用chunk() 將這些資料分割成小資料塊
修改前:
$users = User::all(); foreach ($users as $user) { // ...
你可以這樣做:
User::chunk(100, function ($users) { foreach ($users as $user) { // ... } });
16. 建立模型的時候增加額外操作
我們都知道這條Artisan 命令:
php artisan make:model Company
但是你知道有三個十分有用的標誌符可用於生成模型相關文件
php artisan make:model Company -mcr
-m 創建遷移文件
-c 建立控制器檔案
-r 為控制器新增資源操作方法
17. 呼叫save 方法的時候指定updated_at
你知道 ->save() 方法可以接受参数吗? 我们可以通过传入参数阻止它的默认行为:更新 updated_at 的值为当前时间戳。
$product = Product::find($id); $product->updated_at = '2019-01-01 10:00:00'; $product->save(['timestamps' => false]);
这样,我们成功在 save 时指定了 updated_at 的值。
18. update() 的结果是什么?
你是否想知道这段代码实际上返回什么?
$result = $products->whereNull('category_id')->update(['category_id' => 2]);
我是说,更新操作是在数据库中执行的,但 $result 会包含什么?
答案是受影响的行。 因此如果你想检查多少行受影响, 你不需要额外调用其他任何内容 -- update() 方法会给你返回此数字。
19. 把括号转换成 Eloquent 查询
如果你有个 and 和 or 混合的 SQL 查询,像这样子的:
... WHERE (gender = 'Male' and age >= 18) or (gender = 'Female' and age >= 65)
怎么用 Eloquent 来翻译它呢? 下面是一种错误的方式:
$q->where('gender', 'Male'); $q->orWhere('age', '>=', 18); $q->where('gender', 'Female'); $q->orWhere('age', '>=', 65);
顺序就没对。正确的打开方式稍微复杂点,使用闭包作为子查询:
$q->where(function ($query) { $query->where('gender', 'Male') ->where('age', '>=', 18); })->orWhere(function($query) { $query->where('gender', 'Female') ->where('age', '>=', 65); })
20. 复数参数的 orWhere
终于,你可以传递阵列参数给 orWhere()。平常的方式:
$q->where('a', 1); $q->orWhere('b', 2); $q->orWhere('c', 3);
你可以这样做:
$q->where('a', 1); $q->orWhere(['b' => 2, 'c' => 3]);
更多laravel框架相关技术文章,请访问laravel教程栏目!
以上是Laravel Eloquent 必備的實用技巧的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Laravel通過簡化Web開發過程和提供強大功能脫穎而出。其優勢包括:1)簡潔的語法和強大的ORM系統,2)高效的路由和認證系統,3)豐富的第三方庫支持,使得開發者能專注於編寫優雅的代碼並提高開發效率。

laravelispredminandermanthandermanthandermanthandermanthermanderframework,設計Forserver-SideLogic,databasemagement,andapideplupment,thryitalsosupportsfortfortsfrontenddevelopmentwithbladeTemplates。

Laravel和Python在性能和可擴展性方面的表現各有優劣。 Laravel通過異步處理和隊列系統提升性能,但受PHP限制在高並發時可能有瓶頸;Python利用異步框架和強大的庫生態系統表現出色,但在多線程環境下受GIL影響。

Laravel適合團隊熟悉PHP且需功能豐富的項目,Python框架則視項目需求而定。 1.Laravel提供優雅語法和豐富功能,適合需要快速開發和靈活性的項目。 2.Django適合複雜應用,因其“電池包含”理念。 3.Flask適用於快速原型和小型項目,提供極大靈活性。

Laravel可以用於前端開發。 1)使用Blade模板引擎生成HTML。 2)集成Vite管理前端資源。 3)構建SPA、PWA或靜態網站。 4)結合路由、中間件和EloquentORM創建完整Web應用。

PHP和Laravel可用於構建高效的服務器端應用。 1.PHP是開源腳本語言,適用於Web開發。 2.Laravel提供路由、控制器、EloquentORM、Blade模板引擎等功能,簡化開發。 3.通過緩存、代碼優化和安全措施,提升應用性能和安全性。 4.測試和部署策略確保應用穩定運行。

Laravel和Python在學習曲線和易用性上的表現各有優劣。 Laravel適合快速開發Web應用,學習曲線相對平緩,但掌握高級功能需時間;Python語法簡潔,學習曲線平緩,但動態類型系統需謹慎。

Laravel在後端開發中的優勢包括:1)優雅的語法和EloquentORM簡化了開發流程;2)豐富的生態系統和活躍的社區支持;3)提高了開發效率和代碼質量。 Laravel的設計讓開發者能夠更高效地進行開發,並通過其強大的功能和工具提升代碼質量。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。