今回は多対多のリレーションテーブルを作って、リレーション先のデータを取得するようにしてみます!
objectで取得できるものをarray(配列)でも取得してみようと思います!
中間テーブルの命名規則とかにもちょっとはまってしまった。。。
それでは行ってみよーー (oノ´3`)ノ ピューーン!!
参考
https://readouble.com/laravel/8.x/ja/eloquent-relationships.html
Table of Contents
tableを作る
table概要
一旦こんな感じのテーブルを作ります↓
- usersテーブル
id | name | age |
---|---|---|
1 | 山田 | 17 |
2 | 田中 | 18 |
3 | 中本 | 17 |
4 | 井出 | 16 |
- clubsテーブル
id | name |
---|---|
1 | 野球 |
2 | サッカー |
3 | 柔道 |
4 | バスケ |
そして、上記のテーブルをつなぐ中間テーブルを作成します。
- club_userテーブル
id | user_id | club_id |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 2 | 2 |
4 | 4 | 3 |
説明をすると、userは複数のclubに所属できるようになっています。
clubは複数のuserを所属させることができます。
これが多対多のリレーションになっています。
ほい、ではここからテーブルを作っていきましょう
tableの作成
table作成コマンド
※中間テーブルを作成するときの命名規則にも注意してください。
//table作成時table名は複数系にする必要がある。 例) create_user_tableはダメ×
php artisan make:migration create_users_table
php artisan make:migration create_clubs_table
//中間テーブルは対象のテーブルを単数形にして作成。 今回の場合はclubsテーブルとusersテーブルを合わせてclub_user
//tableの順番はアルファベット順 clubのc userのu で考える
php artisan make:migration create_club_user_table
Code language: JavaScript (javascript)
usersテーブルとclubsテーブルの作り方はここではスキップ
database/migrations/yyyy_mm_dd_xxxxxx_create_club_user_table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateClubUserTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('club_user', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id')->comment('ユーザーID');
$table->unsignedBigInteger('club_id')->comment('クラブID');
//外部キー
$table->foreign('user_id')->references('id')->on('users')->onUpdate('cascade')->onDelete('cascade')->comment('');
$table->foreign('club_id')->references('id')->on('clubs')->onUpdate('cascade')->onDelete('cascade')->comment('');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('club_user');
}
}
Code language: HTML, XML (xml)
Modelにリレーションの設定
多対多のリレーションしますよーっていうのをModelに書きます。
使うのはBelongsToManyです。
↓参考
https://readouble.com/laravel/8.x/ja/eloquent-relationships.html#many-to-many
もしModelが作成されていなかったら以下コマンド
//model名はアッパーキャメル記法で書く ex. User, TestUser
php artisan make:model {Model名}
Code language: JavaScript (javascript)
app/Models/User.php
//追加↓
public function clubs()
{
return $this->belongsToMany(Club::class);
}
Code language: PHP (php)
app/Models/Club.php
//追加↓
public function users()
{
return $this->belongsToMany(User::class);
}
Code language: PHP (php)
はい!これで準備は完了!
リレーション先の取得
とりあえずリレーション先を取得しようと思いますが、データが入ってない…
今回は面倒なのでとりあえずseeder使ってダミーデータ入れることにしまス。
seederの使い方は以下からどうぞ
https://yama-weblog.com/create-dummy-data-using-seeder-in-laravel8/
ほい、そしたら取得していきましょう。
データは最初に確認したtableのデータが入っているとしましょう。
そして以下のようにして対象ユーザが所属するクラブを取得してみました。
ほかにも取得方法はいろいろあるので試してみましょう!
//Requestではuserのidを投げている。
//pluck('name')= clubsテーブルのnameカラムを指定して取得。
//toArray() = オブジェクトとして帰ってくるので配列にして返すようにする。
$clubs = User::find($request->id)->clubs()->pluck('name')->toArray();
return $clubs;
Code language: PHP (php)
その他の取得方法
すべてのリレーションはクエリビルダとしても機能するため、rolesメソッドを呼び出し、クエリに条件をチェーンによりつなげることで、リレーションのクエリへさらに制約を追加できます。
$roles = User::find(1)->roles()->orderBy(‘name’)->get();
公式より https://readouble.com/laravel/8.x/ja/eloquent-relationships.html#many-to-many
はい、こんな感じでいろいろやり方はありますね~
まとめ
今回少し時間がかかったところは、
- 多対多の中間テーブルの命名規則を無視した書き方をしていてエラーで困っていた。
- objectでは取得できたけど、配列でデータを取得方法につまった。
以上2点にすこし時間がかかりました。