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

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

Введение.
Есть проект по порезке деталей с листа (мебельный).
Соотв. каждая деталь имеет собств характеристики, которые храняться напрямую в таблице 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, которых я не вижу?
Не получится ли что в будущем я могу поплатится за такое решение, например скоростью обработки запросов?

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

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы