【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'));
    }
}
Code language: HTML, XML (xml)

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で指定。
    }
}
Code language: HTML, XML (xml)

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);
    }
}

Code language: HTML, XML (xml)

そして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>
Code language: HTML, XML (xml)

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

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

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

命名規則に注意

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

メソッド名

以下の公式を参考に↓
Eloquent

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

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

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

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

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

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

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

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

ここで僕は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と紐づいている。');
    });
}
Code language: PHP (php)

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

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

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

//間違えた外部キー
$table->unsignedBigInteger('userName_id');
Code language: PHP (php)

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

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

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

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

public function {function_name}()
{
    return $this->belongsTo('{Models_name}', '{foreign_key}');
}
Code language: PHP (php)

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

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

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

まとめ

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

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

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

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA