Laravel多態(tài)關(guān)系教程(polymorphic)

1.什么叫多態(tài)關(guān)系度液?

英文叫polymorphic, 本意是一個物體可以有很多的狀態(tài)冤灾。在laravel里面徒恋,就是指各各模型直接有很多相互的關(guān)系,laravel有3種多態(tài)關(guān)系眨攘。我們舉個例子主慰,一個圖片的模型可以歸屬于一個用戶,也可以歸屬于一個文章鲫售,一篇文章可以有多個圖共螺,一個用戶也可以有多個圖。如何在模型文件里反應(yīng)這些關(guān)系呢情竹?我們可以用一個圖片模型來反應(yīng)這個關(guān)系藐不。下面我們通過一個例子來說明這個關(guān)系。

2.創(chuàng)建文章模型秦效,圖片模型雏蛮,然后我們來寫一個遷移文件和工廠文件來填充假數(shù)據(jù)到文章數(shù)據(jù)庫。

php artisan make:model Post -mf

在文章里棉安,我們填兩個字段:

$table->string('title');
$table->text('body');

然后我們創(chuàng)建一個圖片模型文件:

php artisan make:model Image -m

我們暫時不需要創(chuàng)建工廠文件了底扳。
在填遷移文件的時候我們需要填兩個字段:
在通常情況下,我們會填一個post_id來表明這個圖片是屬于這個POST的贡耽。
但是在多態(tài)情況下衷模,這種做法是無法反應(yīng)用戶ID和這個圖片的關(guān)系。
所以在這種情況下我們就加一個特殊的字段蒲赂,叫做"imageable_id".
還有一個字段是填入我們的模型阱冶,一般的做法是加一個"imageable_type"這個字段。
讓我們來看下Image這個模型的遷移文件里加了什么:

$table->string('image_url');
$table->unsignedBigInteger('imageable_id');
$table->string('imageable_type');

第一個字段我們填的是上傳后的圖片連接滥嘴。
第二個字段里我們填的是模型的ID木蹬,例如如果是post的話就是post_id, 如果是user的話是user_id.
第三個字段我們填的是模型類型:如App\Post或者App\User等。

然后我們來遷移若皱。我們來填充一個假數(shù)據(jù)到post這個表格镊叁。

3.一對一的模型文件里多態(tài)關(guān)系的寫法:

在文章模型文件里,我們可以寫:
app/Post.php里面

public function image()
{
   return $this->morphOne(Image::class, 'imageable');
}

app/Image.php里面:
在這里我們必須要用imageable這個方法名走触,因為我們在上面已經(jīng)定義了晦譬。

public function imageable()
{
    return $this->morphTo();
}

就好比我們belongTo()一樣认然,這里要用morphTo().
下面我們來填充一個數(shù)據(jù)到圖片這個模型里锈拨。

Post::first()->image()->create(['image_url' => 'some/image.jpg']);

我們可以用關(guān)系來填充,如果我們看下數(shù)據(jù)庫里面的話图毕,我們會看到:
imageable_id是1,imageable_type是App\Post.
接下來我們要寫User.php里面的來填充一個假數(shù)據(jù)并且加一個圖片到對應(yīng)關(guān)系里面的表格像樊。

在User.php里面的關(guān)系的語句跟post里面的是一模一樣的尤莺。我們還是用同樣的方法來填充數(shù)據(jù):

User::first()->image()->create(['image_url' => 'some/image.jpg']);

數(shù)據(jù)庫里表現(xiàn)的是:imageable_id是1,imageable_type是App\User.

4. 一對多的多態(tài)關(guān)系:

一篇文章可以有多個評論生棍,一個用戶可以有多個評論颤霎。
創(chuàng)建模型文件:

php artisan make:model Comment

遷移文件里面:

$table->text('body');
$table->unsignedBigInteger('commentable_id');
$table->string('commentable_type');

在Post里面:

public function comments()
{
    return $this->morphMany(Comment::class, 'commentable');
}

在Comment里面,加關(guān)系方法:

public function commentable()
{
  return $this->morphTo();
}

我們利用這個關(guān)系來添加一個評論:

Post::first()->comments()->create(['body' => 'my message']);

