Функция passes() пользовательского правила проверки игнорируется

#php #laravel #validation #laravel-5.8

#php #laravel #проверка #laravel-5.8

Вопрос:

Я не знаю, является ли это недостатком сна или отсутствием чего-то очевидного, но у меня возникла такая проблема: я создал пользовательское правило проверки, и мне нужно передать значение запроса через конструктор для выполнения проверки.

Это моя настройка:

Пользовательское правило проверки

 /** Rules/RouteValidationRule.php */

namespace AppRules;

use IlluminateContractsValidationRule;

class RouteValidationRule implements Rule {

    private $action;

    public function __construct(string $action)
    {
        $this->action = $action; // doing dd($action) output the correct value.
    }

    // a dd('Hi'); inside here is just ignored:
    public function passes($attribute, $value)
    {
        if ($this->action === 'complete')
            return (isset($value['delivery_route']))
                amp;amp; (count($value['delivery_route']) >= 2);
        else
            return true;
    }

    public function message() { /** */ }
}
  

Запрос формы

 /** UpdateOrderRequest.php */

namespace AppHttpRequests;

use AppRulesOrderStatusesRule;
use AppRulesRouteValidationRule;
use IlluminateFoundationHttpFormRequest;

class UpdateOrderRequest extends FormRequest {

    public function authorize() { /** */ }

    public function rules() 
    {
        return [
            'action' => ['required', new OrderStatusesRule],
            'meta.delivery_route' => [
                'array',
                new RouteValidationRule($this->get('action')), // <---
           ],
        ];
    }
}
  

Но дело в том, что значение достигает конструктора пользовательского правила, но оно не доходит до passes() метода, оно просто игнорирует это и продолжает, как если бы это было нормально.

PD: я проверял каждый шаг dd() .

Заранее спасибо.


Обновить

 /** MyController.php */

    /**
     * @param UpdateOrderRequest $request
     * @return mixed
     */
    public function handle(UpdateOrderRequest $request) // the RequestForm is injected
    {
        dd('I passed');  // <-- is reaching this statement when it shouldn't
    }
  

Комментарии:

1. Можете ли вы также вставить метод обработчика контроллера? Также не может ли быть так, что проверка вашего запроса завершается неудачно на предыдущем шаге, и поэтому оно не достигнет вашего правила проверки из-за стратегии быстрого выхода?

2. @Tacsiazuma В том-то и дело, что он проходит проверку и достигает контроллера. Я добавлю соответствующий код, как было предложено.

3. И если вы проверите запрос в своем контроллере, он содержит указанное поле? Что произойдет, если вы добавите ‘required’ как правило?

4. @Tacsiazuma если я добавляю required как правило в этот атрибут, он завершается ошибкой при отсутствии (как и ожидалось), но затем, когда я добавляю параметр и повторяю запрос, он передает required , но игнорирует passes() пользовательское правило. И да, атрибут достигает контроллера, это действительно странно

Ответ №1:

Причина, по которой ваше правило не будет выполняться, заключается в том, что тестируемый атрибут отсутствует в Request or null . Если вы хотите, чтобы правило выполнялось независимо от того, присутствует оно или нет, пусть ваше правило ImplicitRule не реализует Rule , например:

 class RouteValidationRule implements ImplicitRule {
  

Ответ №2:

Я взломал аналогичное решение и обнаружил, что оно просто игнорирует проверку, если поле, подлежащее проверке, отсутствует (за исключением случаев, когда required также добавляется в качестве правила проверки):

 Route::any('/', function (UpdateOrderRequest $orderRequest) {
    dd($orderRequest);
});
  

Я добавил dd(‘pass’) внутри метода passes:

  public function passes($attribute, $value)
    {
        dd('pass');
        if ($this->action === 'complete')
            return (isset($value['delivery_route']))
                amp;amp; (count($value['delivery_route']) >= 2);
        else
            return true;
    }
  

Затем отправлен запрос с postman:

 POST / HTTP/1.1
Host: localhost:8888
Content-Type: application/json
cache-control: no-cache
Postman-Token: 848f7181-2c28-46a5-b508-4cb35083315e
{
    "action" : "something",
    "meta" : {
        "delivery_route" : "something else"
    }
}------WebKitFormBoundary7MA4YWxkTrZu0gW--
  

Он столкнулся с методом passes и повторил ‘pass’ обратно. Затем я переименовал «delivery_route» выше, и он оказался в контроллере.

Из документов по проверке Laravel:

По умолчанию, когда проверяемый атрибут отсутствует или содержит пустую строку, обычные правила проверки, включая пользовательские расширения, не выполняются.

Комментарии:

1. Я не понимаю этого решения, или это подтверждение, которое не является проблемой с моей стороны? (возможно, возможная ошибка)

2. Я поместил атрибут present со значением, которое должно было прервать проверку, но все равно прошло.

3. Я думаю, потому что имя поля не совпадает. Читайте о неявных расширениях в laravel.com/docs/5.8/validation

4. Я сделал запрос с теми же именами атрибутов, честно говоря, действительно странные вещи.

5. Можете ли вы попробовать это с помощью запроса JSON (если это еще не так) и обновить свой вопрос с помощью тела запроса?