Как правильно сделать валидацию по техусловиям в laravel?

Прошу помощи в принятии конструктивного решения. Сам в Лараверл недавно, поэтому прошу не пинать, а направлять.

Введение. Есть проект по порезке деталей с листа (мебельный). Соотв. каждая деталь имеет собств характеристики, которые храняться напрямую в таблице details и связанные характеристики, которые хранятся в другой таблице. Поэтому когда пользователь набирает деталь он пользуется несколькими попап-ами и при закрывании каждого летит запрос на сохранение. Для каждого такого запроса есть свой (отличный от других) массив передаваемых параметров и свой обработчик в контроллере. Далее есть техусловия где указываются ограничения для тех или иных параметров и иногда в зависимости от значений других параметров. Для проверки техусловий было решено использовать методы валидации. Поэтому для каждого обработчика был создан кастомный реквест в котором добавляются и проверяются все переданные атрибуты а также дополнительные (виртуальные). Например пользователь вводит ширину и длину а надо проверить ограничение по площади. Поэтому в кастомном реквесте добавляется новый атрибут "area" и правило проверки для него. И все работает как песня, ПОКА не потребовалось делать проверку по зависимым параметрам(которые находятся в разных попап-ах и соотв. в разных реквестах). В результате я пришел к дублированию кода в своих кастомных реквестах.

Идея: Создать собственные правила проверки, но не для проверки значений (как min,max и т.д.) а для проверки атрибута. В результате у меня будет по каждому кастомному правилу на каждое тех условие

Пример кастомного правила

class CuttingMinDimension implements Rule {

    protected $validator;

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

    public function passes($attribute, $value)
    {
        // из конфига возвращается массив [50,100]
        $l_sizes = config( 'cutting.min_sizes' );
        $min = min( $l_sizes );
        $max = max( $l_sizes );

        // Получается что здесь я полностью игнорирую переданное мне значение $value
        // и использую то которое достаю из переданных в  валидатор

        $data = $this->validator->getData();
        $value = $data['cutting_dimension'];

        return $value['min'] >= $min && $value['max'] >= $max;
    }

    public function message()
    {
        return '';
    }

}

И если будет 100-150 техусловий у меня будет 100-150 классов правил. Для каждого по одному. Соответственно для каждого моего кастомного реквеста я смогу использовать свой уникальный набор правил, подготовив соотв все необходимые виртуальные атрибуты.

Пример кастомного реквеста с виртуальным атрибутом

class UpdateDetailsRequest extends FormRequest {

    /**
     * Добавляем виртуальные параметры запроса в массив параметров валидации.
     * @return array
     */
    public function validationData() {
        return array_merge(
            parent::validationData(),
            $this->paramCuttingDetailDimension(),
        );
    }

    /**
     * Параметр габоритные размеры детали.
     *
     * @return array
     */
    protected function paramCuttingDetailDimension() {
        // Здесь width и length это атрибуты которые задает пользователь

        $min_d = min( $this->width, $this->length );
        $max_d = max( $this->width, $this->length );

        // это и есть наш виртуальныей параметр и его значения.
        return [ 'cutting_dimension' => [ 'min' => $min_d, 'max' => $max_d ] ];
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules() {
        return array_merge(
            [],
            $this->ruleCuttingDimension(),
        );
    }

    /**
     * Проверка на мин габоритные размеры по порезке.
     *
     * @return array
     */
    protected function ruleCuttingDimension() {
        return [
            'cutting_dimension' => [
                'required',
                'cutting_min_dimension', // тут просто указываем наше кастомное правило.
            ],
        ];
    }
}

Подключение правил просходит в app/Providers/AppServiceProvider.php согласно документации

public function boot()
    {
        Validator::extend('cutting_min_dimension', function ($attribute, $value, $parameters, $validator) {
            return (new CuttingMinDimension($validator))->passes($attribute, $value);
        });
    }

Теперь вопрос: Я понимаю что немного нарушаю общую концепцию использования класса Rule уникализируя его для атрибута. Возможно есть какие то подводные ками такого использования Rule, которых я не вижу? Не получится ли что в будущем я могу поплатится за такое решение, например скоростью обработки запросов?

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


Ответы (0 шт):