ブログ
Laravelのリレーション整理:1対1のリレーション【hasOneとbelongsTo】
前回のブログでLaravelにはとても便利な ORM(Eloquent)があらかじめ用意されています!と紹介しましたが、このEloquentのリレーションについて掘り下げてみたいと思います🖋️
Laravelのリレーションの定義方法
リレーション定義はModel内で設定します。リレーションは以下に分類されます。
- 1対1
- 1対多
- 多対多
それぞれのリレーション定義について整理してみます。
1対1、1対多
親となる側にhasOne(1対1), hasMany(1対多)を、子となる側にbelongsTo(1対1, 1対多)を定義することで、どちらが親子関係にあるのかを定義することができます。
親モデル側の定義 | 子モデル側の定義 | |
---|---|---|
1対1 | hasOne | belongsTo |
1対多 | hasMany | belongsTo |
親モデルが子モデルを何個持っているか、という感じになるのでhasOneが主(親)であることがわかりやすいですね!
一方、子モデルには従属という意味のbelongsToを定義します。
多対多
多対多の場合は中間テーブルを設ける必要があります。
その中間テーブルに紐づけるモデルそれぞれにbelongsToManyを定義します。
モデル1 | モデル2 | |
---|---|---|
多対多 | belongsToMany | belongsToMany |
複数ひもづくので複数に従属するbelongsToManyとなります。
定義方法について、まず今回は、hasOneのリレーションについて整理してみたいと思います🖋️
1対1のリレーション(hasOne)
前提
今回は従業員🙎と、会社で貸与しているPC💻を例にします。
会社が貸与するPCは一人につき1台🧑💻とします。
DB定義
DB構造は以下のようになります。
従業員テーブル🙎
カラム名 | コメント |
---|---|
id | 従業員ID |
staff_code | 従業員コード |
name | 従業員名 |
PCテーブル💻
カラム名 | コメント |
---|---|
id | PCID |
employee_id | 従業員ID |
owner_code | 所有者コード |
モデル定義
従業員モデル🙎(親)
この『一従業員に対しPCは一台しか貸与しない』という関係をEmployeeモデル内にpcメソッドで定義するため、hasOneメソッドを使用します。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Employee extends Model
{
/**
* 従業員に貸与しているPCの取得
*/
public function pc()
{
return $this->hasOne(Pc::class);
}
}
ここでhasOneメソッドを使用することで、引数で渡したクラスのモデルを1つだけ返してくれるようになります。
hasOneメソッドに渡す最初の引数は、関連するモデルクラスの名前です。
hasOneメソッドはオプションで第3引数まで設定できます。
上記は、第2引数や第3引数を省略することで、pcテーブルのemployee_idが紐づくよう規約で自動的にリレーションしてくれます。
第2引数や第3引数を設定することで、リレーションするカラムの紐付けを指定するよう設定が可能です。
- 第1引数
- 関連するモデルクラスの名前を設定します。
第1引数のみを指定している場合は、子モデルに設定されている親モデル名_id
のカラムと紐付けします。
- 関連するモデルクラスの名前を設定します。
- 第2引数
- 子モデルの外部キーを指定することができます。例えば、pcs.owner_code を紐づけたいときは、以下のように指定します。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Employee extends Model
{
/**
* 従業員に貸与しているPCの取得
*/
public function pc()
{
// employee_id 以外の外部キーに(owner_code を外部キーに指定)したい時
return $this->hasOne(Pc::class, 'owner_code');
}
}
- 第3引数
- 親モデルのキーを指定することができます。 例えば、employees.id ではなく、employees.staff_code をキーにして紐づけたいときは、以下のように指定します。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Employee extends Model
{
/**
* 従業員に貸与しているPCの取得
*/
public function pc()
{
// employee_id 以外の外部キーにし、さらに親モデル側のキーを employees.staff_code に設定したいとき
return $this->hasOne(Pc::class, 'owner_code', 'staff_code');
}
}
PCモデル💻(子)
今度は『会社が貸与するPCは一人につき1台』という逆の関係の定義も必要なので、PCモデル側にも同様の定義をしていきます。 PCを貸与されている従業員へアクセスできるPCモデルのリレーションを定義するには、belongsToメソッドを使用します。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Pc extends Model
{
/**
* このPCを貸与している従業員の取得
*/
public function employee()
{
return $this->belongsTo(Employee::class);
}
}
employeeメソッドを呼び出す時の挙動は、
Pcモデルが持っているemployee_idカラムと同じidを持つEmployeeモデルを取得する
となります🧑💻
こちらも、前述のhasOneメソッド同様に第3引数まで指定することが可能で、同じく引数を指定することで外部キーのオーバーライドを設定することができます💡
- 第2引数
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Pc extends Model
{
/**
* このPCを貸与している従業員の取得
*/
public function employee()
{
// employee_id 以外の外部キーに(owner_code を外部キーに指定)したい時
return $this->belongsTo(Employee::class, 'owner_code');
}
}
- 第3引数
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Pc extends Model
{
/**
* このPCを貸与している従業員の取得
*/
public function employee()
{
// employee_id 以外の外部キーにし、さらに親モデル側のキーを employees.staff_code に設定したいとき
return $this->belongsTo(Employee::class, 'owner_code', 'staff_code');
}
}
まとめ
今回は、一番シンプルでとてもよく使う1対1のリレーションの定義方法をまとめてみました。
Eloquentの機能は便利なので、しっかり身につけてより活用していきたいと思っています。
次回は1対多について、書きたいなと思っています!
株式会社ウイングドアは福岡のシステム開発会社です。
現在、私達と一緒に"楽しく仕事が出来る仲間"として、新卒・中途採用を絶賛募集しています!
ウイングドアの仲間達となら楽しく仕事できるかも?と興味をもった方、
お気軽にお問い合わせ下さい!