Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mrockett's avatar

Conditional array validation in Laravel 5.4

I'm writing a small app that submits booking requests for a fundraising event. The form submits an array of players, which is then validated. Each player may or may not have an email address. There is an option for each of the players to be subscribed to the organisation's mailing list.

How do I go about validating the mailing-list selection (select box values: Yes, No) so that it may only be Yes if the email address for that player is provided, using * notation?

I have thought about using sometimes, but I don't know how to target a specific player in the array.

These are the rules for the players:

'Player.*.FirstName' => 'required|between:2,30',
'Player.*.LastName' => 'required|between:2,30',
'Player.*.ContactNumber' => 'nullable|regex:/0\d{2}\s\d{3}\s\d{4}(?:\sext\.\s\d{1,5})?/',
'Player.*.EmailAddress' => 'nullable|email',
'Player.*.MailingList' => 'required|in:Yes,No', // This should only be Yes if the player's email is present

Many thanks!

0 likes
8 replies
deGecko's avatar

Have you tried something like this?

'Player.*.MailingList' => 'required_if:Player.*.EmailAddress|in:Yes,No',

I imagine Laravel would substitute the * in all the validation components with the current index, not only the keys.

mrockett's avatar

@Gck -- Thanks, but surely required_if will not help me as I'm looking to validate the actual value, and not whether or not it's null or empty? I could revert to a checkbox, but would prefer to use the selectbox.

deGecko's avatar

So if I understand correctly, you want the value of Player.*.MaiLingList to be either Yes or No if the email is available and only allow the No option if the email is unavailable.

I'd suggest to investigate the Illuminate\Validation\Rule class and see if you can access the current element of the array, so you can do something like this:

'Player.*.MailingList' => 'required|in:' . Rule::item()->EmailAddress ? 'Yes,No' : 'No',

Otherwise, you can accomplish the same thing like this:

'Player.*.MailingList' => 'required_if:Player.*.EmailAddress|in:Yes,No',
'Player.*.MailingList' => 'required_unless:Player.*.EmailAddress|in:No',
mrockett's avatar

That looks interesting, thanks @Gck. I didn't know you could separate it like that in the second example... For brevity, I'm more inclined to the Rule example.

Or, as an alternative, should I simply make the email required if MailingList is Yes?

deGecko's avatar

Or, as an alternative, should I simply make the email required if MailingList is Yes?

That sounds like a better way to approach this problem which will also give the user better explanations on what they did wrong.

The complete solution would look like this:

'Player.*.FirstName' => 'required|between:2,30',
'Player.*.LastName' => 'required|between:2,30',
'Player.*.ContactNumber' => 'nullable|regex:/0\d{2}\s\d{3}\s\d{4}(?:\sext\.\s\d{1,5})?/',
'Player.*.EmailAddress' => 'required_if:Player.*.MailingList,Yes|email',
'Player.*.MailingList' => 'required|in:Yes,No',
mrockett's avatar

@Gck, I just tried that, but it doesn't seem to work nicely for players who are not being subscribed to the mailing list and do not have email addresses. In those cases, the email rule fails. I think it has something to do with the new L5.4 middleware, but adding nullable renders the required_if rule void.

mrockett's avatar

(Wish there was email_if:Player.*.MailingList,Yes :D )

mrockett's avatar

Oh, and those first options don't seem to work. Rule::item() is not a method, and required_unless requires two parameters.

Please or to participate in this conversation.