0

I have read a couple of Stack overflow questions about nested array but I want something a step further. Lets say something like the code below:

I have a validator snippet where the request takes an array. Based on what I understood, on xxx.*.yyy, it will find all array of xxx with yyy as key and validate them . However, what if I want to validate the image_id and image_path based on the value of type?

Note: type, title, image_id and image_path are all on the same level.

The array that I want to validate is like this:

[contents] => Array
    (
        [0] => Array
            (
                [type] => not_image
                [title] => title
            )

        [1] => Array
            (
                [type] => image
                [image_id] => 13
                [image_path] => some_image_string
            )
        )
    )

while my validator is this:

$v = Validator::make($request->all(), [
    'contents.*.type' => ['string', 'required', Rule::in(['image', 'not_image']),],
    'contents.*.image_id' => ['required', 'integer'],
    'contents.*.image_path' => ['required', 'string', 'min:2', 'max:500'],
]);

Only validated image_id and image_page if type is image where image_id and image_path would only be validated if type is validated. I know that the code is missing that one ingredient to do what I want. If you have other ideas on how to do this, that would also be great.

1 Answer 1

4

Your last code is not valid, you are saying type => string, required, rule::in, image_id => [rules], that is not valid, that post you are following is just badly indented...

There is a specific section in the documentation that talks and shows about this...

The rule you have to use is exclude_if, the documentation states:

You may occasionally wish to not validate a given field if another field has a given value. You may accomplish this using the exclude_if validation rule. In this example, the appointment_date and doctor_name fields will not be validated if the has_appointment field has a value of false

And the example they give is:

use Illuminate\Support\Facades\Validator;
 
$validator = Validator::make($data, [
    'has_appointment' => 'required|boolean',
    'appointment_date' => 'exclude_if:has_appointment,false|required|date',
    'doctor_name' => 'exclude_if:has_appointment,false|required|string',
]);

As you can see, if the has_appointment is false (exclude_if:has_appointment,false), then appointment_date and doctor_name will not be validated.

In your case, it should be like:

Validator::make(
    $request->all(),
    [
        'contents.*.type' => ['string', 'required', Rule::in(['image', 'not_image'])],
        'contents.*.image_id' => ['exclude_unless:contents.*.type,image', 'required', 'integer'],
        'contents.*.image_path' => ['exclude_unless:contents.*.type,image', 'required', 'string', 'min:2', 'max:500'],
        'contents.*.title' => ['exclude_unless:contents.*.type,not_image', 'required', 'string'],
    ]
);

What that validator is going to do is:

  • Only when contents.*.type = image, then image_id, and image_path are going to be validated
  • Only when contents.*.type = non_image, then title is going to be validated

See that I have used the opposite of exclude_if, that is exclude_unless. So we are saying exclude_unless:contents.*.type,image => If contents.*.type IS image, then use whatever rules I have after this, else completely ignore this field.


You can write it using exclude_if and it would be like this:

Validator::make(
    $request->all(),
    [
        'contents.*.type' => ['string', 'required', Rule::in(['image', 'not_image'])],
        'contents.*.image_id' => ['exclude_if:contents.*.type,non_image', 'required', 'integer'],
        'contents.*.image_path' => ['exclude_if:contents.*.type,non_image', 'required', 'string', 'min:2', 'max:500'],
        'contents.*.title' => ['exclude_if:contents.*.type,image', 'required', 'string'],
    ]
);

The difference (appart from exclude_if instead of exclude_unless) is that now you are ONLY excluding if image or non_image, but using exclude_unless is saying: Only validate if image (or non_image), so if you have 3 types instead of 2 (image and non_image), exclude_if will not work, because you can't specify more than 1 value.


Another quick tip is: just use $request->validate() instead of Validator::make:

$request->validate([
    'contents.*.type' => ['string', 'required', Rule::in(['image', 'not_image'])],
    'contents.*.image_id' => ['exclude_unless:contents.*.type,image', 'required', 'integer'],
    'contents.*.image_path' => ['exclude_unless:contents.*.type,image', 'required', 'string', 'min:2', 'max:500'],
    'contents.*.title' => ['exclude_unless:contents.*.type,not_image', 'required', 'string'],
]);
Sign up to request clarification or add additional context in comments.

4 Comments

Wow. thank you for giving me insights. Will try to implement this as soon as I can. Will let you know. Thank you again. As per you comment the code is not properly indented, thank you for correcting me.
I read it as adding the image id and path inside the type.
deleted that snippet.
This is great. yeah it works. I can also do an AND condition on this. I think we can do an OR on the exclude but I dont need it for now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.