Нужно проверить 2 кейса:
1. Что блюдо принадлежит тому меню, которое принадлежит текущему проекту
2. Сумма всех блюд должна находиться в диапазоне 1-150000.
Кажется, что что-то я делаю не так.
1. $fail не работает внутри коллекции, я мог бы это исправить переведя на обычный foreach или установить флаг на уровне ф-ции __invoke и менять его, в случае ошибки и проверять уже за пределами коллекции (но кажется, что что-то не то).
2. Стоит ли мешать 2 подобные проверки в одном месте?
<?php
namespace App\Rules;
use App\Models\Dishe;
use App\Models\Order;
use App\Models\Project;
use Illuminate\Contracts\Validation\InvokableRule;
use Illuminate\Support\Arr;
class DishesRule implements InvokableRule
{
private Project $project;
private ?Order $order;
public function __construct (Project $project, Order $order = null) {
$this->project = $project;
$this->order = $order;
}
public function __invoke($attribute, $value, $fail)
{
$dishesRequest = collect($value);
$dishesRequest->each(function($dishe) use($fail) {
$disheId = Arr::get($dishe, 'id');
# проверяем принадлежность блюда и меню к одному проекту
$exists = $disheId && Dishe::where('id', $disheId)->Active()->whereHas('menu', function ($query) {
return $query->where('project_id', $this->project->id)->Active();
})->exists();
if (!$exists) {
return $fail(__('validation.exists'));
}
});
# Получаем список блюд по массиву идентификаторов
$dishes = Dishe::whereIn('id', $dishesRequest->pluck('id'))->get();
$totalDishes = $dishes->sum('price');
$total = $this->order ? $totalDishes + $this->order->totalPrice : $totalDishes;
if ($total < 1 || $total > 150000) {
return $fail('Сумма заказа должна быть от 1 ₽ до 150 000 ₽');
}
}
}
# rules
public function rules()
{
return [
'table_id' => [
'required',
'numeric',
Rule::unique('orders')->where(function ($query) {
# проверка доступности стола (нет ли на нем заказов в указанных статусах)
return $query->where('table_id', $this->table_id)->whereIn('status', [Order::NEW, Order::WORK]);
}),
],
'dishes' => ['required', 'array', 'min:1', new DishesRule($this->table->project)],
'dishes.*.id' => ['required', 'numeric'],
'dishes.*.quantity' => ['required', 'numeric', 'digits_between:1,99'],
'dishes.*.comment' => ['nullable', 'string', 'min:1', 'max:255'],
];
}