1.

Laravel Eloquent モデル作成完全ガイド

編集
この記事の要点
  • 基本コマンド: php artisan make:model Postapp/Models/Post.php が生成される
  • -m でマイグレーション、-c でコントローラ、-mc で両方、-mcr で Resource Controller、-a で全部 (Factory / Seeder / Policy も)
  • $fillable でマスアサインメント許可、$guarded で逆に禁止項目を指定 (空配列 = 全て許可)
  • $casts で属性の型変換 (datetime / json / array / boolean / encrypted / Carbon)
  • $hiddentoArray() / toJson() から除外 (パスワード列の漏洩防止)
  • リレーション: hasMany / belongsTo / belongsToMany / hasOneThrough / morphMany
  • Accessor / Mutator は Laravel 9+ から Attribute クラスベース

artisan make:model コマンド

Laravel Eloquent モデルは Artisan コマンドで生成します。最小はmake:model のみですが、関連ファイル一括生成のオプションが豊富です。

# モデルのみ生成 (app/Models/Post.php)
php artisan make:model Post

# モデル + マイグレーション
php artisan make:model Post -m

# モデル + マイグレーション + コントローラ
php artisan make:model Post -mc

# Resource Controller (index/store/show/update/destroy が雛形)
php artisan make:model Post -mcr

# モデル + Factory
php artisan make:model Post -f

# モデル + Seeder
php artisan make:model Post -s

# モデル + Policy (認可)
php artisan make:model Post --policy

# 全部入り (migration + controller + factory + seeder + policy + form-request)
php artisan make:model Post -a

# サブディレクトリ (app/Models/Blog/Post.php)
php artisan make:model Blog/Post

生成されるファイル

テーブル名とプライマリキー

マスアサインメント: $fillable / $guarded

 'Hello',
    'body' => '...',
    'is_admin' => true,   // ← $fillable に無いので無視される (MassAssignmentException も出ない)
]);

$casts: 型変換

 'boolean',
        'amount'       => 'integer',
        'tax_rate'     => 'decimal:2',
        'options'      => 'array',      // JSON ↔ PHP array
        'metadata'     => 'object',     // JSON ↔ stdClass
        'paid_at'      => 'datetime',   // → Carbon インスタンス
        'paid_at_jst'  => 'datetime:Y-m-d H:i:s',
        'token'        => 'encrypted',  // 自動で暗号/復号
        'status'       => OrderStatus::class,  // Enum (Laravel 9+)
    ];
}

$order = Order::find(1);
$order->is_paid;       // (bool) true
$order->options;       // array
$order->paid_at;       // Carbon\Carbon
$order->paid_at->format('Y-m-d');

$hidden / $visible: シリアライズ制御

first_name} {$this->last_name}";
    }
}

リレーション

hasMany(Post::class);
    }

    // 1:1
    public function profile() {
        return $this->hasOne(Profile::class);
    }

    // 多対多 (中間テーブル必要: post_tag)
    public function tags() {
        return $this->belongsToMany(Tag::class)
            ->withPivot('order')
            ->withTimestamps();
    }
}

class Post extends Model
{
    // 逆 (Post belongs to User)
    public function user() {
        return $this->belongsTo(User::class);
    }

    // ポリモーフィック
    public function comments() {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

// 利用
$user = User::with(['posts', 'profile'])->find(1);
foreach ($user->posts as $post) {
    echo $post->title;
}

// 関連を追加
$user->posts()->create(['title' => 'Hi']);
$user->tags()->sync([1, 2, 3]);

Accessor / Mutator (Laravel 9+ Attribute クラス)

 "{$this->first_name} {$this->last_name}",
            set: fn ($value) => [
                'first_name' => explode(' ', $value)[0],
                'last_name'  => explode(' ', $value)[1] ?? '',
            ],
        );
    }

    // 旧スタイル (8 以前) - getXxxAttribute / setXxxAttribute
    public function getEmailAttribute(string $value): string {
        return strtolower($value);
    }

    public function setEmailAttribute(string $value): void {
        $this->attributes['email'] = strtolower($value);
    }
}

$user = User::find(1);
echo $user->full_name;   // get で計算
$user->full_name = 'Alice Smith';
// → first_name='Alice', last_name='Smith' にセット

スコープ (Local / Global)

where('status', 'published');
    }

    public function scopeByAuthor($query, int $userId) {
        return $query->where('user_id', $userId);
    }
}

// 利用
Post::published()->byAuthor(5)->get();

// Laravel 12+ では Attribute と同様に scope() static で書ける

ライフサイクルイベント

slug = Str::slug($post->title);
        });

        // 削除時にキャッシュクリア
        static::deleted(function (Post $post) {
            Cache::forget("post.{$post->id}");
        });
    }
}

// または Observer クラスに切り出す: php artisan make:observer PostObserver --model=Post

Soft Delete (論理削除)

softDeletes(); 必要

Post::find(1)->delete();           // deleted_at にタイムスタンプ
Post::withTrashed()->find(1);      // 削除済も含めて取得
Post::onlyTrashed()->get();        // 削除済のみ
Post::find(1)->restore();          // 復元
Post::find(1)->forceDelete();      // 物理削除

FAQ

Q: モデル名の規則
A: 単数形 PascalCase (Post) 推奨。テーブル名は自動で複数形 snake_case (posts) に。

Q: Models ディレクトリに置きたくない
A: Laravel 8+ は app/Models/ がデフォルト。古い慣習で app/ 直下に置きたい場合は --directory=app 不可、手動移動 + namespace 変更が必要。

Q: マイグレーションを再生成したい
A: make:model ではマイグレーションを上書きしません。既存マイグレーションを編集するか、削除して make:migration で新規作成。

Q: TypeScript の型生成も自動化したい
A: spatie/laravel-typescript-transformerblueprint パッケージで Eloquent → TS 型を生成可能。フロント連携で便利。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. モデルの作成
  2. $fillable $guarded $hiddenの説明
  3. テーブルの紐づけ
  4. 主キーの指定とインクリメント
  5. タイムスタンプ
  6. モデルでselect
  7. モデルでinsert
  8. モデルでupdate
  9. 現在値に加算する方法
  10. created_at/updated_atの別名指定