🍣

Laravel 1対多 リレーション時、Modelの命名規則

2023/11/19に公開

以下のようなデータベースを作っていたのですが、Blog側からUserが呼べず頭を抱えました。結論から言うとModel内のメソッドに命名規則があるということです。なにが問題だったか記述していきます。
ER図

動作環境

PHP 8.2
Laravel 10

マイグレーション

usersのマイグレーションは初期設定のままです。

usersのマイグレーション
public function up(): void
{
    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();
    });
}

blogsはusersの外部キーを設定します。

blogsのマイグレーション
public function up(): void
{
    Schema::create('blogs', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->text('content');
        $table->foreignId('user_id')->constrained()->onDelete('cascade');
        $table->timestamps();
    });
}

リレーション

リレーションするには、ModelのUserとBlogに、メソッドを追加しなければなりません。

Userモデル

app/Models/User.php
use Illuminate\Database\Eloquent\Relations\HasMany;

public function blogs(): HasMany
{
    return $this->hasMany(Blog::class);
}

Blogモデル

Blogにメソッドを記述する際、usersと複数形を記述していますが、これが原因です。この状態でいくらUserを呼び出そうとしても、nullしか返してきません。

app/Models/Blog.php
use Illuminate\Database\Eloquent\Relations\BelongsTo;

public function users(): BelongsTo
{
    return $this->belongsTo(User::class);
}

解決方法

1対多なので、Blog側から呼び出すUserは単数形。ということで、usersではダメです。このメソッドはuserとして単数形にすれば、Blog側からUserを呼び出すことができます。

app/Models/Blog.php
use Illuminate\Database\Eloquent\Relations\BelongsTo;

- public function users(): BelongsTo
+ public function user(): BelongsTo
{
    return $this->belongsTo(User::class);
}

まとめ

リレーションするためのメソッドにも命名規則があるのですね。テーブル名がusersだから、メソッド名もusersでいいや、と思ってメソッドを書いて、痛い目を見ました。今後は、Laravelの命名規則もしっかり合わせていきます。

参考記事

https://yama-weblog.com/eloquent-relationships-in-laravel/

Discussion