一.一對一 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