web-dev-qa-db-ja.com

Laravel 5でフォームリクエスト検証を使用するときにカスタム検証ルールを追加する方法

laravel 5.フォームリクエスト検証メソッドを使用して独自の検証ルールを追加したい。フィールド項目を含む検証numeric_array。

  protected $rules = [
      'shipping_country' => ['max:60'],
      'items' => ['array|numericarray']
];

私のカスタム関数は以下のとおりです

 Validator::extend('numericarray', function($attribute, $value, $parameters) {
            foreach ($value as $v) {
                if (!is_int($v)) {
                    return false;
                }
            }
            return true;
        });

この検証方法をlaravel5のフォームリクエスト検証について使用するにはどうすればよいですか?

37
gsk

Validator::extend()を使用するのと同じように、実際には完全に問題ありません。次のように Service Provider に入れるだけです。

<?php namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class ValidatorServiceProvider extends ServiceProvider {

    public function boot()
    {
        $this->app['validator']->extend('numericarray', function ($attribute, $value, $parameters)
        {
            foreach ($value as $v) {
                if (!is_int($v)) {
                    return false;
                }
            }
            return true;
        });
    }

    public function register()
    {
        //
    }
}

次に、config/app.phpのリストに追加してプロバイダーを登録します。

'providers' => [
    // Other Service Providers

    'App\Providers\ValidatorServiceProvider',
],

numericarray検証ルールをどこでも使用できるようになりました

41
lukasgeiter

上記の答えは正しいですが、多くの場合、特定のフォームリクエストに対してのみカスタム検証を作成したい場合があります。 laravel FormRequestを活用し、依存性注入を使用して検証ファクトリを拡張できます。このソリューションは、サービスプロバイダーを作成するよりもはるかに簡単だと思います。

方法は次のとおりです。

use Illuminate\Validation\Factory as ValidationFactory;

class UpdateMyUserRequest extends FormRequest {

    public function __construct(ValidationFactory $validationFactory)
    {

        $validationFactory->extend(
            'foo',
            function ($attribute, $value, $parameters) {
                return 'foo' === $value;
            },
            'Sorry, it failed foo validation!'
        );

    }

    public function rules()
    {
        return [
            'username' => 'foo',
        ];
    }
}
39
Adrian Gunawan

受け入れられた答えは、グローバル検証ルールに対して機能しますが、多くの場合、フォームに非常に固有の特定の条件を検証します。そのような状況で私が推奨するものは次のとおりです(Laravelソースコード FormRequest.phpの75行目 )。

バリデーターメソッドを親に追加リクエストが拡張するリクエスト:

<?php namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Validator;

abstract class Request extends FormRequest {

    public function validator(){

        $v = Validator::make($this->input(), $this->rules(), $this->messages(), $this->attributes());

        if(method_exists($this, 'moreValidation')){
            $this->moreValidation($v);
        }

        return $v;
    }
}

特定のリクエストはすべて次のようになります:

<?php namespace App\Http\Requests;

use App\Http\Requests\Request;

class ShipRequest extends Request {

    public function rules()
    {
        return [
            'shipping_country' => 'max:60',
            'items' => 'array'
        ];
    }

    // Here we can do more with the validation instance...
    public function moreValidation($validator){

        // Use an "after validation hook" (see laravel docs)
        $validator->after(function($validator)
        {
            // Check to see if valid numeric array
            foreach ($this->input('items') as $item) {
                if (!is_int($item)) {
                    $validator->errors()->add('items', 'Items should all be numeric');
                    break;
                }
            }
        });
    }

    // Bonus: I also like to take care of any custom messages here
    public function messages(){
        return [
            'shipping_country.max' => 'Whoa! Easy there on shipping char. count!'
        ];
    }
}
19
prograhammer

getValidatorInstanceクラスのRequestメソッドをオーバーライドする必要があります。たとえば、次のようにします。

