image — 画像ファイルであることを検証するルール

validation
  • カテゴリ: validation
  • 掲載バージョン: Laravel 12・PHP 8.4
  • 名前空間 / FQCN / コマンド: validation rule image
  • 関連: file / mimes / mimetypes / dimensions / extensions
  • 変更履歴: 旧バージョンでは JPEG 判定まわりの不具合報告あり(Laravel 8 以降で MIME 判定が改善)(Qiita)

要点(TL;DR)

  • 何に使うか:アップロードされたファイルが「画像ファイルかどうか」をサクッと判定したいときに使う。(Laravel)
  • 最低限の使い方$request->validate([ 'avatar' => ['required', 'image'], ]);
  • よくある罠
    • <form>enctype="multipart/form-data" を付け忘れて常に失敗する
    • image だけだとサイズ・拡張子・縦横比などは制限されない
    • PHP / サーバーのアップロード制限で「The file failed to upload.」になる(Qiita)

概要

image ルールは、アップロードされたファイルが一般的な画像 MIME タイプ(jpeg, png, bmp, gif, webp, svg 等)かどうかを検証します。(Laravel)
画像アップロードフォームのバリデーションでほぼ必須となる基本ルールで、maxdimensions などと組み合わせて使うのが実務では一般的です。(Laravel News)

構文 / シグネチャ

// シンプルな書き方
'field' => 'image';

// 配列記法
'field' => ['image'];

// 他ルールとの組み合わせ
'field' => ['required', 'image', 'max:2048'];

引数

image ルール自体には引数はありません。

引数必須既定値説明
なしimage は単独で完結するルール

