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

cosminc's avatar

Checking for validation error and feching the error in a Blade template when having an associative array of inputs

Hello,

I'm struggling to check for validation errors and then fetch the errors in a Blade template when I'm having an array of inputs. I've simplified the HTML and PHP code for demonstration purposes.

The HTML code:

<form>
	<p>Title</p>
	Female: <input type="text" name="title[female]">
	Male: <input type="text" name="title[male]">

	<p>Female Answers</p>
	<input type="text" name="answer[female][]">
	<input type="text" name="answer[female][]">
	<input type="text" name="answer[female][]">

	<p>Male Answers</p>
	<input type="text" name="answer[male][]">
	<input type="text" name="answer[male][]">
	<input type="text" name="answer[male][]">
</form>

The validation rules are defined as following:

$rules = [
	'title.*' => 'required|min:10|max:255',
	'answer.females.*' => 'required',
	'answer.males.*' => 'required'
];

The problem is that when I trying to reach for this errors in the template I get an error like:

htmlspecialchars() expects parameter 1 to be string, array given [...]

I tried multiple approaches for checking for the errors but none of them worked:

{{ $errors->has('title.' . $gender) ? 'form-error' : '' }}
{{ $errors->has('title')[$gender] ? 'form-error' : '' }}
{{ $errors->has('title.{$gender}') ? 'form-error' : '' }}

// Where $gender contains the gender as string, like "females", "males".

Any help is highly appreciated.

0 likes
8 replies
rodrigo.pedra's avatar

Use the blade @\error directive (note I added a backslash to not tag any user).

Also in cases like this I like to hardcode the index. Your form request's validation can still use the * notation.

<form>
    <p>Title</p>
    Female: <input type="text" name="title[female]">
    Male: <input type="text" name="title[male]">

    <p>Female Answers</p>
    @foreach(\range(0, 3) as $index)
        <input type="text" name="answer[female][{{ $index }}]">
        @error("answer[female][{$index}]")
            <p>{{ $message }}</p>
        @enderror
    @endforeach

    <p>Male Answers</p>
    @foreach(\range(0, 3) as $index)
        <input type="text" name="answer[male][{{ $index }}]">
        @error("answer[male][{$index}]")
            <p>{{ $message }}</p>
        @enderror
    @endforeach
</form>

Reference: https://laravel.com/docs/8.x/blade#validation-errors

rodrigo.pedra's avatar

One note:

inside the @\error directive I am using one pair of brackets because it is a regular PHP string interpolation, hence the double quotes. And also I didn't add spaces within brackets due to the same reason.

In the name attribute I am using double brackets because there you need blade's interpolation.

cosminc's avatar

@rodrigo.pedra, I don't think that @\error is available in Laravel 5.x, but I will look it up. Unfortunately, I can't use the loop approach, I have to access the errors as shown in the original post.

rodrigo.pedra's avatar

Try this then:

<?php
    $hasError = $errors->getBag('default')->hasAny([
        'title.male',
        'title.female',
        'answer.female.0',
        'answer.female.1',
        'answer.female.2',
        'answer.male.0',
        'answer.male.1',
        'answer.male.2',
    ]);
?>

<form class="{{ $hasError ? 'form-error' : '' }}">
    <p>Title</p>
    Female: <input type="text" name="title[female]">
    Male: <input type="text" name="title[male]">

    <p>Female Answers</p>
    <input type="text" name="answer[female][0]">
    <input type="text" name="answer[female][1]">
    <input type="text" name="answer[female][2]">

    <p>Male Answers</p>
    <input type="text" name="answer[male][0]">
    <input type="text" name="answer[male][1]">
    <input type="text" name="answer[male][2]">
</form>

Or if this is the only form on this view:

<form class="{{ $errors->any() ? 'form-error' : '' }}">
    <p>Title</p>
    Female: <input type="text" name="title[female]">
    Male: <input type="text" name="title[male]">

    <p>Female Answers</p>
    <input type="text" name="answer[female][]">
    <input type="text" name="answer[female][]">
    <input type="text" name="answer[female][]">

    <p>Male Answers</p>
    <input type="text" name="answer[male][]">
    <input type="text" name="answer[male][]">
    <input type="text" name="answer[male][]">
</form>
rodrigo.pedra's avatar

Just for note:

$errors->any() is available since Laravel 5.2.

$errors->getBag(...)->hasAny(...) is also available since Laravel 5.2.

Internally the $errors variable is an instance of the Illuminate\Support\ViewErrorBag class:

https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/ViewErrorBag.php

And that one stores its messages on a Illuminate\Support\MessageBag

https://github.com/laravel/framework/blob/8.x/src/Illuminate/Support/MessageBag.php

You can use GitHub's blame button on those pages to see when each line was added/updated.

a4ashraf's avatar

@cosminc

this is working for me

and its showing an error when I try this

{{ $errors->has('title.' . $gender) ? 'form-error' : '' }}

see what is my implementation



// in bade file 

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

// Or

{{ $errors->has('title.' . $gender) ? 'form-error' : '' }} // it show me form error

<form action="{{ route('submit') }}" method="post">
		@csrf
		<p>Title</p>
		Female: <input type="text" name="title[female]">
		Male: <input type="text" name="title[male]">

		<p>Female Answers</p>
		<input type="text" name="answer[female][]">
		<input type="text" name="answer[female][]">
		<input type="text" name="answer[female][]">

		<p>Male Answers</p>
		<input type="text" name="answer[male][]">
		<input type="text" name="answer[male][]">
		<input type="text" name="answer[male][]">

		<input type="submit" name="submit" value="submit" />
	</form>


// my controller function 


 $validatedData = $request->validate([
            'title.*' => 'required|min:10|max:255',
            'answer.females.*' => 'required',
            'answer.males.*' => 'required'
        ]);

        dd($validatedData);
cosminc's avatar

@a4ashraf, that's weird, it doesn't work for me.

Could it be because I'm creating a validator like shown bellow?

$validator = Validator::make($request->all(), $rules);

if ($validator->fails()) {
    return redirect('some/route')
        ->withErrors($validator)
        ->withInput();
}
a4ashraf's avatar

@cosminc

this is also working when I apply your code

make sure you are route on that blade file where you are showing the error code


$validator = Validator::make($request->all(), $rules);

$validator = Validator::make($request->all(), [
            'title.*' => 'required|min:10|max:255',
            'answer.females.*' => 'required',
            'answer.males.*' => 'required'
        ]);

        if ($validator->fails()) {
            return redirect('view-name')
                        ->withErrors($validator)
                        ->withInput();
        }

Please or to participate in this conversation.