Laravel8でリレーションがうまくいかない・機能しない時に確認すべきこと
435 回閲覧されました
みなさんこんにちは、jonioです。
Laravelでリレーションをしている時にうまくいかなくて相当苦労したのでリレーションが効かない時に確認すべき内容の解説をします。
目次
Laravelのバージョン
8系です、7系以下だと書き方が若干違うと思います。
9系・10系はリレーションの書き方が変わってないなら今回の内容は対応すると思います。
今回登場するテーブル
今回登場するテーブル名はusersテーブルとrole_typesテーブルです。
usersテーブルはユーザー情報が入っているテーブルでrole_typesテーブルは権限が入っているテーブルです。
1つの権限に色んなユーザーを紐づかせようとしています、だから親テーブルがrole_typesテーブルで子テーブルがusersテーブルになります。
カラム名とデータ型は以下になります。
下記はusersテーブルです。
マイグレーションファイルは下記です。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
//role_type_idを追加した時のマイグレーションファイル
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddRoleTypeIdToUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->unsignedBigInteger('role_type_id')->after('email');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('role_type_id');
});
}
}
下記はrole_typesテーブルです。
マイグレーションファイルは下記です。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateRoleTypesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('role_types', function (Blueprint $table) {
$table->id();
$table->string('role_type');
$table->boolean('hidden')->default(false);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('role_types');
}
}
それでは見た方がいい所の解説をします。
子テーブルに親テーブルのカラムはあるか
子テーブルのカラムに「親テーブル名_id」がないとリレーションが機能しません。
だから今回の解説では「role_type_id」がusersテーブルに必要になります。
カラムの型名は正しいか
親テーブルがrole_typesで子テーブルがusersなのでusersテーブルにはrole_type_idカラムが必要になりますがデータ型に注意しないといけません。
usersテーブルのrole_type_idカラムとusersテーブルのidカラムを対応させるのでrole_type_idカラムのデータ型をintegerにしそうですがやってはいけません。
マイグレーションファイルにも記載していますがリレーションする時のデータ型は「unsignedBigInteger」です。
belongsTo・hasManyなどの書き方は正しいか
リレーションする時にモデルにbelongsTo・hasMany・hasOne・belongsToManyを書きますが下記の書き方を見かけたことがあります。
public function roleType(){
return $this->belongsTo('App\Modes\RoleType');
}
「App\Modes\モデル名(RoleTypeにしています)」はダメです、正解は下記です。
public function roleType(){
return $this->belongsTo('RoleType::class');
}
理由は分からないですがダメな書き方をするとリレーションが効いたり効かなかったりする場合がありました。
メソッド名は正しいか
モデルに書くメソッド名は名称のルールがあります。
今回親テーブルがrole_typesで子テーブルがusersですが例えばrole_typesテーブル(親テーブル)のモデルにメソッドを記述する時の名称は下記にしないといけません。
public function users(){
return $this->hasMany('User::class');
}
メソッド名の「users」は「子テーブル名s」にしないとリレーションが動作しません。
usersテーブル(子テーブル)のモデルにメソッドを記述する時は下記にしないといけません。
public function roleType(){
return $this->belongsTo('RoleType::class');
}
メソッド名の「roleType」は「親テーブル名」(sはつけません)にしないとリレーションが動作しません。
また「role_types」テーブルみたいに複数の単語を「_」でつないでいる場合は2語目以降の最初の文字を大文字にしないといけません。(今回はtypesのtを大文字にしています)
他にも見つかったら情報を追記します。