Margus Pala
Margus Pala

Reputation: 8663

Laravel validation required|exists with exception of 0

HTML form has select dropdown with list of existing categories and no category with id=0. CategoryStoreRequest must check if the category_id from the form belongs to existing category or is 0

Something like that

public function rules() {
    return [
        "name" => "required|min:3",
        "category_id" => "required|exists:categories,id,except_if_value_is_0"
    ];
}

What is the most elegant way to achieve it?

Upvotes: 7

Views: 13359

Answers (5)

Misha Voloshchuk
Misha Voloshchuk

Reputation: 11

The nullable rule is an excellent way to handle this scenario. However, I faced a similar issue where I needed to update multiple database entries at once, so I needed more powerful solution with the following requirements:

  1. Ignore the field value if it's null, so it remains unchanged for all entries.
  2. Remove values from all entries if the value is '0', so the '0' should also be valid.
  3. Set the value only if it exists in the entries database table.

Here’s how I resolved it (I used Laravel 11.33.2):

[
    'entry_id' => [
        'nullable', 
        Rule::in(['0', ...EntryModel::select('id')->get()->pluck('id')])
    ]
]

For more details, see the Laravel Validation Documentation.

Upvotes: 0

Omar Farag
Omar Farag

Reputation: 41

you can create new validation to handle see this example: in your_project_name/app/providers/AppServicesProviders.php

Validator::extend(
        'exists_or_null',
        function ($attribute, $value, $parameters)
        {
            if($value == 0 || is_null($value)) {
                return true;
            } else {
                $validator = Validator::make([$attribute => $value], [
                    $attribute => 'exists:' . implode(",", $parameters)
                ]);
                return !$validator->fails();
            }
        }
    );

in your example do that

public function rules() {
return [
    "name" => "required|min:3",
    "category_id" => "required|exists_or_null:categories,id"
];

}

Upvotes: 4

TheAlexLichter
TheAlexLichter

Reputation: 7289

Instead of checking for exists or 0, you could set your custom zero value to NULL or an empty string.

You need to change a little bit of your logic, but then you can validate it correctly by using the sometimes rule:

public function rules() {
    return [
        "name" => "required|min:3",
        "category_id" => "sometimes|exists:categories,id"
    ];
}

Upvotes: 2

Margus Pala
Margus Pala

Reputation: 8663

It turns out that nullable is one quite elegant way to do it. When submitting the form then category_id array key is still present but its value is null. nullable allows the key to be null also.

public function rules() {
    return [
        "name" => "required|min:3",
        "category_id" => "nullable|exists:categories,id"
    ];
}

In addition the select value must be ""

<select name="category_id">
    <option value="">No category selection</option>
    <option value="1">Cat 1</option>
</select>

Upvotes: 14

schellingerht
schellingerht

Reputation: 5796

You can use sometimes. In this case, the rule will only be applied if a filled category_id is submitted.

public function rules() {
    return [
        "name" => "required|min:3",
        "category_id" => "sometimes|exists:categories,id"
    ];
}

Change your html, so that there's no value set:

<select name="category_id">
    <option value="">No category selection</option>
    <option value="1">Cat 1</option>
</select>

Upvotes: 3

Related Questions