摘要:從屬關(guān)聯(lián)關(guān)系更新關(guān)聯(lián)使用方法,該方法會在子模型設(shè)置外鍵移除關(guān)聯(lián)的時候,使用方法。使得這項操作變得簡單,只需要添加包含關(guān)聯(lián)關(guān)系名稱的屬性到子模型即可觸發(fā)的所有關(guān)聯(lián)關(guān)系關(guān)聯(lián)關(guān)系更新時,所屬模型將也會更新其值
Laravel中Eloquent ORM 關(guān)聯(lián)關(guān)系的操作 關(guān)聯(lián)數(shù)據(jù) 定義關(guān)聯(lián)關(guān)系
一對一
hasOne("AppPhone"); // 外鍵應(yīng)該在父級上有一個與之匹配的id(或者自定義 $primaryKey) // return $this->hasOne("AppPhone", "foreign_key"); // 用User的local_key,匹配Phone的foreign_key // return $this->hasOne("AppPhone", "foreign_key", "local_key"); } } $phone = User::find(1)->phone; // 獲取用戶的手機模型
相對的關(guān)聯(lián)
belongsTo("AppUser"); // return $this->belongsTo("AppUser", "foreign_key"); // return $this->belongsTo("AppUser", "foreign_key", "other_key"); } } $user = Phone::find(1)->user; // 查詢phone的id=1對應(yīng)的user $user = Phone::where("number","188**")->first()->user; // 查詢電話為188的用戶
一對多
class User extends Model{ // 獲取文章 public function article() { return $this->hasMany("AppComment"); // return $this->hasMany("AppComment", "foreign_key"); // return $this->hasMany("AppComment", "foreign_key", "local_key"); } } $articles = User::find(1)->article; // 返回 userid為1 的所有文章 $article = User::find(1)->article()->where("title", "aa")->first(); // 返回某一篇
一對多(逆向)
class Article extends Model{ public function user() { return $this->belongsTo("AppUser"); // return $this->belongsTo("AppPost", "foreign_key"); // return $this->belongsTo("AppPost", "foreign_key", "other_key"); } } $user = Article::find($id)->user; // 返回文章的作者
多對多
需要三張數(shù)據(jù)表:users、roles 和 role_user,
role_user 表為關(guān)系表,默認按照關(guān)聯(lián)模型名的字母順序命名,并且包含 user_id 和 role_id 兩個列。
class User extends Model{ /** * 用戶角色 */ public function roles() { //默認去role_user查找關(guān)系 // return $this->belongsToMany("AppRole"); return $this->belongsToMany("AppRole","role_users"); // 定義鍵值 // return $this->belongsToMany("AppRole", "user_roles", "user_id", "role_id"); } } $roles = User::find(1)->roles; // 返回 [{"id":1,"name":"SuperManager","pivot":{"user_id":1,"role_id":1}},{"id":2,"name":"Manager","pivot":{"user_id":1,"role_id":2}}] $roles = User::find(1)->roles()->orderBy("name")->get(); // 條件約束
注意我們獲取到的每一個 Role 模型都被自動賦上了 pivot 屬性。該屬性包含一個代表中間表的模型,并且可以像Eloquent 模型一樣使用。
如果你的 pivot 表包含額外的屬性,必須在定義關(guān)聯(lián)關(guān)系時進行指定:
return $this->belongsToMany("AppRole")->withPivot("column1", "column2");
如果你想要你的 pivot 表自動包含created_at 和 updated_at 時間戳,在關(guān)聯(lián)關(guān)系定義時使用 withTimestamps 方法:
return $this->belongsToMany("AppRole")->withTimestamps();
過中間表字段過濾關(guān)聯(lián)關(guān)系
return $this->belongsToMany("AppRole")->wherePivot("approved", 1); return $this->belongsToMany("AppRole")->wherePivotIn("priority", [1, 2]);關(guān)聯(lián)查詢
存在的關(guān)聯(lián)查詢
// 獲取所有至少有一條評論的文章... $posts = AppPost::has("comments")->get(); 你還可以指定操作符和數(shù)目來自定義查詢: // 獲取所有至少有三條評論的文章... $posts = Post::has("comments", ">=", 3)->get(); 還可以使用”.“來構(gòu)造嵌套 has 語句,例如,你要獲取所有至少有一條評論及投票的文章: // 獲取所有至少有一條評論獲得投票的文章... $posts = Post::has("comments.votes")->get(); 如果你需要更強大的功能,可以使用 whereHas 和 orWhereHas 方法將 where 條件放到 has 查詢上,這些方法允許你添加自定義條件約束到關(guān)聯(lián)關(guān)系條件約束,例如檢查一條評論的內(nèi)容: // 獲取所有至少有一條評論包含foo字樣的文章 $posts = Post::whereHas("comments", function ($query) { $query->where("content", "like", "foo%"); })->get();
無關(guān)聯(lián)結(jié)果查詢
// 獲取所有沒有評論的博客文章 $posts = AppPost::doesntHave("comments")->get(); // 檢查評論內(nèi)容: $posts = Post::whereDoesntHave("comments", function ($query) { $query->where("content", "like", "foo%"); })->get();
統(tǒng)計關(guān)聯(lián)模型
如果你想要在不加載關(guān)聯(lián)關(guān)系的情況下統(tǒng)計關(guān)聯(lián)結(jié)果數(shù)目,可以使用 withCount 方法,該方法會放置一個 {relation}_count 字段到結(jié)果模型
$posts = AppPost::withCount("comments")->get(); foreach ($posts as $post) { echo $post->comments_count; } // 添加約束條件到查詢一樣來添加多個關(guān)聯(lián)關(guān)系的“計數(shù)”: $posts = Post::withCount(["votes", "comments" => function ($query) { $query->where("content", "like", "foo%"); }])->get(); echo $posts[0]->votes_count; echo $posts[0]->comments_count; // 為關(guān)聯(lián)關(guān)系計數(shù)結(jié)果設(shè)置別名,從而允許在一個關(guān)聯(lián)關(guān)系上進行多維度計數(shù): $posts = Post::withCount([ "comments", "comments AS pending_comments" => function ($query) { $query->where("approved", false); } ])->get(); echo $posts[0]->comments_count; echo $posts[0]->pending_comments_count;渴求式加載
當(dāng)以屬性方式訪問數(shù)據(jù)庫關(guān)聯(lián)關(guān)系的時候,關(guān)聯(lián)關(guān)系數(shù)據(jù)是“懶惰式加載”的,這意味著關(guān)聯(lián)關(guān)系數(shù)據(jù)直到第一次訪問的時候才被加載。
$books = AppBook::all(); foreach ($books as $book) { echo $book->author->name; } // 該循環(huán)要執(zhí)行26次查詢:1次是獲取書本身,剩下的25次查詢是為每一本書獲取其作者。
$books = AppBook::with("author")->get(); foreach ($books as $book) { echo $book->author->name; } // 在該操作中,只執(zhí)行兩次查詢即可: // select * from books // select * from authors where id in (1, 2, 3, 4, 5, ...)
渴求式加載多個關(guān)聯(lián)關(guān)系
$books = AppBook::with("author", "publisher")->get();
嵌套的渴求式加載
// 加載所有書的作者及所有作者的個人聯(lián)系方式: $books = AppBook::with("author.contacts")->get();
帶條件約束的渴求式加載
// 加載 title 包含 first 的文章 $users = AppUser::with(["posts" => function ($query) { $query->where("title", "like", "%first%"); }])->get(); // 加載按created_at倒序的的文章 $users = AppUser::with(["posts" => function ($query) { $query->orderBy("created_at", "desc"); }])->get();
懶惰渴求式加載
$books = AppBook::all(); if ($someCondition) { $books->load("author", "publisher"); } // 設(shè)置更多的查詢條件到渴求式加載查詢上,可以傳遞一個閉包到 load 方法: $books->load(["author" => function ($query) { $query->orderBy("published_date", "asc"); }]);插入 & 更新關(guān)聯(lián)模型
save 方法
$comment = new AppComment(["message" => "A new comment."]); $post = AppPost::find(1); $post->comments()->save($comment); // save 方法會自動添加 post_id 值到新的Comment 模型。
保存多個關(guān)聯(lián)模型,可以使用 saveMany 方法:
$post = AppPost::find(1); $post->comments()->saveMany([ new AppComment(["message" => "A new comment."]), new AppComment(["message" => "Another comment."]), ]);
create方法
該方法接收屬性數(shù)組、創(chuàng)建模型、然后插入數(shù)據(jù)庫。save 和 create 的不同之處在于 save 接收整個 Eloquent 模型實例而 create 接收原生 PHP 數(shù)組:
使用 create 方法之前確保先瀏覽屬性批量賦值文檔。
$post = AppPost::find(1); $comment = $post->comments()->create([ "message" => "A new comment.", ]);
從屬關(guān)聯(lián)關(guān)系
更新 belongsTo 關(guān)聯(lián), 使用associate 方法,該方法會在子模型設(shè)置外鍵:
$account = AppAccount::find(10); $user->account()->associate($account); $user->save();
移除 belongsTo 關(guān)聯(lián)的時候,使用dissociate 方法。該方法會設(shè)置關(guān)聯(lián)關(guān)系的外鍵為 null:
$user->account()->dissociate(); $user->save();多對多關(guān)聯(lián) 的 附加/分離
假定一個用戶可能有多個角色,同時一個角色屬于多個用戶,要通過在連接模型的中間表中插入記錄附加角色到用戶上,可以使用 attach 方法:
$user = AppUser::find(1); $user->roles()->attach($roleId); // 以數(shù)組形式傳遞額外被插入數(shù)據(jù)到中間表: $user->roles()->attach($roleId, ["expires" => $expires]);
移除一個多對多關(guān)聯(lián)記錄,使用 detach 方法。detach 方法將會從中間表中移除相應(yīng)的記錄;
但是,兩個模型在數(shù)據(jù)庫中都保持不變:
// 從指定用戶中移除角色... $user->roles()->detach($roleId); // 從指定用戶移除所有角色... $user->roles()->detach();
接收數(shù)組形式的 ID 作為輸入:
$user = AppUser::find(1); $user->roles()->detach([1, 2, 3]); $user->roles()->attach([1 => ["expires" => $expires], 2, 3]);
同步關(guān)聯(lián)
sync 方法接收數(shù)組形式的 ID 并將其放置到中間表
// 任何不在該數(shù)組中的 ID 對應(yīng)記錄將會從中間表中移除 $user->roles()->sync([1, 2, 3]); // 還可以和 ID 一起傳遞額外的中間表值: $user->roles()->sync([1 => ["expires" => true], 2, 3]); // 如果不想要脫離存在的ID,可以使用syncWithoutDetaching 方法: $user->roles()->syncWithoutDetaching([1, 2, 3]);
切換關(guān)聯(lián)
// 如果當(dāng)前沒有附加,則附加:如果給定ID當(dāng)前被附加,則取消附加 $user->roles()->toggle([1, 2, 3]);
在中間表上保存額外數(shù)據(jù)
// 接收額外中間表屬性數(shù)組作為第二個參數(shù): AppUser::find(1)->roles()->save($role, ["expires" => $expires]);
更新中間表記錄 updateExistingPivot
// 更新中間表中已存在的行,接收中間記錄外鍵和屬性數(shù)組進行更新 $user = AppUser::find(1); $user->roles()->updateExistingPivot($roleId, $attributes);觸發(fā)父級時間戳
當(dāng)一個模型屬于另外一個時,子模型更新時父模型的時間戳也被更新將很有用
例如,當(dāng) Comment 模型被更新時,你可能想要”觸發(fā)“更新其所屬模型 Post 的updated_at 時間戳。Eloquent 使得這項操作變得簡單,只需要添加包含關(guān)聯(lián)關(guān)系名稱的 touches 屬性到子模型即可:
class Comment extends Model{ // 觸發(fā)的所有關(guān)聯(lián)關(guān)系 protected $touches = ["post"]; // 關(guān)聯(lián)關(guān)系 public function post() { return $this->belongsTo("AppPost"); } }
更新 Comment 時,所屬模型 Post 將也會更新其 updated_at 值
$comment = AppComment::find(1); $comment->text = "Edit to this comment!"; $comment->save();
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/30780.html
摘要:是什么是一個,全稱為,翻譯為對象關(guān)系映射如果只把它當(dāng)成數(shù)組庫抽象層那就太小看它了。所謂對象,就是本文所說的模型對象關(guān)系映射,即為模型間關(guān)系。至此,深入理解系列文章到此結(jié)束。 原文發(fā)表在我的個人網(wǎng)站:深入理解 Laravel Eloquent(三)——模型間關(guān)系(關(guān)聯(lián)) 在本篇文章中,我將跟大家一起學(xué)習(xí) Eloquent 中最復(fù)雜也是最難理解的部分——模型間關(guān)系。官方英文文檔中...
摘要:關(guān)聯(lián)關(guān)系查詢在中,所有的關(guān)系都是使用函數(shù)定義的,可以在不執(zhí)行關(guān)聯(lián)查詢的情況下獲取關(guān)聯(lián)的實例。 關(guān)聯(lián)關(guān)系 One To One 假設(shè)User模型關(guān)聯(lián)了Phone模型,要定義這樣一個關(guān)聯(lián),需要在User模型中定義一個phone方法,該方法返回一個hasOne方法定義的關(guān)聯(lián)
摘要:軟刪除當(dāng)模型被軟刪除后,它們并沒有真的從數(shù)據(jù)庫刪除,而是在模型上設(shè)置一個屬性并插入數(shù)據(jù)庫,如果模型有一個非空值,那么該模型已經(jīng)被軟刪除了。 Laravel 中Eloquent ORM 相關(guān)操作 定義 操作 獲?。ú樵儯?獲取集合,(查詢列表) 返回值是 IlluminateDatabaseEloquentCollection 的一個實例 獲取所有的數(shù)據(jù) use AppUser; $us...
摘要:在中要想在數(shù)據(jù)庫事務(wù)中運行一組操作,則可以在中使用方法。如果在事務(wù)的閉包內(nèi)拋出異常,事務(wù)將會被自動還原。 Description 在Laravel中要想在數(shù)據(jù)庫事務(wù)中運行一組操作,則可以在 DB facade 中使用 transaction 方法。如果在事務(wù)的閉包內(nèi)拋出異常,事務(wù)將會被自動還原。如果閉包運行成功,事務(wù)將被自動提交。你不需要擔(dān)心在使用 transaction 方法時還需要...
摘要:模型資料庫遷移儲存紀錄在及之間建立關(guān)聯(lián)在及之間建立關(guān)聯(lián)取得紀錄取得取得一對多關(guān)聯(lián)示例細節(jié)在此示例中,我們有兩個模型小偷和車,和兩張表和。業(yè)務(wù)規(guī)則小偷可以偷走多輛車。關(guān)系圖關(guān)聯(lián)詳情關(guān)聯(lián)表應(yīng)該保存駕駛員和汽車。 showImg(https://segmentfault.com/img/remote/1460000016043938); 一張 Laravel’s Eloquent ORM 5...
閱讀 2273·2021-11-25 09:43
閱讀 3147·2021-10-14 09:42
閱讀 3496·2021-10-12 10:12
閱讀 1580·2021-09-07 10:17
閱讀 1911·2019-08-30 15:54
閱讀 3196·2019-08-30 15:54
閱讀 1569·2019-08-30 15:53
閱讀 1930·2019-08-29 11:21