【Laravelの命名規則に注意!】リレーション先のデータを取得する方法をやってみても取得できない!?

Laravel

今回はリレーション先のデータが欲しくて欲しくて、詰まっていたのでそれの取得方法を紹介していきます。

今回は命名規則に困らされたので、その辺も共有しますね。

現在のテーブル説明

現在以下のようなテーブルを持っているとします。

ユーザーテーブル

id(ID) user(名前) age(年齢)
1 山田 太郎 25
2 藤本 祐樹 26

コメントテーブル

id(ID) comment(コメント) user_id(ユーザとのリレーションID)
1 最近暑い 1
2 最近寒い 2

この時にコメントをすべて出力したいときに、そのコメントに紐づくユーザを取得したいわけです。

リレーション元のテーブルを取得したい!

ということでLaravel使ってやってみましょう。

リレーション元を取得していく。 ※命名規則に注意!

まずはController

<?php

namespace App\Http\Controllers\Comment;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Comment; //追記
use App\Models\User; //追記

class CommentController extends Controller
{
    //一覧表示
    public function index()
    {
        //with()の中にはModelsで作ったメソッド名を入れる。
        $logs = Log::with('user')->get();
        return view('comment.index', compact('logs'));
    }
}

CommentModel

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    use HasFactory;

    protected $table = "comment";

    protected $fillable = [
        'id',
        'comment',
        'user_id',
    ];

    public function user()
    {
        return $this->belongsTo(User::class); //リレーション元のモデルをbelongsToで指定。
    }
}

belongsToの使い方↓
逆の関係の定義

UserModel

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    use HasFactory;

    protected $table = "user";

    protected $fillable = [
        'id',
        'name',
        'age',
    ];

    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

そしてviewで表示していきます。

<table border="1">
    <tr>
        <td>ID</td>
        <td>ユーザ名</td>
        <td>コメント</td>
        <td>年齢</td>
    </tr>
    @foreach ($logs as $log)
    <tr>
        <td>{{$log->id}}</td>
        <td>{{$log->user->name}}</td>
        <td>{{$log->comment}}</td>
        <td>{{$log->age}}</td>
    </tr>
    @endforeach
</table>

こうすると、こんな感じで出力!

id(ID) ユーザ名 コメント 年齢
1 山田 太郎 最近暑い 25
2 藤本 祐樹 最近寒い 26

ほい!こんな感じで取得することができました!

命名規則に注意

Laravelを書くときには命名規則に注意です!僕は以下のようなところで詰まったので、もしあれ載っている通りにやっているはずなのに動かないというときはこんなところも注意してくださいね。

メソッド名

以下の公式を参考に↓
Eloquent

ここで注意したいのがfunctionの命名規則。

今回は1対多になっていますよね。そこで「ユーザ:コメント」の関係になるわけですが…

ユーザ側のModelでfunctionを定義するときは、function名を複数形にしましょう。

というのも、コメントは複数(多)だから。

というわけで、こう書く↓

//commentにするとうまく呼び出せない ユーザに対してコメントは「多」なので複数形のメソッド名
public function comments()
{
    return $this->hasMany(Comment::class);
}

そして、コメント側からは単数形で以下のように書きます。

//コメントに対して、userは「1」なので単数形
public function user()
{
    return $this->belongsTo(User::class); //リレーション元のモデルをbelongsToで指定。
}

ここで僕はusersという関数を作ってしまって全く動かず止まっていました…w

テーブル名

テーブル名にも少し注意が必要かもしれませんね。

public function up()
{
    Schema::create('comment', function (Blueprint $table) {
    $table->increments('id');
    $table->timestamps();
    $table->unsignedBigInteger('user_id');

    //外部キー
    $table->foreign('client_id')->references('id')->on('user')->comment('user_idはclientテーブルのIDと紐づいている。');
    });
}

こんな感じでmigrationファイルを作るとしますね。

もし、以下のように外部キーを作るとおかしくなります。

//現在の外部キー
$table->unsignedBigInteger('user_id');

//間違えた外部キー
$table->unsignedBigInteger('userName_id');

こうした時に[user]テーブルにたいして、[user_id]というカラムを持っていたら、リレーションの対応付けを勝手にLaravelは行ってくれるわけです。

しかし、[userName_id]カラムとなると、うまく[user]テーブルとの対応をうまくやってくれないようです。

基本的には[user]テーブルに対しては[user_id]というカラムを持つようにしましょう。

が、もしそれ以外の理由があるなら、以下の形式で、Modelで外部キーを指定しましょう。

public function {function_name}()
{
    return $this->belongsTo('{Models_name}', '{foreign_key}');
}

例として、[userName_id]とした場合には、以下の感じで指定します。

public function user()
{
    return $this->belongsTo(''App\Models\User', 'user_id');
}

これで、リレーションもうまいこと処理してくれて、viewでも取得できるようになります。

まとめ

今回は本当に命名規則に悩まされた一日となりました。

そこまで注意せずにどんどん作っていくとある時に困らされます。

フレームワークは命名規則に沿った関数名、フォルダ名とかで区別がされやすいので注意が必要ということがよくわかりました。

コメント

タイトルとURLをコピーしました