Validator Rule not applied

I got the following $rules for a certain model:

    public $rules = [
        'name' => 'required',
        'category_id' => 'required_if:published,1',
    ];

The Category is a relation:

    public $belongsTo = [
        'category' => [
            Category::class,
            'order' => 'name'
        ]
    ];

Now, if I save the model within the create/edit view and for example the name is missing or I try to publish if no category is set, everything just works fine: The validation error is thrown and nothing is saved.

Now I added a listswitch to my list (basically a bit more advanced version of the listswitch plugin) which should perform this validation, too:

    private function processInvertField($modelClass, $id, $fieldName, $dateFieldOnTrue)
    {
        if (empty($fieldName) || empty($id) || empty($modelClass)) {
            throw new ApplicationException("Following parameters are required : id, field, model");
        }
        $item = $modelClass::findOrFail($id);
        # If Item is set to true, also set this datefield to the actual date
        if (!empty($dateFieldOnTrue) && !$item->{$fieldName}) {
            $item->{$dateFieldOnTrue} = Carbon::now();
        }
        $item->{$fieldName} = !$item->{$fieldName};

        # Validate
# $item->name = '';
        $validator = Validator::make($item->attributes, (new $modelClass)->rules);
        if ($validator->fails()) {
            throw new ApplicationException($validator->getMessageBag()->first());
        }
        
        $item->save();
    }

I posted the whole method, but just the validation part is relevant. I call the validator and it does not apply for the category_id and I dont know why. If I remove the name with the commented line, the validation message is thrown. Not for the category.

What did I miss?

Thanks for every kind of help :slight_smile:

1 Like

Hi @LordRazen

I would write the rules like this:

public $rules = [
        'name' => 'required',
        'category' => 'required_if:published,1',
    ];
2 Likes

Also, try calling trace_log($item->attributes); before the validation step to see what attributes you are working with in the event log.

1 Like

Thanks you two,

I tested both ideas. Using “category” did not solve the problem, but it still worked if I changed the publish state within the “edit” view…

The trace log showed the following:

Rules:

(
    [name] => required
    [category_id] => required_if:published,1
    [category] => required_if:published,1
)

Item Attributes:

(
    [id] => 1202
    [name] => Some name...
    [category_id] => 

So it looks correct, but it does not work :-/

the field published seems to be absent form your attribute, therefore the required rule for category_id will not be applied

1 Like

Hm, no the published attribute exists, I accidently removed it from the displayed array above cause there’re several other attributes. Sorry for this.

But I found the issue:

While using the code above with the list switch button, the following rule worked:
'category_id' => ' required_if:published,true',

However, when I tried the validation with the regular save button while editing the model, the variant with “true” didnt work while this one did:
'category_id' => ' required_if:published,1',

This feels strange… one time the true works, one time a “1”.

This here is the DB field if needed:
$table->boolean('published')->default(0)

Is this a bug? It feels like one to me…

It could be a bug. What database engine are you using, is it MySQL?

1 Like

I’m using XAMPP 3.3.0 for local development, as far as I can see this has MariaDB.

I can’t seem to reproduce it. Perhaps using the $casts property would help here.

I had another look into this and what should I say: If you go on googling this problem, you find it over and over since Laravel 5. So a fix will most likely not come from OctoberCMS.

I also found an old OctoberCMS thread with the same problem:
https://octobercms.com/forum/post/validation-required-if-with-boolean-not-working


However, I tried to find a solution.

Your suggestion of using the $casts property in the model didnt work out well
protected $casts = ['published' => 'integer'];
Neither boolean nor integer didnt change anything about the problem.

What did help now were a simple build of two rules testing for the integer and the boolean value:
'category_id' => ['required_if:published,1', 'required_if:published,true'],

It’s not pretty and the natively generated validation messages are difference since one ends on “…1”, the other on “…true”, but this can be changed.

That’s at least my solution after all the research…

And now you’ve replicated the accepted rule from Laravels validation library :wink:

General accepted rule

and

required_if_accepted rule

The accepted validation keyword deals exactly with that problem. It checks for values yes , on , 1 , "1" , true , or "true".

'category_id' => ['required_if_accepted:published'],

This also took me far too long to find when I had that problem.

2 Likes

Finally!!!

The solution I hoped for :smiley:

Didnt think of those additional Laravel validations, would be nice if those are linked in the October doku. Not all of us are Laravel experts :smiley:

Thanks to everybody who tried to help here :slight_smile:

Finally solved