【Laravel】Eloquent のリレーションで関連モデルの最新データを簡単に取得できます

こんにちは。今回はEloquentのリレーションを使用して関連するテーブルの最新の1件を取得する方法を解説していきます。

アプリケーションの要件として以下のようなものが出てきたときに役に立ちます。

  • ユーザーの最新の購入商品を表示する
  • 記事に対する最新のコメントを表示する

こういった要件は意外と多いですよね。SQLで実現しようとすると副問合せを駆使して実装することになるのですが、Eloquentを使うと簡単な記述で実装することができます。それでは見ていきましょう。

やりたいこと

ユーザーが最も最近購入した商品を取得します。

テーブル構成を説明します。usersとordersに分かれており、orderにはuserの商品購入履歴が登録されています。2つのテーブルはuserのidで関連付けることができます。

idnameemail
1joejoe@xxx.xxx.xxx
usersテーブル
iddateuser_idkingakushouhin
12021-08-0713000Book A
22021-08-0812000Book B
ordersテーブル

実装する

ordersテーブルを作る

まずはordersテーブルをマイグレーションで作成します。

$ php artisan make:migration create_orders_table
Created Migration: 2021_08_07_234840_create_orders_table
public function up() {
    Schema::create('orders', function (Blueprint $table) 
        $table->id();
        $table->date('date');
        $table->integer('user_id');
        $table->integer('kingaku');
        $table->string('shohin', 30);
        $table->timestamps();
    });
}

テーブルができたら冒頭で記述したデータを作成しておきます。

Eloquentモデルを作る

テーブルができたらEloquentモデルを作成します。Userモデルはインストール時から存在しますので、Orderモデルのみ作成します。

$ php artisan make:model Order
Model created successfully.

リレーションを張る

Userモデルにリレーションを作成します。まずは最新の「1件」を取得するためhasOneを指定します。その次に、「最新」のレコードを取得するためlatestOfManyをチェーンでつなげて指定します。

      public function LatestOrder(){
          return $this->hasOne(Order::class)->latestOfMany();
      }

使ってみる

作成したモデルを使ってユーザーの最新の購入を取得してみましょう。tinkerを使用して実行します。

id=1のユーザーをfindメソッドで取得し、LatestOrderをチェーンで指定します。すると、id=1のユーザーの最新の購入が取得できます。

>>> App\Models\User::find(1)->LatestOrder
=> App\Models\Order {#4352
     id: "2",
     date: "2021-08-08",
     user_id: "1",
     kingaku: "2000",
     shohin: "Book B",
     created_at: null,
     updated_at: null,
   }

まとめ

いかがでしょうか。最新の1件を簡単に取得することができました。クエリビルダで同じことをしようとすると、副問合せを使う必要がありかなり面倒ですが、Eloquentで作ると簡単ですね。

この他にも「最も古い1件」や「購入金額が最も大きい1件」なども同じように実装することができます。詳細は公式ドキュメントのHas One of Manyの部分を参照してください。(https://readouble.com/laravel/8.x/ja/eloquent-relationships.html

Laravel

Posted by kobainmac