戻り値

  • : bool(バリデーション内部的には true/false
  • 意味: 対象フィールドが「アップロードされた画像ファイル」であれば true。そうでなければ false となり、通常は ValidationException が投げられます。

例外 / 副作用

  • 例外
    • コントローラで $request->validate() を使うと、失敗時に Illuminate\Validation\ValidationException がスローされ、直前ページへリダイレクト+エラーメッセージがフラッシュされる。(Laravel)
  • 副作用
    • アップロードそのものは PHP/SAPI が行う。image ルールは「アップロード済みの一時ファイル」を検査するのみ。

使用例

最小例

ユーザーのアイコン画像をアップロードする簡単な例。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ProfileController extends Controller
{
    public function update(Request $request)
    {
        // バリデーション
        $validated = $request->validate([
            'avatar' => ['required', 'image'], // 画像ファイルであることだけを保証
        ]);

        // ファイル保存(storage/app/public/avatars に保存)
        $path = $request->file('avatar')->store('avatars', 'public');

        // ユーザー情報を更新
        $request->user()->update([
            'avatar_path' => $path,
        ]);

        return back()->with('status', 'プロフィール画像を更新しました。');
    }
}
<!-- Blade 側のフォーム例 -->
<form method="POST" action="{{ route('profile.update') }}" enctype="multipart/form-data">
    @csrf
    <input type="file" name="avatar" accept="image/*">
    <button type="submit">保存</button>
</form>

ポイント:

  • <form>enctype="multipart/form-data" を必ず付与
  • accept="image/*" はフロント側の補助(バリデーションには依存しない)

実務例:サイズ・拡張子・縦横比をまとめてチェック

サムネイル画像として横長(16:9)、2MB までの JPEG/PNG のみ許可する例。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Validation\Rules\File;

class PostController extends Controller
{
    public function store(Request $request)
    {
        $validated = $request->validate([
            'title'   => ['required', 'string', 'max:255'],
            'content' => ['required', 'string'],
            'thumbnail' => [
                'required',
                'image',                 // 画像であること
                'mimes:jpeg,jpg,png',    // 拡張子・MIME を限定
                'max:2048',              // 2MB まで(KB 単位)
                'dimensions:ratio=16/9', // 16:9 のみ許可
            ],
        ]);

        $path = $request->file('thumbnail')->store('thumbnails', 'public');

        // DB 保存など
        // Post::create([...]);

        return redirect()->route('posts.index')
            ->with('status', '記事を登録しました。');
    }
}
  • image だけでは「画像っぽいファイル」かどうかしか判定しないため、mimes / max / dimensions と組み合わせるのが定番です。(Laravel Daily)

よくある落とし穴・注意

  • フォームの enctype を忘れている
    • multipart/form-data がないと、サーバー側にはファイルが届かず image 以前に required で落ちます。
  • ファイルサイズ制限は別ルール
    • image にはサイズ制限は含まれません。max:2048 などを明示的に指定する必要があります。(Stack Overflow)
  • MIME と拡張子の制御
    • 画像であれば何でも良いのか、JPEG/PNG のみにしたいのかで mimes / mimetypes を併用します。
  • PHP / Web サーバーのアップロード制限
    • upload_max_filesize / post_max_size / client_max_body_size(Nginx)などで制限を超えると、Laravel 側では「The file failed to upload.」になりがちです。(Qiita)
  • 古い Laravel で JPEG 判定バグ
    • 7 以前では image ルールと JPEG 周りに不具合がある報告があり、mimes:jpeg,jpg,png,... を明示することで回避するケースがありました。Laravel 8+ / 12 では改善済みです。(Qiita)

代替・関連APIとの比較

ルール役割主な使いどころ
image画像ファイルであるかどうか(共通の画像 MIME)「とりあえず画像かどうか」を判定したいときの基本
fileアップロードされたファイル全般画像以外(PDF, ZIP など)も扱う場合のベース
mimes:jpeg,png,...拡張子 / MIME を限定許可する形式を厳密に制御したいとき
mimetypes:image/jpeg,...正確な MIME タイプ指定API など MIME を厳格にチェックしたいとき
dimensions画像の幅・高さ・比率を制御サムネイル・バナーなど、デザイン上の制約がある画像

選び方の目安

  • 「画像かどうか」だけで良い → image
  • 「JPEG/PNG だけ」など形式も制限したい → image + mimes
  • 「サムネイルは 16:9 だけ」などレイアウト前提 → image + dimensions
  • 「画像も含めファイル全般を扱うフォーム」 → file と条件分岐 or フィールド分割

テスト例(Pest)

<?php

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Validator;

it('accepts valid image file', function () {
    $file = UploadedFile::fake()->image('avatar.jpg', 300, 300);

    $validator = Validator::make(
        ['avatar' => $file],
        ['avatar' => ['required', 'image']]
    );

    expect($validator->passes())->toBeTrue();
});

it('rejects non-image file', function () {
    $file = UploadedFile::fake()->create('document.pdf', 100, 'application/pdf');

    $validator = Validator::make(
        ['avatar' => $file],
        ['avatar' => ['required', 'image']]
    );

    expect($validator->fails())->toBeTrue();
});

トラブルシュート(エラー別)

症状/エラー原因対処
The avatar must be an image.image ルールに失敗。そもそもファイルが画像ではない/アップロードされていない対象フィールド名の確認、enctype 設定、accept="image/*" で UI 補助
The file failed to upload.PHP / Web サーバー側のアップロードサイズやタイムアウト制限に抵触php.iniupload_max_filesizepost_max_size、Nginx/Apache 側の制限を見直す(Qiita)
null なのにエラーになるフィールドが任意なのに nullable を付けていないルールに nullable を追加(`nullable
JPEG なのにエラーになる(古い案件)古い Laravel バージョンで JPEG 判定まわりのバグLaravel をアップデート、または mimes:jpeg,jpg,png,... を明示的に追加(Qiita)

参考リンク

レン (Wren)

こんにちは。レンです。

Laravelのコードの森に住んでいる、小さな案内役です。
ルーティングの枝やクラスの影を歩きながら、コードの流れや仕組みを眺めています。

このサイトでは、Laravelの基本から実装のコツまで、開発で役立つポイントを静かに整理しています。
難しいことを増やすのではなく、コードの見通しが少し良くなるヒントを届けるのが役目です。

「この処理はどこに書くのがいいのか」
「Laravelではどう考えると整理できるのか」

そんな疑問に、小さなメモを残すような気持ちで記事を書いています。

コードを書いている途中で迷ったとき、
このサイトが少し立ち止まって整理できる場所になればうれしいです。

レン (Wren)をフォローする