laravel belongsToMany解析

推薦文章深入理解 Laravel Eloquent(三)——模型間關系(關聯(lián))

其實關聯(lián)模型的效率是最低的,但是我們可以通過關聯(lián)模型查看更多的 sql語句的寫法两嘴。

多對對的本質其實就是兩個表使用了inner join table on語句 查詢
比如下面兩個圖,我們要取出parent_id=9的數據族壳,可以使用

select B* from system_menu as A  inner join system_menu as B 
on B.`parent_id`= A.menu_id where A.menu_id=9
或者 where B.parent_id=9
但是這樣其實沒有什么意義憔辫,直接where查詢是一樣的
圖片.png

圖片.png

首先我們要了解幾個概念

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

1.外鍵,在user表中account_id就是外鍵仿荆。
外鍵不在本表內贰您,他是在與本表關聯(lián)的表里面
這個字段相當于是account表的id鍵。

belongsToMany()多對多這個關聯(lián)可能不好理解拢操,但是我們可以打開源碼锦亦,一步步打印

   /**
     * Define a many-to-many relationship.
     *
     * @param  string  $related
     * @param  string  $table
     * @param  string  $foreignPivotKey
     * @param  string  $relatedPivotKey
     * @param  string  $parentKey
     * @param  string  $relatedKey
     * @param  string  $relation
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    public function belongsToMany($related, $table = null, $foreignPivotKey = null, $relatedPivotKey = null,
                                  $parentKey = null, $relatedKey = null, $relation = null)
    {
        // If no relationship name was passed, we will pull backtraces to get the
        // name of the calling function. We will use that function name as the
        // title of this relation since that is a great convention to apply.
        if (is_null($relation)) {
            $relation = $this->guessBelongsToManyRelation();
        }

        // First, we'll need to determine the foreign key and "other key" for the
        // relationship. Once we have determined the keys we'll make the query
        // instances as well as the relationship instances we need for this.
        $instance = $this->newRelatedInstance($related);

        $foreignPivotKey = $foreignPivotKey ?: $this->getForeignKey();

        $relatedPivotKey = $relatedPivotKey ?: $instance->getForeignKey();

        // If no table name was provided, we can guess it by concatenating the two
        // models using underscores in alphabetical order. The two model names
        // are transformed to snake case from their default CamelCase also.
        if (is_null($table)) {
            $table = $this->joiningTable($related);
        }

        return $this->newBelongsToMany(
            $instance->newQuery(), $this, $table, $foreignPivotKey,
            $relatedPivotKey, $parentKey ?: $this->getKeyName(),
            $relatedKey ?: $instance->getKeyName(), $relation
        );
    }

$related

`$instance = $this->newRelatedInstance($related);`是我們最終要獲取數據的關聯(lián)表

$table是一個中間表

 // If no table name was provided, we can guess it by concatenating the two
        // models using underscores in alphabetical order. The two model names
        // are transformed to snake case from their default CamelCase also.
        if (is_null($table)) {
            $table = $this->joiningTable($related);
        }

$foreignPivotKey可以看出,其實是本表的外鍵

$foreignPivotKey = $foreignPivotKey ?: $this->getForeignKey();

$relatedPivotKey

$instance = $this->newRelatedInstance($related);
//打印$instance 得到第一個參數的類
$relatedPivotKey = $relatedPivotKey ?: $instance->getForeignKey();
// 所以relatedPivotKey 我個人理解應該是第一個參數類的外鍵
可是事實上是 第一個參數類的主鍵ID

$parentKey第五個參數令境,如果第三個參數用的不是自己的主鍵杠园,則需要第五個參數。現在我們使用的是role_id展父,第五個參數應該就是role_id返劲,雖然從sql語句上看不出來什么玲昧,但是你看傳遞的參數值就知道了栖茉,傳遞的其實就是第五個參數的值

$parentKey ?: $this->getKeyName(),

    public function getKeyName()
    {
        return $this->primaryKey;
    }
所以第五個參數默認是本地的主鍵

belongsToMany()這個方法的使用,我感覺文檔上解釋的并不多孵延,以至于里面的參數感覺有寫模糊吕漂,不知道寫什么,還是自己一步步摸索吧
我的思路是尘应,參數不填寫惶凝,會默認顯示參數,將默認參數打印犬钢,我們就知道寫什么了

  • 需求苍鲜,一個用戶表admin里面有role_id字段,
    org_role_permit表菜單menuadmin的映射表

admin.php模型里面

return $this->belongsToMany('App\Models\System\Menu', 'org_role_permit', 'role_id', 'menu_id');

得到的sql
select `system_menu`.*, `org_role_permit`.`role_id` as `pivot_role_id`, 
`org_role_permit`.`menu_id` as `pivot_menu_id` 
from `system_menu` inner join `org_role_permit` 
on `system_menu`.`menu_id` = `org_role_permit`.`menu_id` 
where `org_role_permit`.`role_id` = 2
  • 第三個參數是本地關聯(lián)的ID玷犹,可以理解成本地id混滔,但是并不是所有的關聯(lián)都是使用ID,所以其實也不能理解成ID。同時他也是where條件里面的一個字段坯屿,如果換成menu_id,則會變成 where org_role_permit.menu_id = 2
圖片.png
打印文件.png
打印結果

在剛開始沒有思路的時候油湖,其實知道不適用模型是可以實現的,首先取出關聯(lián)表里面role_id對應的數據的所有menu_id數組集,然后在menu表里面取出所有menu_id的數據

    $menuIds = \DB::table('org_role_permit')
            ->where('role_id', '=', $this->getRoleId())
            ->pluck('menu_id')->toArray();
                return Menu::whereIn('menu_id', $menuIds);

但是后來發(fā)現一種更簡單的方式,直接通過inner join內連接取值即可领跛,因為越少的sql取值速度越快乏德,所以建議使用以下方式。

 return Menu::where('role_id', '=', $this->getRoleId())
       ->join('org_role_permit','system_menu.menu_id','=','org_role_permit.menu_id');

得到的sql
select * from `system_menu` inner join `org_role_permit` on 
`system_menu`.`menu_id` = `org_role_permit`.`menu_id` where `role_id` = 2
圖片.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末吠昭,一起剝皮案震驚了整個濱河市喊括,隨后出現的幾起案子,更是在濱河造成了極大的恐慌矢棚,老刑警劉巖瘾晃,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異幻妓,居然都是意外死亡蹦误,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門肉津,熙熙樓的掌柜王于貴愁眉苦臉地迎上來强胰,“玉大人,你說我怎么就攤上這事妹沙∨佳螅” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵距糖,是天一觀的道長玄窝。 經常有香客問我,道長悍引,這世上最難降的妖魔是什么恩脂? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮趣斤,結果婚禮上俩块,老公的妹妹穿的比我還像新娘。我一直安慰自己浓领,他們只是感情好玉凯,可當我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著联贩,像睡著了一般漫仆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泪幌,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天盲厌,我揣著相機與錄音玄渗,去河邊找鬼。 笑死狸眼,一個胖子當著我的面吹牛藤树,可吹牛的內容都是我干的。 我是一名探鬼主播拓萌,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼岁钓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了微王?” 一聲冷哼從身側響起屡限,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎炕倘,沒想到半個月后钧大,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡罩旋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年啊央,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涨醋。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡瓜饥,死狀恐怖,靈堂內的尸體忽然破棺而出浴骂,到底是詐尸還是另有隱情乓土,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布溯警,位于F島的核電站趣苏,受9級特大地震影響,放射性物質發(fā)生泄漏梯轻。R本人自食惡果不足惜食磕,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望檩淋。 院中可真熱鬧芬为,春花似錦萄金、人聲如沸蟀悦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽日戈。三九已至,卻和暖如春孙乖,著一層夾襖步出監(jiān)牢的瞬間浙炼,已是汗流浹背份氧。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留弯屈,地道東北人蜗帜。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像资厉,于是被迫代替她去往敵國和親厅缺。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內容

  • 回首頁 第一部分 Drupal簡介 Drupal overview A tour of Drupal fundam...
    王乂閱讀 2,034評論 0 9
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理宴偿,服務發(fā)現湘捎,斷路器,智...
    卡卡羅2017閱讀 134,665評論 18 139
  • ORA-00001: 違反唯一約束條件 (.) 錯誤說明:當在唯一索引所對應的列上鍵入重復值時窄刘,會觸發(fā)此異常窥妇。 O...
    我想起個好名字閱讀 5,320評論 0 9
  • 作者:華萊士.沃特萊斯 一條公式,三個概念娩践,十大標準幫助你收獲100%健康活翩! 這本書從心理學角度講述了保持健康的方...
    殷琦榕閱讀 359評論 0 0
  • 蟬兒在依賴著 大樹的胸膛, 撒嬌的聲音 讓人受不了翻伺。 過街的熙攘纱新, 耳里播放的, 全是熱鬧穆趴。 洋溢出來的 俱是歡笑...
    混爾清閱讀 245評論 0 1