推薦文章深入理解 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查詢是一樣的
首先我們要了解幾個概念
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
表菜單menu
與admin
的映射表
在
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
在剛開始沒有思路的時候油湖,其實知道不適用模型是可以實現的,首先取出關聯(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