加載中...

多態關聯


多態一對多關聯

多態關聯允許一個模型在單個關聯定義方法中從屬一個以上其它模型,例如用戶可以評論書和文章,但評論表通常都是同一個數據表的設計。多態一對多關聯關系,就是為了滿足類似的使用場景而設計。

下面是關聯表的數據表結構:

article
    id - integer
    title - string
    content - text

book
    id - integer
    title - string

comment
    id - integer
    content - text
    commentable_id - integer
    commentable_type - string

有兩個需要注意的字段是?comment?表中的?commentable_id?和?commentable_type我們稱之為多態字段。其中,?commentable_id?用于存放書或者文章的 id(主鍵) ,而?commentable_type?用于存放所屬模型的類型。通常的設計是多態字段有一個公共的前綴(例如這里用的commentable),當然,也支持設置完全不同的字段名(例如使用data_idtype)。

多態關聯定義

接著,讓我們來查看創建這種關聯所需的模型定義:

文章模型:

<?php
namespace app\index\model;

use think\Model;

class Article extends Model
{
    /**
     * 獲取所有針對文章的評論。
     */
    public function comments()
    {
        return $this->morphMany('Comment', 'commentable');
    }
}

morphMany方法的參數如下:

morphMany('關聯模型','多態字段','多態類型');

關聯模型(必須):關聯的模型名稱,可以使用模型名(如Comment)或者完整的命名空間模型名(如app\index\model\Comment)。

多態字段(可選):支持兩種方式定義 如果是字符串表示多態字段的前綴,多態字段使用 多態前綴_type多態前綴_id,如果是數組,表示使用['多態類型字段名','多態ID字段名'],默認為當前的關聯方法名作為字段前綴。

多態類型(可選):當前模型對應的多態類型,默認為當前模型名,可以使用模型名(如Article)或者完整的命名空間模型名(如app\index\model\Article)。

書籍模型:

<?php
namespace app\index\model;

use think\Model;

class Book extends Model
{
    /**
     * 獲取所有針對書籍的評論。
     */
    public function comments()
    {
        return $this->morphMany('Comment', 'commentable');
    }
}

書籍模型的設置方法同文章模型一致,區別在于多態類型不同,但由于多態類型默認會取當前模型名,因此不需要單獨設置。

下面是評論模型的關聯定義:

<?php
namespace app\index\model;

use think\Model;

class Comment extends Model
{
    /**
     * 獲取評論對應的多態模型。
     */
    public function commentable()
    {
        return $this->morphTo();
    }
}

morphTo方法的參數如下:

morphTo('多態字段',['多態類型別名']);

多態字段(可選):支持兩種方式定義 如果是字符串表示多態字段的前綴,多態字段使用 多態前綴_type多態前綴_id,如果是數組,表示使用['多態類型字段名','多態ID字段名'],默認為當前的關聯方法名作為字段前綴 多態類型別名(可選):數組方式定義

獲取多態關聯

一旦你的數據表及模型被定義,則可以通過模型來訪問關聯。例如,若要訪問某篇文章的所有評論,則可以簡單的使用?comments?動態屬性:

$article = Article::get(1);

foreach ($article->comments as $comment) {
    dump($comment);
}

你也可以從多態模型的多態關聯中,通過訪問調用?morphTo?的方法名稱來獲取擁有者,也就是此例子中?Comment?模型的?commentable?方法。所以,我們可以使用動態屬性來訪問這個方法:

$comment = Comment::get(1);
$commentable = $comment->commentable;

Comment?模型的?commentable?關聯會返回?Article?或?Book?模型的對象實例,這取決于評論所屬模型的類型。

自定義多態關聯的類型字段

默認情況下,ThinkPHP 會使用模型名作為多態表的類型區分,例如,Comment屬于?Article?或者?Book?,?commentable_type?的默認值可以分別是?Article?或者?Book?。我們可以通過定義多態的時候傳入參數來對數據庫進行解耦。

    public function commentable()
    {
        return $this->morphTo('commentable',[
            'book'  =>  'app\index\model\Book',
            'post'  =>  'app\admin\model\Article',
        ]);
    }

多態一對一關聯

多態一對一相比多態一對多關聯的區別是動態的一對一關聯,舉個例子說有一個個人和團隊表,而無論個人還是團隊都有一個頭像需要保存但都會對應同一個頭像表

member
    id - integer
    name - string

team
    id - integer
    name - string

avatar
    id - integer
    avatar - string
    imageable_id - integer
    imageable_type - string 

會員模型:

<?php
namespace app\index\model;

use think\Model;

class Member extends Model
{
    /**
     * 獲取用戶的頭像
     */
    public function avatar()
    {
        return $this->morphOne('Avatar', 'imageable');
    }
}

團隊模型:

<?php
namespace app\index\model;

use think\Model;

class Team extends Model
{
    /**
     * 獲取團隊的頭像
     */
    public function avatar()
    {
        return $this->morphOne('Avatar', 'imageable');
    }
}

morphOne方法的參數如下:

morphOne('關聯模型','多態字段','多態類型');

關聯模型(必須):關聯的模型名稱,可以使用模型名(如Member)或者完整的命名空間模型名(如app\index\model\Member)。

多態字段(可選):支持兩種方式定義 如果是字符串表示多態字段的前綴,多態字段使用 多態前綴_type多態前綴_id,如果是數組,表示使用['多態類型字段名','多態ID字段名'],默認為當前的關聯方法名作為字段前綴。

多態類型(可選):當前模型對應的多態類型,默認為當前模型名,可以使用模型名(如Member)或者完整的命名空間模型名(如app\index\model\Member)。

下面是頭像模型的關聯定義:

<?php
namespace app\index\model;

use think\Model;

class Avatar extends Model
{
    /**
     * 獲取頭像對應的多態模型。
     */
    public function imageable()
    {
        return $this->morphTo();
    }
}

理解了多態一對多關聯后,多態一對一關聯其實就很容易理解了,區別就是當前模型和動態關聯的模型之間的關聯屬于一對一關系。


還沒有評論.
股票配资平台l选一直牛