三、深刻理解 Laravel Eloquent(三)——模型間關係(關聯)

深刻理解 Laravel Eloquent(三)——模型間關係(關聯)

在本篇文章中,我將跟你們一塊兒學習 Eloquent 中最複雜也是最難理解的部分——模型間關係。官方英文文檔中叫 Relationships,我的認爲翻譯成 「模型間關係」 比如今的 「關聯」 更好理解一點哈哈。php

Eloquent是什麼

Eloquent 是一個 ORM,全稱爲 Object Relational Mapping,翻譯爲 「對象關係映射」(若是隻把它當成 Database Abstraction Layer 數組庫抽象層那就過小看它了)。所謂 「對象」,就是本文所說的 「模型(Model)」;對象關係映射,即爲模型間關係。中文文檔: http://laravel-china.org/docs/eloquent#relationshipshtml

下面咱們開始一個一個地學習。laravel

一對一關係

顧名思義,這描述的是兩個模型之間一對一的關係。這種關係是不須要中間表的。web

假如咱們有兩個模型:User 和 Account,分別對應註冊用戶和消費者,他們是一對一的關係,那麼若是咱們要使用 Eloquent 提供的一對一關係方法,表結構應該是這樣的:數據庫

user: id ... ... account_id account: id ... ... user_id

假設咱們須要在 User 模型中查詢對應的 Account 表的信息,那麼代碼應該是這樣的。 `/app/models/User.php`:json

<?php class User extends Eloquent {      protected $table = 'users';   public function hasOneAccount()   {       return $this->hasOne('Account', 'user_id', 'id');   } }

而後,當咱們須要用到這種關係的時候,該如何使用呢?以下:數組

$account = User::find(10)->hasOneAccount;

此時獲得的 `$account` 即爲 `Account` 類的一個實例。app


這裏最難的地方在於後面的兩個 foreign_key 和 local_key 的設置,你們能夠就此記住:在 User 類中,不管 hasOne 誰,第二個參數都是 `user_id`,第三個參數通常都是 `id`。因爲前面的 `find(10)` 已經鎖定了 id = 10,因此這段函數對應的 SQL 爲: `select * from account where user_id=10`。ide


這段代碼除了展現了一對一關係該如何使用以外,還傳達了三點信息,也是我對於你們使用 Eloquent 時候的建議:函數

1. 每個 Model 中都指定表名

2. has one account 這樣的關係寫成 `hasOneAccount()` 而不是簡單的 `account()`

3. 每次使用模型間關係的時候都寫全參數,不要省略

相應的,若是使用 belongsTo() 關係,應該這麼寫:

<?php class Account extends Eloquent {   protected $table = 'accounts';      public function belongsToUser()   {     return $this->belongsTo('User', 'user_id', 'id');   } }

一對多關係

學會了前面使用一對一關係的基礎方法,後面的幾種關係就簡單多了。

咱們引入一個新的Model:Pay,付款記錄。表結構應該是這樣的:

user: id ... ... pay: id ... ... user_id

User 和 Pay 具備一對多關係,換句話說就是一個 User 能夠有多個 Pay,這樣的話,只在 Pay 表中存在一個 `user_id` 字段便可。 `/app/models/User.php`:

<?php class User extends Eloquent {      protected $table = 'users';   public function hasManyPays()   {     return $this->hasMany('Pay', 'user_id', 'id');   } }

而後,當咱們須要用到這種關係的時候,該如何使用呢?以下:

$accounts = User::find(10)->hasManyPays()->get();

此時獲得的 `$accounts` 即爲 `Illuminate\Database\Eloquent\Collection` 類的一個實例。你們應該也已經注意到了,這裏不是簡單的 `-> hasOneAccount` 而是 `->hasManyPays()->get()`,爲何呢?由於這裏是 `hasMany`,操做的是一個對象集合。

相應的 belongsTo() 的用法跟上面一對一關係同樣:

<?php class Pay extends Eloquent {   protected $table = 'pays';      public function belongsToUser()   {     return $this->belongsTo('User', 'user_id', 'id');   } }

多對多關係

多對多關係和以前的關係徹底不同,由於多對多關係可能出現不少冗餘數據,用以前自帶的表存不下了。

咱們定義兩個模型:Article 和 Tag,分別表示文章和標籤,他們是多對多的關係。表結構應該是這樣的:

article: id ... ... tag: id ... ... article_tag: article_id tag_id

在 Model 中使用:

<?php class Tag extends Eloquent {   protected $table = 'tags';      public function belongsToManyArticle()   {     return $this->belongsToMany('Article', 'article_tag', 'tag_id', 'article_id');   } }

須要注意的是,第三個參數是本類的 id,第四個參數是第一個參數那個類的 id。

使用跟 hasMany 同樣:

$tagsWithArticles = Tag::take(10)->get()->belongsToManyArticle()->get();

這裏會獲得一個很是複雜的對象,能夠自行 `var_dump()`。跟你們說一個訣竅,`var_dump()` 之後,用 Chrome 右鍵 「查看源代碼」,就能夠看到很是整齊的對象/數組展開了。

在這裏給你們展現一個少見用法(奇技淫巧):

public function parent_video() {     return $this->belongsToMany($this, 'video_hierarchy', 'video_id', 'video_parent_id'); } public function children_video() {     return $this->belongsToMany($this, 'video_hierarchy', 'video_parent_id', 'video_id'); }

對,你沒有看錯,能夠 belongsToMany 本身。

其餘關係

Eloquent 還提供 「遠層一對多關聯」、「多態關聯」 和 「多態的多對多關聯」 這另外三種用法,通過上面的學習,咱們已經掌握了 Eloquent 模型間關係的基本概念和使用方法,剩下的幾種不經常使用的方法就留到咱們用到的時候再本身探索吧。

重要技巧:關係預載入

你也許已經發現了,在一對一關係中,若是咱們須要一次性查詢出10個 User 並帶上對應的 Account 的話,那麼就須要給數據庫打 1 + 10 條 SQL,這樣性能是不好的。咱們可使用一個重要的特性,關係預載入:http://laravel-china.org/docs/eloquent#eager-loading

直接上代碼:

$users = User::with('hasOneAccount')->take(10)->get()

這樣生成的 SQL 就是這個樣子的:

select * from account where id in (1, 2, 3, ... ...)

這樣 1 + 10 條 SQL 就變成了 1 + 1 條,性能大增。



至此,深刻理解 Laravel Eloquent 系列文章到此結束。推薦繼續瞭解 軟刪除 、轉換成數組/JSON

相關文章
相關標籤/搜索