Как добавить пользовательские правила проверки при использовании проверки запроса формы в Laravel 5

Я использую метод проверки запроса формы для проверки запроса в laravel 5.Я хотел бы добавить свое собственное правило проверки с помощью метода проверки запроса формы.Мой класс запроса приведен ниже.Я хочу добавить пользовательскую проверку numeric_array с элементами поля.

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

моя функция cusotom приведена ниже

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

Как можно использовать этот метод проверки с проверкой запроса формы в laravel5?

7 ответов


используя Validator::extend() Как вы на самом деле прекрасно, вам просто нужно поместить это в Провайдер такой:

<?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 правила проверки везде, где вы хотите


хотя приведенный выше ответ верен, во многих случаях вы можете создать пользовательскую проверку только для определенного запроса формы. Вы можете использовать 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',
        ];
    }
}

принятый ответ работает для глобальных правил проверки, но много раз вы будете проверять определенные условия, которые очень специфичны для формы. Вот что я рекомендую в этих обстоятельствах (это, кажется, несколько предназначено из исходного кода Laravel в строка 75 FormRequest.в PHP):

добавить метод валидатора к родительскому запросу ваши запросы будут расширяться:

<?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!'
        ];
    }
}

вам нужно переопределить 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;
}

вам не нужно расширять валидатор для проверки элементов массива, вы можете проверить каждый элемент массива с помощью"*", как вы можете видеть в Проверка Массива

protected $rules = [
      'shipping_country' => ['max:60'],
      'items' => ['array'],
      'items.*' => 'integer'
];

для меня работает решение, которое дает нам lukasgeiter, но с той разницей ,что мы создаем класс с нашими пользовательскими проверками, например, для laravel 5.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. теперь давайте создадим поставщика услуг. Создайте 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'
 ];
}

или в валидаторе: 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// здесь объясните подробно. благодаря им.


Пользовательский Объект Правила

один из способов сделать это с помощью Пользовательский Объект Правила, таким образом, вы можете определить столько правил, сколько хотите, без необходимости вносить изменения в поставщиков и в контроллер/сервис для установки новых правил.

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]
];