How can I use whereHas() method in Rule::unique() for Multi Column Unique Validation

108 Views Asked by At

Can I use whereHas method in Rule::unique() ? There are no column here for cows, the data of cows are comming from pivot table by ManyToMany relationship. Please help me.

I want something like that:

public function rules(): array
    {
        return [
            'vaccination_date' => [
                'required', 'date', 'before:tomorrow',
                Rule::unique('vaccines', 'vaccination_date')
                ->where(function ($query) {
                    $query->where('vaccination_date', $this->input('vaccination_date'))
                    ->where('next_vaccination_date', $this->input('next_vaccination_date'))
                    ->where('vaccine_type', $this->input('vaccine_type'))
                    ->where('dose', $this->input('dose'))
                    ->whereHas('cows', function($query)  {
                        $query->whereIn('id', [1,2]);
                    })->get();
                }),],

            'next_vaccination_date' => ['required', 'date', 'after:vaccination_date'],

            'vaccine_type' => [
                'required',
                'string',
                new Enum(VaccineTypeEnum::class)
            ],
            'dose' => [
                'required',
                'string',
                new Enum(VaccineDoseEnum::class)
            ],
            'cows' => ['required', 'array', 'min:1', Rule::exists('cows', 'id')],

        ];
    }
1

There are 1 best solutions below

1
Shahadat Shuvo On

Solved with custom rules. Here is the code of the custom Rule class:

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;
use App\Models\Vaccine;

class UniqueVaccine implements Rule
{
    protected $request;

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

    public function passes($attribute, $value)
    {
        $vaccination_date = $this->request['vaccination_date'];
        $next_vaccination_date = $this->request['next_vaccination_date'];
        $vaccine_type = $this->request['vaccine_type'];
        $dose = $this->request['dose'];
        $cows = $this->request['cows'];
        $exists =
        Vaccine::where('vaccination_date', $vaccination_date)
            ->where('next_vaccination_date', $next_vaccination_date)
            ->where('vaccine_type', $vaccine_type)
            ->where('dose', $dose)
            ->where(function ($query) use ($cows) {
                $query->WhereHas('cows', function ($subquery) use ($cows) {
                    $subquery->whereIn('id', $cows);
                });
            })->exists();


        // Return true if the combination is unique, false otherwise
        return !$exists;
    }

    public function message()
    {
        return 'A vaccine with the same combination of information already exists.';
    }
}

Here is the code of rules() method of the FormRequest class:

public function rules(): array
    {
        return [
            'vaccination_date' => [
                'required', 'date', 'before:tomorrow', new UniqueVaccine($this->all())
            ],

            'next_vaccination_date' => ['required', 'date', 'after:vaccination_date'],

            'vaccine_type' => [
                'required',
                'string',
                new Enum(VaccineTypeEnum::class)
            ],
            'dose' => [
                'required',
                'string',
                new Enum(VaccineDoseEnum::class)
            ],

            'cows' => ['required', 'array', 'min:1', Rule::exists('cows', 'id')],
        ];
    }

Let me know if you have any suggestions about my code.