@lexstile

Как корректно соcтавить правило валидации на laravel 9?

нужно корректно провалидировать поле user_id.
OrderUpdateRequest
public function rules()
    {
        return [
            'table_id' => [
                'numeric',
                Rule::exists('tables', 'id')->where(function ($query) {
                    # проверка принадлежности стола и заказа к одному проекту
                    return $query->where('project_id', $this->project->id);
                }),
                Rule::unique('orders')->where(function ($query) {
                    # проверка доступности стола (нет ли на нем заказов в указанных статусах)
                    return $query->where('table_id', $this->table_id)->whereIn('status', [Order::NEW, Order::WORK, Order::PAID]);
                }),
            ],
            'user_id' => [
                'nullable',
                'numeric',
                'exists:users,id',
                new UserAssigneeToOrderRule($this->project),
            ],
            'status' => ['string', new OrderStatusRule($this->order)],
        ];
    }

Пока остановился на версии 2, но все равно кажется, что можно как-то это проще сделать.
Если есть идеи, буду очень признателен.
Версия 1:

class UserAssigneeToOrderRule implements InvokableRule
{
    private Project $project;

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

    /**
     * Run the validation rule.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @param  \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString  $fail
     * @return void
     */
    public function __invoke($attribute, $value, $fail)
    {
        # @owner - может назначать на всех и на себя
        # @admin - может назначать на employee и на себя
        # @employee - может назначать на себя

        $user = $this->project->users()->firstWhere('users.id', $value);

        if (auth()->user()->isOwner() && !$user && auth()->id() != $value) {
            $fail('Пользователь не принадлежит проекту');
        }

        if (!auth()->user()->isOwner() && !$user) {
            $fail('Пользователь не принадлежит проекту');
        }

        if (auth()->user()->isAdmin() && (auth()->id() !== $user?->id || !$user->isEmployee())) {
            $fail('Можно назначать на себя, либо на сотрудника');
        }

        if (auth()->user()->isEmployee() && auth()->id() !== $user?->id) {
            $fail('Можно назначать только на себя');
        }
    }
}

Версия 2:

class UserAssigneeToOrderRule implements InvokableRule
{
    private Project $project;

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

    public function __invoke($attribute, $value, $fail)
    {
        # @owner - может назначать заказ на всех сотрудников и на себя
        # @admin - может назначать на @employee и на себя
        # @employee - может назначать на себя

        # привязан ли назначаемый сотрудник к проекту (есть связь в таблице project_user)
        $user = $this->project->users()->firstWhere('users.id', $value);

        if (auth()->user()->isOwner()) {
            # если не на себя или нет связанных пользователей (@admin или @employee)
            if (!(auth()->id() == $value || $user)) {
                $fail('Пользователь не принадлежит проекту');
            }
        } else if (auth()->user()->isAdmin()) {
            # если не на себя или не на сотрудника в роли пользователя от @employee
            if (!(auth()->id() === $user?->id || $user?->isEmployee())) {
                $fail('Можно назначать на себя, либо на сотрудника');
            }
        } else if (auth()->user()->isEmployee()) {
            # если не на себя
            if (!(auth()->id() === $user?->id)) {
                $fail('Можно назначать только на себя');
            }
        }
    }
}

Таблицы:
projects
637f98f25ae01550793761.png

orders
637f99062adbf189820913.png

project_user
637f993102d0e155820638.png
  • Вопрос задан
  • 114 просмотров
Пригласить эксперта
Ваш ответ на вопрос

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

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