protected function getValidatorInstance()
{
    $validator = parent::getValidatorInstance();
    $validator->addImplicitExtension('numericarray', function($attribute, $value, $parameters) {
        foreach ($value as $v) {
            if (!is_int($v)) {
                return false;
            }
        }
        return true;
    });

    return $validator;
}
5

カスタムルールオブジェクト

カスタムルールオブジェクト を使用すると、新しいルールを設定するためにプロバイダーやコントローラー/サービスを変更する必要なく、必要な数のルールを定義できます。

php artisan make:rule NumericArray

NumericArray.phpで

namespace App\Rules;
class NumericArray implements Rule
{
   public function passes($attribute, $value)
   {
     foreach ($value as $v) {
       if (!is_int($v)) {
         return false;
       }
     }
     return true;
   }


  public function message()
  {
     return 'error message...';
  }
}

その後、フォームリクエストで持っている

use App\Rules\NumericArray;
.
.
protected $rules = [
      'shipping_country' => ['max:60'],
      'items' => ['array', new NumericArray]
];
4
gk.

配列項目を検証するためにバリデーターを拡張する必要はありません。 Array Validation でわかるように、配列の各項目を「*」で検証できます。

protected $rules = [
      'shipping_country' => ['max:60'],
      'items' => ['array'],
      'items.*' => 'integer'
];
3
Félix Díaz

私にとっては、lukasgeiterを提供するソリューションが動作しますが、laravel 5.2。*の場合、次の例のように、カスタム検証でクラスを作成するという違いがあります2番目の日付が最初の日付と同じかそれより大きくなければならない日付の範囲

App/ProvidersでValidatorExtended.phpを作成します

<?php
namespace App\Providers;
use Illuminate\Validation\Validator as IlluminateValidator;

class ValidatorExtended extends IlluminateValidator {

private $_custom_messages = array(
 "after_or_equal" => ":attribute debe ser una fecha posterior o igual a 
 :date.",
);

public function __construct( $translator, $data, $rules, $messages = array(),      
$customAttributes = array() ) {
  parent::__construct( $translator, $data, $rules, $messages, 
  $customAttributes );
  $this->_set_custom_stuff();
}

protected function _set_custom_stuff() {
   //setup our custom error messages
  $this->setCustomMessages( $this->_custom_messages );
}

/**
 * La fecha final debe ser mayor o igual a la fecha inicial
 *
 * after_or_equal
 */
protected function validateAfterOrEqual( $attribute, $value, $parameters, 
$validator) {
   return strtotime($validator->getData()[$parameters[0]]) <= 
  strtotime($value);
}

}   //end of class

OK。次に、サービスプロバイダーを作成します。 app/Providers内にValidationExtensionServiceProvider.phpを作成し、コーディングします

<?php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Validator;

class ValidationExtensionServiceProvider extends ServiceProvider {

public function register() {}

public function boot() {
  $this->app->validator->resolver( function( $translator, $data, $rules, 
  $messages = array(), $customAttributes = array() ) {
    return new ValidatorExtended( $translator, $data, $rules, $messages, 
    $customAttributes );
} );
}

}   //end of class

ここでLaravelにこのサービスプロバイダーをロードし、config/app.phpの最後にプロバイダー配列に追加して、

//Servicio para extender validaciones
App\Providers\ValidationExtensionServiceProvider::class,

関数ルールのリクエストでこの検証を使用できるようになりました

public function rules()
{
  return [
    'fDesde'     => 'date',
    'fHasta'     => 'date|after_or_equal:fDesde'
 ];
}

またはValidator:makeで

$validator = Validator::make($request->all(), [
    'fDesde'     => 'date',
    'fHasta'     => 'date|after_or_equal:fDesde'
], $messages);

検証を行うメソッドの名前には接頭辞validateがあり、キャメルケーススタイルのvalidateAfterOrEqualであることに注意する必要がありますが、検証のルールを使用すると、すべての大文字がアンダースコアと小文字の文字に置き換えられます。

このすべてを https://www.sitepoint.com/data-validation-laravel-right-way-custom-validators// からここで詳しく説明します。彼らに感謝します。

0
Carolina