Laravel之Eloquent ORM關聯

一.一對一

1.主對從(hasOne)
從User模型中取出用戶的手機

User模型中:

/**
* 獲取關聯到用戶的手機
*/
public function phone()
{
	return $this->hasOne('App\Phone');
	// return $this->hasOne(Phone::class);
}

phone默認有個user_id外鍵關聯user模型的id,因此上面的應該是
return $this->hasOne('App\Phone', 'id', 'user_id');//第二個參數是被關聯模型的(User模型中的)字段,第三個參數是當前模型的須要和被關聯模型對應的字段(此處Phone模型字段)

調用:
User::find(1)->phone; //做爲屬性調用
User::find(1)->phone()->get();//做爲方法調用

或者:
$user = User::find(1);
$phone = $task->phone()->get();
若是對phone的結果進一步過濾,能夠加where
$phone = $task->phone()->where('is_active', 1)->get();


對應原生的SQL查詢:
select * from `lar_users` where `lar_users`.`id` = 1 limit 1;
select * from `lar_phones` where `lar_phones`.`id` = 1 and `lar_phones`.`id` is not null limit 1;

2.從對主(belongsTo)
/**
* 獲取任務模型對應的用戶
*/
public function user()
{
        return $this->belongsTo(User::class, 'user_id', 'id');//和前面的相反,第二個參數是當前模型的字段,第三個參數是關聯模型的字段
}

對應原生SQL:
select * from `lar_tasks` where `lar_tasks`.`id` = 1 limit 1;
select * from `lar_users` where `lar_users`.`id` = 1 limit 1;

二者原生的SQL語句有個區別是加了is not null;

二.一對多

1.一主對多從

public function tasks()
{
	return $this->hasMany(Task::class, 'user_id', 'id');
}

原生sql
select * from `lar_users` where `lar_users`.`id` = ? limit 1
select * from `lar_tasks` where `lar_tasks`.`user_id` = ? and `lar_tasks`.`user_id` is not null

2.多從對一主
這跟一對一的從對主同樣


三.對關聯關係進行查詢(where子查詢)
好比須要查詢有三條任務的用戶,使用has,傳入關聯屬性
User::has('tasks', '>', 3)->get()

對應的原生SQL語句:
select * from `lar_users` where (select count(*) from `lar_tasks` where `lar_tasks`.`user_id` = `lar_users`.`id`) > 3;

更復雜的能夠使用whereHas和orWhereHas,查詢有任務,且任務名稱爲'發送'開頭的用戶
User::whereHas('tasks', function($query) {
	$query->where('name', 'like', '發送%');
	})->get();

對應的原生SQL語句:
select * from `lar_users` where (select count(*) from `lar_tasks` where `lar_tasks`.`user_id` = `lar_users`.`id` and `name` like ?) >= 1;

四.渴求式加載
關聯關係數據時"懶惰式加載"的,也就是在第一次用到的時候纔會被加載.

1.懶惰加載產生的問題
打印每一個用戶的任務名稱
$users = User::all();
foreach ($users as $user) {
	$user->tasks->name;
}

這將先查詢一次users表,再挨個去查詢tasks表,有多少個用戶就查詢多少次
原生的SQL語句以下所示:
select * from `lar_users
select * from `lar_tasks` where `lar_tasks`.`user_id` = ? and `lar_tasks`.`user_id` is not null limit 1
select * from `lar_tasks` where `lar_tasks`.`user_id` = ? and `lar_tasks`.`user_id` is not null limit 1
select * from `lar_tasks` where `lar_tasks`.`user_id` = ? and `lar_tasks`.`user_id` is not null limit 1
select * from `lar_tasks` where `lar_tasks`.`user_id` = ? and `lar_tasks`.`user_id` is not null limit 1
.............

2.使用渴求式加載:
$users = User::with('tasks')->get();
foreach ($users as $user) {
	$user->tasks->name;
}

原生的SQL語句以下所示:
select * from `lar_users
select * from `lar_tasks` where `lar_tasks`.`user_id` in (?, ?)

五.關聯模型的insert/update 1.基本的insert $user = User::find(1); $user->tasks()->create(['name' => '測試任務1']); 也能夠使用save/saveMany,不過save接受的是一個模型實例,create接受原生數組.user_id被自動帶入到插入的數組中. 原生SQL語句: select * from `lar_users` where `lar_users`.`id` = ? limit 1 insert into `lar_tasks` (`name`, `user_id`, `updated_at`, `created_at`) values (?, ?, ?, ?); 2.常見的從對主的更新(belongsTo) 觸發父模型的更新時間戳(update_at) class Task extends Model { protected $touches = ['user']; protected $fillable = ['name','user_id']; public function user() { return $this->belongsTo(User::class, 'user_id', 'id'); } } 更新: $task = Task::find(1); $task->name='最新測試'; $task->save();

 

若是僅僅須要關聯表的部分字段,則能夠使用閉包,但字段中必須包含該關聯表的主鍵,如
$users = User::with(['tasks'=>function($query){
  return $query->select('id', 'task_name');
}])->get();sql

相關文章
相關標籤/搜索