2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【modeltyper】LaravelのModelの型も自動生成させて幸せになる(Type-Model編)

2
Last updated at Posted at 2025-12-02

前書き

Laravel 開発を極めてくると高確率で直面する問題。のつづき。
Model も型がつかないんですよねぇ...
(これによって、他の FW には無い特大魔法 マジックメソッド が使えるのですが。。)

とはいえ、それらには様々な解法が登場しています。
ららべらーで知らない人はモグリかもしれません。(言い過ぎ?)

基本的にこーいう系のツールは、今のDBのスキーマを取得して、それに対応する型を当てはめるものが多いです。

Laravel Data を使うと Resource を DTO として定義することはできるのですが、モデルの属性を手動で登録する必要があり、かなりの手間を感じます...

それなら、モデルも自動的に型を生成できればいいのでは?
スキーマだけではなく、リレーションも取得できると幸せですよね。

modeltyper

なんとできるんです。

modeltyper の凄いところは、殆ど設定せずにモデルの属性とリレーション、count exists などの特殊メソッドにまで対応しているところです。
さらには自動生成が難しい型の上書きにも対応しています。

PHP - TypeScript の型共有にて、うまくいかないところを愚直に吸収してくれるんですね。神。

他にも 7nohe さんが作成された laravel-typegen もおすすめです。
今回はシンプルさ命で採用したので、より肌にあうものを採用しましょ。

インストール

以下のパッケージをインストールしてください。
config がありますが、設定はCLIオプションで指定できるのでお好みで。

$ composer require --dev fumeapp/modeltyper

型の生成

今回も以下のようなブログポストを例にします。

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained('users');
    $table->string('title');
    $table->text('body');
    $table->timestamps();
});

Schema::create('post_tags', function (Blueprint $table) {
    $table->id();
    $table->foreignId('post_id')->constrained('posts');
    $table->string('name');
    $table->string('color')->nullable();
    $table->timestamps();
});  

各テーブルのモデルも予め作成しておきます。

$fillable は、利用者が手動で登録する可能性があるものを加えます。
リレーションは、どのカラムが紐づいているか分かりにくくなるため、個人的にはキーまで書くのがおススメです。
1テーブルに3列くらいユーザーと紐づくことあるからね...。

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $fillable = [
        'user_id',
        'title',
        'body',
    ];

    public function user()
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    public function tags()
    {
        return $this->hasMany(PostTag::class, 'post_id');
    }
}
use Illuminate\Database\Eloquent\Model;

class PostTag extends Model
{
    protected $fillable = [
        'name',
        'color',
    ];

    public function post()
    {
        return $this->belongsTo(Post::class, 'post_id');
    }
}

そしたら、上記モデルの型を生成していきます。

$ php artisan model:typer ./resources/js/types/model.d.ts

すると。。。

resources/js/types/model.d.ts
export interface Post {
  // columns
  id: number
  user_id: number
  title: string
  body: string
  created_at: string | null
  updated_at: string | null
  // relations
  user: User
  tags: PostTag[]
  // counts
  tags_count: number
  // exists
  user_exists: boolean
  tags_exists: boolean
}

export interface PostTag {
  // columns
  id: number
  post_id: number
  name: string
  color: string | null
  created_at: string | null
  updated_at: string | null
  // relations
  post: Post
  // counts
  // exists
  post_exists: boolean
}

export interface User {

...

これだけ。
簡単、お手軽、素晴らしい。

上書き

ここまでなら他にもあるんですけど、modeltyper はこの型情報を PHP 側から上書きすることができるのです!
例えば PostTag にある color 属性、赤青緑だけ指定できるんだけど...といった時も $interfaces という変数を作成して上書き定義することができます。
(例なので Enum 使えという意見は聞きません)

app/Models/PostTag.php
class PostTag extends Model
{
    protected $fillable = [
        'name',
        'color',
    ];

+   public array $interfaces = [
+       'color' => [
+           'type' => "'red' | 'blue' | 'green'",
+       ],
+   ];
    ...
resources/js/types/model.d.ts
export interface PostTag {
  // columns
  id: number
  post_id: number
  name: string
- color: string | null
  created_at: string | null
  updated_at: string | null
  // overrides
+ color: 'red' | 'blue' | 'green'
  // relations
  post: Post
  // counts
  // exists
  post_exists: boolean
}

スクリプトで強制上書きは簡単ですけど、PHP側から上書きできるので、書き換え忘れなどを防止できます。
素晴らしい。

有用な例としては、ポリモーフィズムを採用したときに、リレーション先のモデルクラスそれぞれを ModelA | ModelB で上書きする、が考えられますね。

おわりに

とはいえ、modeltyper はとてもシンプルなツールなので、かゆいところに手が届かないことが多いです。
その際は Artisan Commandsed などと組み合わせて、俺の最強の Model Type Generator を作成しましょう!

あ、ちなみに interfacetype どちらでも出力可能なので、宗教戦争にも対応しています!


さらに発展させたい場合はこちらをドゾ。

2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?