Ⓜ️

Eloquent Model の ID を ULID に指定する方法

2023/12/03に公開

こんにちは。 SAW です。
最近 Nintendo SwitchPlayStation 5 を購入しました。
マリオカート8 デラックスGran Turismo 7 などをプレイしたいなと思っています。

Eloquent Model の規約では、 ID は暗黙的に整数型にキャスト されます。
しかし、以前の記事で紹介したように、テーブルの ID を ULID に設定した場合は、モデルの ID も ULID に対応する型に変換 する必要があります。
https://zenn.dev/azuki_penguin/articles/59715b43ef3b70

本記事では、 Eloquent Model の ID を ULID に指定する方法を紹介します。
なお、本記事では Laravel のバージョンが 10.x 系 を前提としています。

対象読者

本記事で想定する読者層は次の通りです。

  • Laravel の基本的な知識を有している

前準備: テーブルのスキーマ定義

本記事の前準備として、 posts テーブルのスキーマを以下のように定義します。

posts テーブルのスキーマ定義
Schema::create('posts', function (Blueprint $table) {
    $table->ulid('id')->primary();
    $table->foreignUlid('author_id');
    $table->string('title');
    $table->string('content');
    $table->timestamps();
});   

Eloquent Model での ID の規約

公式ドキュメントの #primary-keys のセクションを確認すると、 Eloquent はデフォルトで primary key のフィールドは id で、整数型として扱われると記載されています。

ID を ULID にした場合、テーブル側は文字列型となります。
しかし、モデル側の id を取得すると、 整数型にキャスト されます。

前準備: テーブルのスキーマ定義 のセクションで定義した posts テーブルについて、実際に Eloquent Model から id プロパティを取得してみると、値は整数型にキャストされます。

以下は tinker で Post のプロパティの値と、 id プロパティを取得した出力結果です。
Post::first() の返却値を確認すると、 id には ULID の文字列が格納されていることがわかります。
しかし、 Post インスタンスの id プロパティにアクセスすると、 ULID の文字列の先頭部分 01 を整数型にキャストした 1 が返ってくることがわかります。

tinker での出力結果
> Post::first()
= App\Models\Post {#7008
    id: "01HGNMB0BXB3M8E1XT6W3C6WBN",
    author_id: "01HGNMB0B0C35Q6WZ8BJ61V574",
    title: "Optio ad qui velit ducimus molestiae magnam.",
    content: "Enim veniam hic earum animi expedita optio. Tempora nihil sed ut. Voluptatem sapiente recusandae harum cumque repudiandae.",
    created_at: "2023-12-02 16:03:44",
    updated_at: "2023-12-02 16:03:44",
  }

> Post::first()->id
= 1

Eloquent Model の ID を ULID に指定する方法

Eloquent Model の id プロパティで ULID を取得するには、 公式ドキュメントの #uuid-and-ulid-keys のセクションに記載されているように、 Illuminate\Database\Eloquent\Concerns\HasUlids trait を利用します。

Post クラスで HasUlids trait を利用するコード例は以下の通りです。

app/Models/Post.php
namespace App\Models;

use Illuminate\Database\Eloquent\Concerns\HasUlids;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasUlids;
}

再度 tinker で id プロパティを取得すると、今度は ULID の文字列が取得できていることが確認できました。

HasUlids trait を適用した後の tinker での出力結果
> Post::first()
= App\Models\Post {#7008
    id: "01HGNMB0BXB3M8E1XT6W3C6WBN",
    author_id: "01HGNMB0B0C35Q6WZ8BJ61V574",
    title: "Optio ad qui velit ducimus molestiae magnam.",
    content: "Enim veniam hic earum animi expedita optio. Tempora nihil sed ut. Voluptatem sapiente recusandae harum cumque repudiandae.",
    created_at: "2023-12-02 16:03:44",
    updated_at: "2023-12-02 16:03:44",
  }

> Post::first()->id
= "01HGNMB0BXB3M8E1XT6W3C6WBN"

まとめ

本記事のまとめは次の通りです。

  • Eloquent の id プロパティはデフォルトで整数型にキャストされる
  • HasUlids trait を利用することで id を ULID に対応する型に変換できる

Eloquent の id がデフォルトでは整数型にキャストされることが知れて勉強になりました。

参考文献

https://laravel.com/docs/master/eloquent

Discussion