我們會看到數(shù)據(jù)庫里多一個記錄足绅。
imageable_id是1捷绑,imageable_type是App\Post.
當(dāng)然因為它是1對多的關(guān)系,我們可以繼續(xù)加一條記錄氢妈。
用同樣的方法粹污,我們可以加一個評論,用User的模型首量。

5.多對多的多態(tài)關(guān)系
多對多的多態(tài)關(guān)系壮吩,跟上面的不同點比較多,我們來用tags(標(biāo)簽)來做下例子加缘。任何模型都可以有很多tag鸭叙。標(biāo)簽也屬于很多的模型。例如一個帖子post有很多標(biāo)簽拣宏,php, java, python等等沈贝,反過來也一樣。

我們首先需要創(chuàng)建一個模型勋乾,然后需要再創(chuàng)建一個“膠水”宋下,用這個“膠水”把標(biāo)簽?zāi)P秃推渌哪P吐?lián)系到一起。

php artisan make:model tag -m

我們再做一個“膠水”的遷移文件:

php artisan make:migration creates_taggables_table --create taggables

我們把這個遷移文件打開進行修改辑莫。

$table->increments('id');

我們將這句改一下学歧,因為我們要把tag模型和taggables直接做個關(guān)聯(lián)。

$table->unsignedBigInteger('tag_id');

然后再加2個字段:

$table->unsignedBigInteger('taggable_id');
$table->string('taggable_type');

在tag這個表格上我們只需要加一個字段

$table->string('name');

這樣我們所要做的工作就結(jié)束了各吨,我們在Post這個模型上加一個方法:
Post.php

public function tags()
{
    return $this->morphToMany(Tag::class, 'taggable');
}

在tags.php里面枝笨,我們可以加

public function posts()
{
    return $this->morphedByMany(Post::class, 'taggable');
}

比較好的記憶方法是,在要被關(guān)聯(lián)的模型里加一個以表格名稱起名的方法揭蜒,然后跟模型和關(guān)鍵詞('taggable')進行關(guān)聯(lián)横浑,然后在另一個模型里放morphedByMany這個關(guān)鍵詞,放對應(yīng)的模型和關(guān)鍵詞就行可以了屉更。

如果我們試著放一個數(shù)據(jù)到這里的時候伪嫁,我們會發(fā)現(xiàn):

Post::first()->tag()->create(['name' => 'php']);

在taggables表格里多出了一個記錄,而且在tags表格里多出了一個記錄偶垮。








最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子似舵,更是在濱河造成了極大的恐慌脚猾,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砚哗,死亡現(xiàn)場離奇詭異龙助,居然都是意外死亡,警方通過查閱死者的電腦和手機蛛芥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門提鸟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人仅淑,你說我怎么就攤上這事称勋。” “怎么了涯竟?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵赡鲜,是天一觀的道長。 經(jīng)常有香客問我庐船,道長银酬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任筐钟,我火速辦了婚禮揩瞪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘篓冲。我一直安慰自己李破,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布纹因。 她就那樣靜靜地躺著喷屋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瞭恰。 梳的紋絲不亂的頭發(fā)上屯曹,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音惊畏,去河邊找鬼恶耽。 笑死,一個胖子當(dāng)著我的面吹牛颜启,可吹牛的內(nèi)容都是我干的偷俭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼缰盏,長吁一口氣:“原來是場噩夢啊……” “哼涌萤!你這毒婦竟也來了淹遵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤负溪,失蹤者是張志新(化名)和其女友劉穎透揣,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體川抡,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡辐真,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了崖堤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侍咱。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖密幔,靈堂內(nèi)的尸體忽然破棺而出楔脯,到底是詐尸還是另有隱情,我是刑警寧澤老玛,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布淤年,位于F島的核電站,受9級特大地震影響蜡豹,放射性物質(zhì)發(fā)生泄漏麸粮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一镜廉、第九天 我趴在偏房一處隱蔽的房頂上張望弄诲。 院中可真熱鬧,春花似錦娇唯、人聲如沸齐遵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽梗摇。三九已至,卻和暖如春想许,著一層夾襖步出監(jiān)牢的瞬間伶授,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工流纹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留糜烹,地道東北人。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓漱凝,卻偏偏與公主長得像疮蹦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子茸炒,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容