mysql中的自关联详解_Laravel - MySQL数据库的使用详解6(Eloquent ORM用法3:模型关联、关联查询)...
一、一對一關聯
一對一關聯是很基本的關聯。假設一個 User 對應到一個 Phone,phones 表結構如下(通過 user_id 關聯 user 表的主鍵):
1,定義一對一關聯
(1)User 模型中按下面這樣定義關聯,傳到 hasOne 方法里的第一個參數是關聯模型的類名稱。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
// 獲取用戶對應的電話
public function phone()
{
return $this->hasOne('App\Models\Phone');
}
}
(2)定義好關聯之后,就可以使用 Eloquent 的動態屬性取得關聯對象:
$phone = User::find(1)->phone;
(3)上面操作實際上執行了如下 sql:
select * from users where id = 1
select * from phones where user_id = 1
2,指定一對一關聯的外鍵
(1)默認情況下,外鍵名稱是基于模型名稱來的。比如上面樣例,Phone 模型則自動以 user_id 作為外鍵。如果想要更改這個默認值,可以傳入第二個參數到 hasOne 方法里。
return $this->hasOne('App\Models\Phone', 'my_user_id');
(2)我們還可以傳入第三個參數,指定關聯的外鍵要對應到本身的哪個字段:
return $this->hasOne('App\Models\Phone', 'my_user_id', 'uid');
3,定義相對的關聯
(1)前面我們是在 phones 表中有個 user_id 用來關聯 user 表數據,如果想在 Phone 模型中獲取 User 模型對象,可以使用 belongsTo 定義相對的關聯。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Phone extends Model {
// 獲取電話對應的用戶
public function user()
{
return $this->belongsTo('App\Models\User');
}
}
(2)定義好關聯之后,就可以使用 Eloquent 的動態屬性取得關聯對象:
$user = Phone::find(1)->user;
4,指定關聯的外鍵
(1)默認情況下,外鍵名稱是基于模型名稱來的。比如上面樣例,Phone 模型則自動以 user_id 作為外鍵。我們也可以在 belongsTo 方法里傳入第二個參數,來指定外鍵字段。
return $this->belongsTo('App\Models\User', 'local_key');
(2)除此之外,也可以傳入第三個參數指定要參照上層數據庫表的哪個字段。
return $this->belongsTo('App\Models\User', 'local_key', 'parent_key');
二、一對多關聯
同樣以用戶、電話表為例。假設一個 User 可以擁有多個 Phone,phones 表結構如下(通過 user_id 關聯 user 表的主鍵):
1,定義一對多關聯
(1)User 模型中按下面這樣定義關聯,傳到 hasMany 方法里的第一個參數是關聯模型的類名稱。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
// 獲取用戶對應的所有電話
public function phones()
{
return $this->hasMany('App\Models\Phone');
}
}
(2)定義好關聯之后,就可以使用 Eloquent 的動態屬性取得所有關聯對象:
// 獲取id為1的用戶所有電話
$phones = User::find(1)->phones;
// 返回的結果同樣支持鏈式調用
$phone = User::find(1)->phones->first();
2,指定一對多關聯的外鍵
(1)默認情況下,外鍵名稱是基于模型名稱來的。比如上面樣例,Phone 模型則自動以 user_id 作為外鍵。如果想要更改這個默認值,可以傳入第二個參數到 hasMany 方法里。
return $this->hasMany('App\Models\Phone', 'my_user_id');
(2)我們還可以傳入第三個參數,指定關聯的外鍵要對應到本身的哪個字段:
return $this->hasMany('App\Models\Phone', 'my_user_id', 'uid');
3,定義相對的關聯
如果想要在 Phone 模型中獲取 User 模型對象,那么使用 belongsTo 定義相對的關聯。具體用法詳見上方一對一關聯部分。
三、遠層一對多關聯(Has Many Through)
“遠層一對多關聯”提供了方便簡短的方法,可以經由多層間的關聯取得遠層的關聯。例如,一個 Country 模型可能通過 Users 關聯到很多 Posts 模型,這些數據庫表間的關系如下:
countries
id - integer
name - string
users
id - integer
country_id - integer
name - string
posts
id - integer
user_id - integer
title - string
(1)雖然 posts 數據庫表本身沒有 country_id 字段,但 hasManyThrough 方法讓我們可以使用 $country->posts 取得 country 的 posts。我們可以定義以下關聯:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Country extends Model {
public function posts()
{
return $this->hasManyThrough('App\Models\Post', 'App\Models\User');
}
}
(2)如果想要手動指定關聯的字段名稱,可以傳入第三和第四個參數到方法里:
return $this->hasManyThrough('App\Models\Post', 'App\Models\User', 'country_id', 'user_id');
四、多對多關聯
多對多關聯常見有用戶、角色之間的相互關聯:一個用戶( user )可能用有很多角色( role ),而一種角色可能很多用戶都有。
所以數據庫會存在如下三個表:用戶表(users)、角色表(roles)、用戶角色關聯表(role_user)。其中關聯表以關聯的兩個模型命名(先后按字母順序排列),關聯表結構如下:
1,定義多對多關聯
(1)在 User 和 Role 模型中我們可以使用 belongsToMany 方法定義多對多關系(關聯表是不需要定義對應的模型的)
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
// 獲取用戶對應的所有角色
public function roles()
{
return $this->belongsToMany('App\Models\Role');
}
}
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Role extends Model {
// 獲取角色對應的所有用戶
public function users()
{
return $this->belongsToMany('App\Models\User');
}
}
(2)定義好關聯之后,就可以使用 Eloquent 的動態屬性取得關聯對象。下面樣例取得 id 為 1的用戶擁有的所有角色:
$roles = User::find(1)->roles;
2,指定關聯表名和關聯字段
(1)如果我們關聯表是按規定的格式命名的話(以關聯的兩個模型命名,先后按字母順序排列),是不需要在手動指定關聯表。否則,我們可以在 belongsToMany 方法中傳入第二個參數,指定使用的關聯表名。
return $this->belongsToMany('App\Models\Role', 'users_roles');
(2)同樣的關聯表中的關聯字段默認同樣采用“模型_id”的命名方式,如果不是的話,我們可以在 belongsToMany 第三、第四個參數指定使用的關聯字段。
return $this->belongsToMany('App\Models\Role', 'users_roles', 'user_id', 'role_id');
五、關聯查詢
在取得模型數據時,我們可能想要以關聯模型作為查詢限制。下面同樣以上面的用戶(User)、電話(Phone)這個一對多關聯場景進行演示。
1,has 方法
(1)想要取得所有“至少有一個電話”的用戶。可以使用 has 方法達成目的。
$users = User::has('phones')->get();
(2)也可以指定運算符和數量:
$users = User::has('phones', '>=', 3)->get();
(3)也可以使用“點號”的形式來獲取嵌套的 has 聲明:
$users = User::has('phones.xxxx')->get();
2,whereHas 、 orWhereHas 方法
如果想要更進階的用法,可以使用 whereHas 和 orWhereHas 方法,在 has 查詢里設置 “where” 條件 :
$users = Post::whereHas('phones', function($q)
{
$q->where('number', 'like', '189%');
})->get();
附:預載入
預載入是用來減少 N + 1查詢問題。例如,一個 Phone 模型數據會關聯到一個 User ,關聯會像下面這樣定義。
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Phone extends Model {
// 獲取電話對應的用戶
public function user()
{
return $this->belongsTo('App\Models\User');
}
}
1,基本用法
(1)假設我們使用下面的循環會執行一次查詢取回所有數據庫表上的電話,然而每個電話又都會執行一次查詢取得用戶。所以若我們有 10 個電話記錄,就會進行 11 次查詢。
foreach (Phone::all() as $phone)
{
echo $phone->user->username;
}
(2)我們可以使用預載入大量減少查詢次數。即使用 with 方法指定想要預載入的關聯對象:
foreach (Phone::with('user')->get() as $phone)
{
echo $phone->user->username;
}
(3)上面的循環總共只會執行兩次查詢,對應的 sql 如下:
select * from phones
select * from users where id in (1, 2, 3, 4, 5, ...)
2,同時載入多種關聯
使用預載入可以大大提高程序的性能,當然 with 方法也是可以同時載入多種關聯的。
Phone::with('user', 'operator')->get()
3,預載入條件限制
(1)我們也可以指定預載入時的查詢限制,比如下面只預載入李姓用戶:
$phone = Phone::with(['user' => function($query)
{
$query->where('username', 'like', '李%');
}])->get();
(2)當然,預載入的閉合函數里不一定只能加上條件限制,也可以加上排序:
$phone = Phone::with(['user' => function($query)
{
$query->orderBy('age', 'desc');
}])->get();
總結
以上是生活随笔為你收集整理的mysql中的自关联详解_Laravel - MySQL数据库的使用详解6(Eloquent ORM用法3:模型关联、关联查询)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 联想主板怎么进去bios设置界面 联想电
- 下一篇: suse mysql ERROR1045