0

I have following segment of the validation:

'places' => [
    new CompanyHasPlacesRule,
],

and the validation class:

public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        $company = DB::table('companies')
            ->select('companies.id', DB::raw('GROUP_CONCAT(places.id) as placeIDs'))
            ->join('places', 'companies.id', '=', 'places.company_id')
            ->where('companies.id', $this->data['company_id'])
            ->groupBy('companies.id')
            ->first();
        
        if (! $company?->placeIDs && $value === null) {
            return;
        }

        if ($company?->placeIDs && $value === null) {
            $fail('Please select place associated with the company.');
        }

        if ($value && $company->placeIDs) {

            $difference = array_diff($value, explode(',', $company->placeIDs));

            if (! empty($difference)) {
                $fail('Selected company does not have this place assigned.');
            }

            return;
        }

        $fail('Selected company does not have this place assigned.');

    }

The problem: company doesn't always have a place, but if the company have a place, one or more places needs to be selected - places needs to be validated only if the company have places, and the only way to find out if the company has places is in validation. Is there a way to always validated places even if the places field is not in the request?

1
  • 1
    In your form request class use the required if rule: 'places' => [Required::if(Company::find($this->company_id)->places()->count())] Commented Mar 12, 2024 at 16:33

1 Answer 1

0

Just for simplicity, I'm going to use eloquent's relationships

class Company extends Model
{
    public function places()
    {
        return $this->hasMany(Place::class);
    }
}

In the validation class

public function validate(string $attribute, mixed $values, Closure $fail): void
{
    // Retrieve the company with its associated places
    $company = Company::with(['places:id,company_id'])
        ->firstWhere('id', $this->data['company_id']);

    // If the company doesn't have places, the validation will pass
    if ($company->places->count() === 0) {
        return;
    }

    if (empty($values)) {
        $fail('Please select a place associated with the company.');
    }

    $placesIds = $company->places->pluck('id')->toArray();
    $difference = array_diff($values, $placesIds);

    // If one or more selected places are not associated with the company,
    // the validation will fail
    if (! empty($difference)) {
        $fail('One or more selected places are not associated with the company.');
    }

    // If the company has places and the selected places are associated with the company,
    // the validation will pass

}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.