LoginSignup
11
6

More than 3 years have passed since last update.

Laravelのmax file sizeのValidationメッセージでKBをMBにする方法

Last updated at Posted at 2020-04-29

概要

タイトル通りです。
max file sizeのValidationはデフォルトでKB表示になっているので、それをMBやGBに変更する方法を調べたので備忘録です。

環境

PHP: 7.2.22
Laravel: 6.18.3

事前準備

以下のようにRequestオブジェクトにvalidationのルールを記述すると「inputFile」フォームからアップロードするファイルの上限を1MBに設定します。

app/Http/Requests/FileUploadRequest.php
    public function rules()
    {
        return [
            'inputFile' => 'max:1024'
        ];
    }

1MB以上のファイルをアップロードした場合は以下のように「The input file may not be greater than 1024 kilobytes.」と表示されるので、これをメガバイト表示に修正していきます。
スクリーンショット 2020-04-12 16.37.19.png

設定変更

方法1: メッセージを固定する

一番手軽に解決できます。
該当のフォームがvalidationに引っかかった場合に表示するメッセージを〜megabytesで固定します。

app/Http/Requests/FileUploadRequest.php
    public function rules()
    {
        return [
            'inputFile' => 'max:1024'
        ];
    }

    public function messages()
    {
        return [
            'inputFile.max' => 'The input file may not be greater than 1 megabytes.'
        ];
    }

スクリーンショット 2020-04-12 16.58.11.png

方法2: カスタムValiationルールを作成する

方法1のやり方だと上限の1MBが2MB等に変更になったときにメッセージも都度修正しないといけないので面倒です。
なので、KBではなくMB表示できるような新しいvalidationのルールを作成します。
参考1(公式ドキュメント)
参考2(stack overflow)

app/Providers/AppServiceProvider.php
<?php

namespace App\Providers;

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

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        // max_mb ファイルサイズの最大値をメガバイトで指定するvalidationルールを追加する
        Validator::extend('max_mb', function ($attribute, $value, $parameters, $validator) {
            // パラメータ数のチェック
            $this->requireParameterCount(1, $parameters, 'max_mb');

            // アップロードに成功しているかの判定
            if ($value instanceof UploadedFile && ! $value->isValid()) {
                return false;
            }

            // ファイルサイズをMBに変換
            $megaBytes = $value->getSize() / 1024 / 1024;

            // $parametersにルールで設定した引数より小さければ問題なし
            return $megaBytes <= $parameters[0];
        });

        // validationメッセージ「The :attribute may not be greater than :max_mb megabytes.」の
        // 「:max_mb」部分をパラメータとして与えられた値と置き換える
        Validator::replacer('max_mb', function ($message, $attribute, $rule, $parameters) {
            return str_replace(':max_mb', $parameters[0], $message);
        });
    }

    /**
     * ルールに与えられるパラメータ数のチェックを行う
     *
     * @param integer $count
     * @param array $parameters
     * @param string $rule
     * @return void
     */
    protected function requireParameterCount($count, $parameters, $rule)
    {
        if (count($parameters) < $count) {
            throw new InvalidArgumentException("Validation rule $rule requires at least $count parameters.");
        }
    }
}
validation.php
    'max_mb' => 'The :attribute may not be greater than :max_mb megabytes.'

AppServiceProviderにValidationルールを書くのが嫌な場合は、新しくServiceProviderを作成してそっちに記述する必要があります。

方法3: ルールオブジェクトを作成する

方法2はLaravel5.4までで行われていた方法のようで、Laravel5.5以降はルールオブジェクトを作成することでのカスタムValidationルールの作成が可能でしたので、そちらも試します。
参考(公式ドキュメント)

まず、下記コマンドを実行します。

$ php artisan make:rule MegaBytes

app/Rules/MegaBytes.phpが作成されたので以下のように編集します。

MegaBytes.php
<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class MegaBytes implements Rule
{
    protected $param;

    public function __construct($param)
    {
        $this->param = $param;
    }

    public function passes($attribute, $value)
    {
        $megaBytes = $value->getSize() / 1024 / 1024;

        return $megaBytes <= $this->param;
    }

    public function message()
    {
        return trans('validation.max_mb', ['max_mb' => $this->param]);
    }
}

messageメソッドではtransヘルパーを利用して方法2と同様にvalidation.phpにメッセージを記述して、それを呼び出しています。
このルールを呼び出す時はForm Requestだと以下のように書けます。

<?php

namespace App\Http\Requests;

use App\Rules\MegaBytes;
use Illuminate\Foundation\Http\FormRequest;

//
// 中略
// 
    public function rules()
    {
        return [
            'inputFile' => [new MegaBytes(1)]
        ];
    }

方法4: Validator::replacerだけで値を修正する(2020/05/02追記)

コメントでご指摘いただきました。多謝。
方法2ではValidator::extendでvalidationルールを追加していますが、Validator::replacerだけでも同じような動作を実現できます。

Validator::replacer('max', function ($message, $attribute, $rule, $parameters) {
    return str_replace(':max_mb', $parameters[0] / 1024, $message);
});
    public function rules()
    {
        return [
            'inputFile' => 'max:1024'
        ];
    }

    public function messages()
    {
        return [
            'inputFile.max' => 'The input file may not be greater than :max_mb megabytes.'
        ];
    }

所感

個人的には方法2が分かりやすかったです。

他にやり方があるようでしたら是非コメントをお願いしますー。

11
6
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
11
6