Bonjour,

Je travaille actuellement sur un CRUD laravel d'une table pivot et passe par un FormRequest pour valider mes requêtes.

J'aimerais m'assurer que la combinaison de deux champs (operation_id et doctor_id) n'existent pas dans ma db, sauf s'il s'agit de mon model actuel.

/**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'operation_id' => 'required|exists:operations,id',
            'doctor_id' => 'required|exists:doctors,id',
            'value' => 'nullable|string',
        ];
    }

    /**
     * Configure the validator instance.
     *
     * @param  \Illuminate\Validation\Validator  $validator
     * @return void
     */
    public function withValidator($validator)
    {
        $validator->after(function ($validator) {
            if ($this->comboExistInDb()) {
                $validator->errors()->add('operation_id', 'La combinaison des deux champs existent déjà');
                $validator->errors()->add('doctor_id', 'La combinaison des deux champs existent déjà');
            }
        });
    }

    private function comboExistInDb()
    {
        return DoctorOperation::where('doctor_id', $this->doctor_id)
            ->where('operation_id', $this->operation_id)
            ->where('id', '!=', $this->route('doctor-operation')) // Supposedly get the route parameter
            ->exists();
    }

Ce que je veux

J'aimerais que la combinaison de mes deux champs soient uniques sauf s'il s'agit de mon model actuel.

Ce que j'obtiens

Après validation, je suis directement redirigé vers mon formulaire avec le message
"La combinaison des deux champs existent déjà".

PS: J'ai déjà essayé avec Rule::unique && en inline 'unique'.

3 réponses


popotte
Réponse acceptée

Alors il te faut bien la règle unique
Ensuite il te faut un ignore pour exclure ton model actuel:

Rule::unique('doctor_operations', 'doctor_id', 'operation_id')->ignore($doctorOperation) // Soit ca
Rule::unique('doctor_operations', ['doctor_id', 'operation_id'])->ignore($doctorOperation) // Soit ca

Rule::unique('doctor_operations', 'doctor_id')->where(function ($query) { // Si tu passes operation_id dans ta request ou les 2
        return $query->where('operation_id', $this->operation_id); 
    })
Rule::unique('doctor_operations', 'operation_id')->where(function ($query) { // Si tu passes doctor_id dans ta request ou les 2
        return $query->where('doctor_id', $this->doctor_id); 
    })

C'est une de ces rules ^^'

Dans cette Rule, la validation va vérifier si il y'a un doc id ET une opération id qui existent déjà, mais la validation va laisser passer ton $model ($model est a remplacer par le nom de ton modèle ($doctorOperation?))
Et normalement tu pourras virer ton comboExistInDb, c'est la validation qui s'occupera de vérifier et de te donner un message d'erreur :)

Adraknar
Auteur
Réponse acceptée

Hey, merci de ta réponse ça m'a beaucoup aidé !

Pour ceux que ça intéresse, j'ai finalement réécrit ma règle de cette façon :

public function rules()
    {
        return [
            'operation_id' => [
                'required',
                'exists:operations,id',
                Rule::unique('doctor_operation',  'operation_id')->where(function ($query) {
                    return $query->where('doctor_id', $this->doctor_id);
                })->ignore($this->route('doctor_operation'))
            ],
            'doctor_id' => [
                'required',
                'exists:doctors,id',
                Rule::unique('doctor_operation',  'doctor_id')->where(function ($query) {
                    return $query->where('operation_id', $this->operation_id);
                })->ignore($this->route('doctor_operation'))
            ],
        ];
    }

A bientôt sur Grafikart,
Adrak'

De rien ;)
Ah oui comme ca ca a l'air mieux :p