【Laravel】多対多の中間デーブルへダミーデータを挿入するシーダークラスの例

テーブルの多対多のリレーションを定義する場合、中間デーブルが必要となりますが、今回は、Laravelのシーディングで、中間テーブルの外部キーに、ダミーデータを挿入するシーダークラスの例となります。
また、テーブルの多対多のリレーションを定義する方法と、シーディングついては、以下のリンク先を参考にしてみてください。
【Laravel】多対多の中間デーブルへダミーデータを挿入するシーダークラスの例
例のシーダークラスでは、post_tagテーブル(中間テーブル)の外部キー(post_idとtag_idカラム)へ、外部キーが参照するpostsとtagsテーブルのそれぞれの主キー(idカラム)の値をランダムで取得し、forループを使って30件挿入します。
そのため、以下は準備されている前提としています。
- post_tagテーブル(中間テーブル)を用意し、複合主キーとして外部キーのpost_idとtag_idカラムがある状態
- postsテーブル、tagsテーブルを用意し、それぞれの主キー(idカラム)に値がセットされた状態
- postsテーブル、tagsテーブルのそれぞれのモデル
また、post_tagテーブルの外部キーは複合主キーのため、外部キーが参照するpostsとtagsテーブルのそれぞれのidカラムにセットされている値の総数は、複合主キーとして利用する際に重複しない数が必要となります。
シーダークラスの例
以下、中間テーブルの外部キーにダミーデータを挿入するシーダークラスの例となり、シーダークラス名は、PostTagSeederとしています。
<?php
use Illuminate\Database\Seeder;
class PostTagSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
for ($i = 0; $i < 30; $i++){
// postsとtagsテーブルのidカラムをランダムに並び替え、先頭の値を取得
$set_post_id = App\Post::select('id')->orderByRaw("RAND()")->first()->id;
$set_tag_id = App\Tag::select('id')->orderByRaw("RAND()")->first()->id;
// クエリビルダを利用し、上記のモデルから取得した値が、現在までの複合主キーと重複するかを確認
$post_tag = DB::table('post_tag')
->where([
['post_id', '=', $set_post_id],
['tag_id', '=', $set_tag_id]
])->get();
// 上記のクエリビルダで取得したコレクションが空の場合、外部キーに上記のモデルから取得した値をセット
if($post_tag->isEmpty()){
DB::table('post_tag')->insert(
[
'post_id' => $set_post_id,
'tag_id' => $set_tag_id,
]
);
}else{
$i--;
}
}
}
}
例のシーダークラスの説明
以下、forループ内の処理についての説明となります。
モデルから値を取得
ソースコード17行目からの箇所では、次の処理を行っています。
postsとtagsテーブルのモデルから、それぞれのidカラムをランダムに並び替え、先頭の値を取得し、それぞれ変数にセットします。
クエリビルダを利用して複合主キーの重複を確認
ソースコード21行目からの箇所では、次の処理を行っています。
クエリビルダのwhereメソッドを利用し、現在までの中間テーブルの複合主キー(post_idとterm_idカラム)の値に、上記でモデルから取得した値が存在するかを確認します。
中間テーブルの外部キーに値を挿入
ソースコード28行目からの箇所では、次の処理を行っています。
上記クエリビルダで取得したコレクションが空の場合に、post_idとterm_idカラムのフィールドに、最初にpostsとtagsテーブルのそれぞれのidカラムから取得した値を挿入します。
また、取得したコレクション内に値がある場合には、現在までの複合主キーの値と重複するので、現在のループでは値を挿入せずに、ループ回数のカウンターを1回減らしています。