概要
タイトル通りです。
max file sizeのValidationはデフォルトでKB表示になっているので、それをMBやGBに変更する方法を調べたので備忘録です。
環境
PHP: 7.2.22
Laravel: 6.18.3
事前準備
以下のようにRequestオブジェクトにvalidationのルールを記述すると「inputFile」フォームからアップロードするファイルの上限を1MBに設定します。
public function rules()
{
return [
'inputFile' => 'max:1024'
];
}
1MB以上のファイルをアップロードした場合は以下のように「The input file may not be greater than 1024 kilobytes.」と表示されるので、これをメガバイト表示に修正していきます。
設定変更
方法1: メッセージを固定する
一番手軽に解決できます。
該当のフォームがvalidationに引っかかった場合に表示するメッセージを〜megabytesで固定します。
public function rules()
{
return [
'inputFile' => 'max:1024'
];
}
public function messages()
{
return [
'inputFile.max' => 'The input file may not be greater than 1 megabytes.'
];
}
方法2: カスタムValiationルールを作成する
方法1のやり方だと上限の1MBが2MB等に変更になったときにメッセージも都度修正しないといけないので面倒です。
なので、KBではなくMB表示できるような新しいvalidationのルールを作成します。
参考1(公式ドキュメント)
参考2(stack overflow)
<?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.");
}
}
}
'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
が作成されたので以下のように編集します。
<?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が分かりやすかったです。
他にやり方があるようでしたら是非コメントをお願いしますー。