詳解Laravel設(shè)置多態(tài)關(guān)系模型別名的方式
作為 Laravel 的重度使用者肯定都對(duì)多態(tài)關(guān)系不默生,以官方文檔為例,文章有標(biāo)簽,視頻有標(biāo)簽,那么文章和視頻這些模型與標(biāo)簽?zāi)P偷年P(guān)系就是 多態(tài)多對(duì)多(Many To Many (Polymorphic))
如果我們給 ID 為 1 的文章打上兩個(gè)標(biāo)簽,數(shù)據(jù)庫標(biāo)簽關(guān)系表的的存儲(chǔ)結(jié)果就是這樣子:
> select * from taggables; +--------+-------------+---------------+ | tag_id | taggable_id | taggable_type | +--------+-------------+---------------+ | 1 | 1 | App\Post | | 2 | 1 | App\Post | +--------+-------------+---------------+
相信有不少人和我一樣希望 taggable_type 的值不要直接用模型類名,而是使用表名: posts 。官方文檔的建議是:
use Illuminate\Database\Eloquent\Relations\Relation; Relation::morphMap([ 'posts' => 'App\Post', 'videos' => 'App\Video', ]);
https://laravel.com/docs/6.x/eloquent-relationships#custom-polymorphic-types
我們可以將這個(gè)定義寫到 AppServiceProvider 中,但是有一個(gè)非常嚴(yán)重的問題: 我們?cè)谛略龌蛘邉h除模型的時(shí)候,會(huì)很容易忘記去更新這個(gè)定義 。我已經(jīng)至少出現(xiàn)這個(gè)問題 3 次了,所以我一直在糾結(jié)有沒有更好的方法,今天突然靈機(jī)一動(dòng),實(shí)現(xiàn)了一個(gè)看起來似乎是一個(gè)不錯(cuò)的方式,分享給大家。
思路來源
我嘗試跟蹤了一遍源碼,發(fā)現(xiàn)模型中有一個(gè)方法 getMorphClass ,多態(tài)關(guān)聯(lián)的時(shí)候,就是用它來取目標(biāo)對(duì)象的類型名稱的,默認(rèn)返回類名:
public function getMorphClass() { $morphMap = Relation::morphMap(); if (! empty($morphMap) && in_array(static::class, $morphMap)) { return array_search(static::class, $morphMap, true); } return static::class; }
那么,只要我們?cè)谀P椭懈采w這個(gè)方法便可以方便的實(shí)現(xiàn)目標(biāo)了。
實(shí)現(xiàn)目標(biāo)
我們有兩個(gè)選擇去實(shí)現(xiàn)它:
- 創(chuàng)建一個(gè)模型基類覆蓋這個(gè)方法,所有的模型都來集成它即可;
- 創(chuàng)建一個(gè) trait,在需要的模型中引入它。
我當(dāng)然會(huì)選擇 trait 方式來實(shí)現(xiàn),不管從定義還是代碼耦合度上,使用 trait 來解決這類特性需求都是再適合不過了,如果你對(duì) trait 還不太熟悉,可以閱讀我之前的文章: 《我所理解的 PHP Trait》
我們的目標(biāo)是使用表名來做為關(guān)系類別名,那么在模型中如何獲取表名呢,直接使用模型的 getTable 即可,那么整個(gè) trait 的實(shí)現(xiàn)如下:
app/Traits/UseTableNameAsMorphClass.php <?php namespace App\Traits; trait UseTableNameAsMorphClass { public function getMorphClass() { return $this->getTable(); } }
然后在我們需要用到關(guān)系類型的模型中引入它即可:
<?php namespace App; use App\Traits\UseTableNameAsMorphClass; use Illuminate\Database\Eloquent\Model; class Post extends Model { use UseTableNameAsMorphClass; //... }
友情提示
當(dāng)然,如果你習(xí)慣給表名加前綴,或者你的表名與模型名不太一致,那么,你只需要修改 trait 中 getMorphClass
的實(shí)現(xiàn)即可,我個(gè)人的習(xí)慣是模型名就是表名的單數(shù),不帶前綴。
總結(jié)
以上所述是小編給大家介紹的Laravel設(shè)置多態(tài)關(guān)系模型別名的方式,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
- Laravel5.1 框架模型查詢作用域定義與用法實(shí)例分析
- Laravel5.1 框架模型工廠ModelFactory用法實(shí)例分析
- Laravel5.1 框架模型軟刪除操作實(shí)例分析
- Laravel5.1 框架模型創(chuàng)建與使用方法實(shí)例分析
- Laravel 5框架學(xué)習(xí)之模型、控制器、視圖基礎(chǔ)流程
- Laravel模型間關(guān)系設(shè)置分表的方法示例
- Laravel關(guān)系模型指定條件查詢方法
- Laravel 實(shí)現(xiàn)關(guān)系模型取出需要的字段
- Laravel模型事件的實(shí)現(xiàn)原理詳解
- Laravel框架模型的創(chuàng)建及模型對(duì)數(shù)據(jù)操作示例
- Laravel使用模型實(shí)現(xiàn)like模糊查詢的例子
- Laravel5.1 框架模型一對(duì)一關(guān)系實(shí)現(xiàn)與使用方法實(shí)例分析
相關(guān)文章
php實(shí)現(xiàn)文件下載功能的幾個(gè)代碼分享
我們一般實(shí)現(xiàn)下載都是調(diào)用url來下載,但是遇到ie能識(shí)別打開的文件就不能用這種方式了,比如下載一個(gè)圖片、html網(wǎng)頁等,這時(shí)就需要編程來實(shí)現(xiàn)2014-05-05解決PHP使用CURL發(fā)送GET請(qǐng)求時(shí)傳遞參數(shù)的問題
今天小編就為大家分享一篇解決PHP使用CURL發(fā)送GET請(qǐng)求時(shí)傳遞參數(shù)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-10-10php 問卷調(diào)查結(jié)果統(tǒng)計(jì)
一個(gè)新產(chǎn)品投入市場(chǎng),要先做問卷調(diào)查,考察這個(gè)產(chǎn)品在市場(chǎng)的需求量,本篇文章主要跟大家介紹使用php問卷調(diào)查結(jié)果統(tǒng)計(jì),感興趣的朋友一起學(xué)習(xí)吧2015-10-10thinkPHP框架實(shí)現(xiàn)類似java過濾器的簡(jiǎn)單方法示例
這篇文章主要介紹了thinkPHP框架實(shí)現(xiàn)類似java過濾器的簡(jiǎn)單方法,結(jié)合實(shí)例形式分析了thinkPHP基于繼承實(shí)現(xiàn)的登錄驗(yàn)證功能相關(guān)操作方法,需要的朋友可以參考下2018-09-09PHP獲取網(wǎng)頁標(biāo)題的3種實(shí)現(xiàn)方法代碼實(shí)例
這篇文章主要介紹了PHP獲取網(wǎng)頁標(biāo)題的3種實(shí)現(xiàn)方法,分別使用CURL、file()函數(shù)、file_get_contents實(shí)現(xiàn),需要的朋友可以參考下2014-04-04淺談php中變量的數(shù)據(jù)類型判斷函數(shù)
下面小編就為大家?guī)硪黄獪\談php中變量的數(shù)據(jù)類型判斷函數(shù)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03