Laravel, как при определённом условии добавить ошибку в валидатор в событии модели?

Рейтинг: 0Ответов: 1Опубликовано: 17.06.2023

Допустим есть ресурсный контроллер, который создаётся с флагом make:controller --resource.

...
public function store(ProductRequest $request)
{
    $brand = Brand::where('id', $request->input('brand_id')->first();
    if ($brand->categories->contains($request->input('category_id'))) {...} //повторяющаяся проверка
    $product = Product::create($request->all());


    return redirect()->...
}

public function update(ProductRequest $request, string $id)
{
    $product = Product::findOrFail($id);
    $brand = Brand::where('id', $request->input('brand_id')->first();
    if ($brand->categories->contains($request->input('category_id'))) {...} //повторяющаяся проверка
    $product->update($request->all());

    return back();
}

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

protected static function boot()
{
    parent::boot();

    static::saving(function(Model $car) {

        if (!someerror) {
            //validator->errors()->add
            return false;
        }

    });
}

т.е. ошибки, которые потом выводятся примерно так:

<ul>
    @foreach ($errors->all() as $error)
    <li>{{ $error }}</li>
    @endforeach
</ul>

Подскажите, как это правильно сделать?

p.s.
App\Models\Brand

public function categories(): BelongsToMany
{
    return $this->belongsToMany(Category::class);
}

Также пытался добавить в FormRequest правило примерно так

'title' => [
        'required',
        'max:255',
        function (string $attribute, mixed $value, Closure $fail) {
            
            if ($value === 'foo') {
                $fail("The {$attribute} is invalid.");
            }
        },
    ],

но тут как я понимаю доступ только к одному атрибуту, а нужно при проверке одного атрибута иметь доступ сразу ко всем атрибутам модели при проверке.
Или чтобы в FormRequest получить доступ ко всем атрибутам модели нужно воспользоваться request()->all()? Но они ведь ещё не проверены будут в FormRequest?

Ответы

▲ -2

Для валидации и доставки данных в контроллер используем кастом Request, где прописываем правли валидации, инкапсулируем все входные параметры, по возможности собираем внутри Request DTO - это даст нам 100% гарантию валидности данных входящих в контроллер. Это первый момент. Далее... Никогда, запомните, никогда не берите данные напрямую из $request, всегда обращайтесь только к методам, например $request->getCategoryId(); или (в идеале) $request->getCategoryDTO(); который вернет вам объект с данными. Третье - не используйте модели напрямую в контроллере. Если логика простая (сохранить\обновить) выносите такие вещи в репозитории, к примеру ProductRepository $pr->update($request->getProductDTO()); Если же логики много - реализуйте её в сервисе \ операции и там делайте свою магию. P.S. На один метод контроллера - уникальный Request. Не переиспользуйте один и тот же. Всегда используйте типизацию методов\свойств - будет счастье.