這篇文章主要介紹了Laravel Eloquent的使用技巧有哪些,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
目前成都創(chuàng)新互聯(lián)已為1000多家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站托管運(yùn)營(yíng)、企業(yè)網(wǎng)站設(shè)計(jì)、隨州網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶(hù)導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶(hù)和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
Eloquent ORM 看起來(lái)是一個(gè)簡(jiǎn)單的機(jī)制,但是在底層,有很多半隱藏的函數(shù)和鮮為人知的方式來(lái)實(shí)現(xiàn)更多功能
要代替以下實(shí)現(xiàn):
$article = Article::find($article_id); $article->read_count++; $article->save();
你可以這樣做:
$article = Article::find($article_id); $article->increment('read_count');
以下這些方法也可以實(shí)現(xiàn):
Article::find($article_id)->increment('read_count'); Article::find($article_id)->increment('read_count', 10); // +10 Product::find($produce_id)->decrement('stock'); // -1
Eloquent 有相當(dāng)一部分函數(shù)可以把兩個(gè)方法結(jié)合在一起使用, 例如 『 請(qǐng)先執(zhí)行 X 方法, X 方法執(zhí)行不成功則執(zhí)行 Y 方法 』。
實(shí)例 1 -- findOrFail()
:
要替代以下代碼的實(shí)現(xiàn):
$user = User::find($id); if (!$user) { abort (404); }
你可以這樣寫(xiě):
$user = User::findOrFail($id);
實(shí)例 2 -- firstOrCreate()
:
要替代以下代碼的實(shí)現(xiàn):
$user = User::where('email', $email)->first(); if (!$user) { User::create([ 'email' => $email ]); }
這樣寫(xiě)就可以了:
$user = User::firstOrCreate(['email' => $email]);
在一個(gè) Eloquent 模型中,有個(gè)神奇的地方,叫 boot()
,在那里,你可以覆蓋默認(rèn)的行為:
class User extends Model { public static function boot() { parent::boot(); static::updating(function($model) { // 寫(xiě)點(diǎn)日志啥的 // 覆蓋一些屬性,類(lèi)似這樣 $model->something = transform($something); }); } }
在創(chuàng)建模型對(duì)象時(shí)設(shè)置某些字段的值,大概是最受歡迎的例子之一了。 一起來(lái)看看在創(chuàng)建模型對(duì)象時(shí),你想要生成 UUID 字段 該怎么做。
public static function boot() { parent::boot(); self::creating(function ($model) { $model->uuid = (string)Uuid::generate(); }); }
定義關(guān)聯(lián)關(guān)系的一般方式:
public function users() { return $this->hasMany('App\User'); }
你知道嗎?也可以在上面的基礎(chǔ)上增加 where
或者 orderBy
?\
舉個(gè)例子,如果你想關(guān)聯(lián)某些類(lèi)型的用戶(hù),同時(shí)使用 email 字段排序,你可以這樣做:
public function approvedUsers() { return $this->hasMany('App\User')->where('approved', 1)->orderBy('email'); }
Eloquent模型有些參數(shù),使用類(lèi)的屬性形式。最常用是:
class User extends Model { protected $table = 'users'; protected $fillable = ['email', 'password']; // 可以被批量賦值字段,如 User::create() 新增時(shí),可使用字段 protected $dates = ['created_at', 'deleted_at']; // 需要被Carbon維護(hù)的字段名 protected $appends = ['field1', 'field2']; // json返回時(shí),附加的字段 }
不只這些,還有:
protected $primaryKey = 'uuid'; // 更換主鍵 public $incrementing = false; // 設(shè)置 不自增長(zhǎng) protected $perPage = 25; // 定義分頁(yè)每頁(yè)顯示數(shù)量(默認(rèn)15) const CREATED_AT = 'created_at'; const UPDATED_AT = 'updated_at'; //重寫(xiě) 時(shí)間字段名 public $timestamps = false; // 設(shè)置不需要維護(hù)時(shí)間字段
還有更多,我只列出了一些有意思的特性,具體參考文檔 abstract Model class 了解所有特性.
所有人都知道 find()
方法,對(duì)吧?
$user = User::find(1);
我十分意外竟然很少人知道這個(gè)方法可以接受多個(gè) ID 的數(shù)組作為參數(shù):
$users = User::find([1,2,3]);
有一種優(yōu)雅的方式能將這種代碼:
$users = User::where('approved', 1)->get();
轉(zhuǎn)換成這種:
$users = User::whereApproved(1)->get();
對(duì),你沒(méi)有看錯(cuò),使用字段名作為后綴添加到 where
后面,它就能通過(guò)魔術(shù)方法運(yùn)行了。
另外,在 Eloquent 里也有些和時(shí)間相關(guān)的預(yù)定義方法:
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'));
一個(gè)復(fù)雜一點(diǎn)的「技巧」。你想對(duì)論壇話(huà)題按最新發(fā)布的帖子來(lái)排序?論壇中最新更新的主題在最前面是很常見(jiàn)的需求,對(duì)吧?
首先,為主題的最新帖子定義一個(gè)單獨(dú)的關(guān)系:
public function latestPost() { return $this->hasOne(\App\Post::class)->latest(); }
然后,在控制器中,我們可以實(shí)現(xiàn)這個(gè)「魔法」:
$users = Topic::with('latestPost')->get()->sortByDesc('latestPost.created_at');
很多人都喜歡使用"if-else"來(lái)寫(xiě)查詢(xún)條件,像這樣:
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')); });
它可能看上去不是很優(yōu)雅,但它強(qiáng)大的功能是傳遞參數(shù):
$query = User::query(); $query->when(request('role', false), function ($q, $role) { return $q->where('role_id', $role); }); $authors = $query->get();
假設(shè)現(xiàn)在有種情況是要顯示文章的作者,然后模板代碼是:
{{ $post->author->name }}
但是如果作者的信息被刪除或者因?yàn)槟承┰驔](méi)有被設(shè)置。代碼會(huì)返回一個(gè)錯(cuò)誤,諸如 "property of non-object"。
當(dāng)然你可以這樣處理:
{{ $post->author->name ?? '' }}
你可以通過(guò) Eloquent 關(guān)系這樣做:
public function author() { return $this->belongsTo('App\Author')->withDefault(); }
在此示例中,如果文字沒(méi)有作者的信息, author()
會(huì)返回一個(gè)空的 App\Author
模型對(duì)象。
再者,我們也可以給默認(rèn)的模型對(duì)象里面的屬性賦默認(rèn)值。
public function author() { return $this->belongsTo('App\Author')->withDefault([ 'name' => 'Guest Author' ]); }
想象一下你有這樣的代碼:
function getFullNameAttribute() { return $this->attributes['first_name'] . ' ' . $this->attributes['last_name']; }
現(xiàn)在,你想要通過(guò) "full_name" 進(jìn)行排序? 發(fā)現(xiàn)是沒(méi)有效果的:
$clients = Client::orderBy('full_name')->get(); //沒(méi)有效果
解決辦法很簡(jiǎn)單.我們需要在獲取結(jié)果后對(duì)結(jié)果進(jìn)行排序.
$clients = Client::get()->sortBy('full_name'); // 成功!
注意的是方法名稱(chēng)是不相同的 -- 它不是orderBy,而是sortBy
如果你想要 User::all()
總是按照 name
字段來(lái)排序呢? 你可以給它分配一個(gè)全局作用域。讓我們回到 boot()
這個(gè)我們?cè)谏衔奶岬竭^(guò)的方法:
protected static function boot() { parent::boot(); // 按照 name 正序排序 static::addGlobalScope('order', function (Builder $builder) { $builder->orderBy('name', 'asc'); }); }
擴(kuò)展閱讀 查詢(xún)作用域 。
有時(shí)候,我們需要在 Eloquent 語(yǔ)句中添加原生查詢(xún)。 幸運(yùn)的是,確實(shí)有這樣的方法。
// 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();
很簡(jiǎn)單。說(shuō)明不是很深入,下面是復(fù)制數(shù)據(jù)庫(kù)實(shí)體(一條數(shù)據(jù))的最佳方法:
$task = Tasks::find(1); $newTask = $task->replicate(); $newTask->save();
與 Eloquent 不完全相關(guān),它更多的關(guān)于 Collection (集合),但是對(duì)于處理大數(shù)據(jù)集合,仍然是很有用的。你可以使用 chunk() 將這些數(shù)據(jù)分割成小數(shù)據(jù)塊
修改前:
$users = User::all(); foreach ($users as $user) { // ...
你可以這樣做:
User::chunk(100, function ($users) { foreach ($users as $user) { // ... } });
我們都知道Artisan命令:
php artisan make:model Company
但是,你知道有三個(gè)有用的標(biāo)記可以為模型生成相關(guān)文件嗎?
php artisan make:model Company -mcr
-m 將創(chuàng)建一個(gè)遷移文件
-c 將創(chuàng)建一個(gè)控制器
-r 表示控制器應(yīng)該是一個(gè)資源控制器
你知道 ->save()
方法可以接受參數(shù)嗎? 我們可以通過(guò)傳入?yún)?shù)阻止它的默認(rèn)行為:更新 updated_at
的值為當(dāng)前時(shí)間戳。
$product = Product::find($id); $product->updated_at = '2019-01-01 10:00:00'; $product->save(['timestamps' => false]);
這樣,我們成功在 save
時(shí)指定了 updated_at
的值。
你是否想知道這段代碼實(shí)際上返回什么?
$result = $products->whereNull('category_id')->update(['category_id' => 2]);
我是說(shuō),更新操作是在數(shù)據(jù)庫(kù)中執(zhí)行的,但 $result
會(huì)包含什么?
答案是受影響的行。 因此如果你想檢查多少行受影響, 你不需要額外調(diào)用其他任何內(nèi)容 -- update()
方法會(huì)給你返回此數(shù)字。
如果你有個(gè) and
和 or
混合的 SQL 查詢(xún),像這樣子的:
... WHERE (gender = 'Male' and age >= 18) or (gender = 'Female' and age >= 65)
怎么用 Eloquent 來(lái)翻譯它呢? 下面是一種錯(cuò)誤的方式:
$q->where('gender', 'Male'); $q->orWhere('age', '>=', 18); $q->where('gender', 'Female'); $q->orWhere('age', '>=', 65);
順序就沒(méi)對(duì)。正確的打開(kāi)方式稍微復(fù)雜點(diǎn),使用閉包作為子查詢(xún):
$q->where(function ($query) { $query->where('gender', 'Male') ->where('age', '>=', 18); })->orWhere(function($query) { $query->where('gender', 'Female') ->where('age', '>=', 65); })
終于,你可以傳遞陣列參數(shù)給 orWhere()
。平常的方式:
$q->where('a', 1); $q->orWhere('b', 2); $q->orWhere('c', 3);
你可以這樣做:
$q->where('a', 1); $q->orWhere(['b' => 2, 'c' => 3]);
我很確定還有更多隱藏的秘訣,但我希望至少上面的其中一些對(duì)你來(lái)說(shuō)是新的。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Laravel Eloquent的使用技巧有哪些”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!
分享文章:LaravelEloquent的使用技巧有哪些
網(wǎng)站地址:http://muchs.cn/article0/jeheoo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、靜態(tài)網(wǎng)站、網(wǎng)站收錄、響應(yīng)式網(wǎng)站、定制網(wǎng)站、面包屑導(dǎo)航
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)