0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravel リレーションのまとめ(一対多 多対多 )

Posted at

リレーションについて毎回調べてしまっていることが多いので、内容整理として。
(随時更新)

前提

バージョン:Laravel6

一対多

①一対多とは

一対多のリレーションとは、あるmodelインスタンス一つ(ModelA)に対して複数のmodelインスタンス(ModelB)が紐づく関係のこと。その「紐づき」にあたるものが外部キー。あるModelAインスタンスには複数のModelBインスタンスが紐づくが、あるModelBインスタンスは特定のModelAインスタンスにだけ紐づく。

②migration

create_model_a_table.php
//ModelAマイグレーション
public function up()
{
    Schema::create('model_a', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name');
        $table->timestamps();
    });
}
create_model_b_table.php
//ModelBマイグレーション
public function up()
{
    Schema::create('model_b', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->unsignedBigInteger('model_a_id'); // 外部キー
        $table->string('name');
        $table->timestamps();
        
        // 外部キー制約
        $table->foreign('model_a_id')->references('id')->on('model_a')->onDelete('cascade');
    });
}

外部キー制約はforeign('外部キー')->references('参照先のカラム')->on('参照テーブル')と記述する。
onDelete('**')はデータ削除時の振舞いを指定するもの。

  • cascade:参照先が削除されると、共に削除される。
  • set null:参照先が削除されると、外部キーがnullになる。
  • restrict:参照先が削除されると、エラーを返す。

③model

ModelA.php
// このインスタンスに紐づくModelBインスタンス
public function modelBs() {
    return $this->hasMany(ModelB::class);
}

// このインスタンスに紐づくインスタンスの数を取得する。
public function loadRelationshipCounts() {
    $this->loadCount('modelBs');
}
ModelB.php
// このインスタンスに紐づくModelAインスタンス
public function modelA() {
    return $this->belongsTo(ModelA::class);
}

多対多

①多対多とは

多対多のリレーションとは、あるmodelインスタンス群(ModelC)に対して複数のmodelインスタンス群(ModelD)が紐づく関係のこと。一対多とは異なり、あるModelCインスタンスが複数のModelDインスタンスと紐づくだけでなく、あるModelDインスタンスが複数のModelCインスタンスと紐づくことができる。
多対多を実現するには中間テーブルを用いる。

②migration

create_model_c_table.php
//ModelCマイグレーション
public function up()
{
    Schema::create('model_c', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name');
        $table->timestamps();
    });
}
create_model_d_table.php
//ModelDマイグレーション
public function up()
{
    Schema::create('model_d', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('name');
        $table->timestamps();
    });
}
create_relay_c_d_table.php
//中間テーブルマイグレーション
public function up()
{
    Schema::create('relay_c_d', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->unsignedBigInteger('model_c_id'); // 外部キー
        $table->unsignedBigInteger('model_d_id'); // 外部キー
        $table->string('name');
        $table->timestamps();
        
        // 外部キー制約
        $table->foreign('model_a_id')->references('id')->on('model_c')->onDelete('cascade');
        $table->foreign('model_a_id')->references('id')->on('model_d')->onDelete('cascade');
    });
}

外部キー制約はforeign('外部キー')->references('参照先のカラム')->on('参照テーブル')と記述する。
onDelete('**')はデータ削除時の振舞いを指定するもの。

  • cascade:参照先が削除されると、共に削除される。
  • set null:参照先が削除されると、外部キーがnullになる。
  • restrict:参照先が削除されると、エラーを返す。

③model

ModelC.php
// このインスタンスに紐づくModelDインスタンス
public function modelDs() {
    return $this->belongsToMany(ModelB::class, 'relay_c_d', 'model_c_id', 'model_d_id')->withTimestamps();
}

// このインスタンスに紐づくインスタンスの数を取得する。
public function loadRelationshipCounts() {
    $this->loadCount('modelDs');
}
ModelD.php
// このインスタンスに紐づくModelCインスタンス
public function modelCs() {
    return $this->belongsToMany(ModelC::class, 'relay_c_d', 'model_d_id', 'model_c_id')->withTimestamps();
}

// このインスタンスに紐づくインスタンスの数を取得する。
public function loadRelationshipCounts() {
    $this->loadCount('modelCs');
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?