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

TimeSocks's avatar

Form Request Validation for Dynamically Generated Fields?

Hi,

I have a form that dynamically generates a set of 3 fields based on the user's choice, e.g. if they specify they want to book tickets for 2 people, 2 sets of 3 fields (name, e-mail address, phone number) are generated. Here's my blade code for doing that:

@for($i = 0; $i < $data['ticketno']; $i++)
    <h3>Ticket {{$i+1}}</h3>
    <div class="form-group">
        {!! Form::label('name[{{ $i }}]',' Name:') !!}
        {!! Form::text('name[{{ $i }}]', null, ['class' => 'form-control']) !!}
    </div>

    <div class="form-group">
        {!! Form::label('email[{{ $i }}]',' E-mail Address:') !!}
        {!! Form::text('email[{{ $i }}]', null, ['class' => 'form-control']) !!}
    </div>

    <div class="form-group">
        {!! Form::label('tel[{{ $i }}]',' Telephone Number:') !!}
        {!! Form::text('tel[{{ $i }}]', null, ['class' => 'form-control']) !!}
    </div>
    <hr/>
@endfor

Now, naturally I want to validate these, so after a quick search I found this page: http://ericlbarnes.com/laravel-array-validation/

And have tried to adapt the code therein, given that I have 3 dynamically generated fields, not one:

// BookStepTwoRequest.php
public function rules()
    {
         foreach($this->request->get('name') as $key => $val)
         {
           $rules['name.'.$key] = 'required';
         }

         foreach($this->request->get('email') as $key => $val)
         {
           $rules['email.'.$key] = 'required|email';
         }

         foreach($this->request->get('tel') as $key => $val)
         {
           $rules['delegate_tel.'.$key] = 'required|numeric';
         }

         return $rules;
    }

However, when I run this, I get:

ErrorException in BookStepTwoRequest.php line 24:
Invalid argument supplied for foreach()

Line 24 is the first foreach.

How can I fix this? Or is there a better way to go about the whole thing anyway?

0 likes
4 replies
pmall's avatar

You have to better structure the name of your html fields :

  • users[0][email]
  • users[0][name]
  • users[1][email]
  • users[1][name]
  • users[2][email]
  • users[2][name]

Then you will receive a user array you can loop through to construct your rules with dot notation

public function rules ()
{
    $rules = []

    for ($i = 0; $i < count($this->users); $i++) {

        $rules['users.' . $i . '.email'] = 'required|email|...';
        $rules['users.' . $i . '.name'] = 'required|...';

    }

    return $rules;
}
6 likes
TimeSocks's avatar

@pmall Hmmm, well, I have no idea if that works because I'm getting another error that seems unrelated... perhaps you would be so kind as to help me out with that as well? Basically I have a multi-page form setup. Here's my controller:

public function show($id)
    {
        $instance = Instance::with(['event','venues'])->whereId($id)->first();

        session()->put('instance', $instance);

        return view('book.show',compact('instance'));

    }

    public function stepTwo(Requests\BookingFormRequest $request)
    {
        $data = $request->all();
        $session = session()->get('instance');

        session()->put('booker',$data);

        return view('book.stepTwo',compact(['data','session']));
    }

    public function stepThree(Requests\BookStepTwoRequest $request)
    {
        $tickets= $request->all();
        $booker = session()->get('booker');
        $instance = session()->get('instance');

        return 'Success';
    }

Here's my routes for this part of the app:

//Booking
Route::resource('book','BookController');
Route::post('book/{id}/steptwo','BookController@stepTwo');
Route::get('book/{id}/steptwo','BookController@show');
Route::post('book/{id}/stepthree','BookController@stepThree');
Route::get('book/{id}/stepthree','BookController@show');

So to stop people jumping in further along the booking process I'm checking for GET requests and redirecting to the first page of the form, ie show.

My forms have the following methods/actions:

{!! Form::open(['method' => 'POST','action' => 'BookController@stepTwo']) !!}

{!! Form::open(['method' => 'POST','action' => 'BookController@stepThree']) !!}

Step/Page Two is where my dynamically generated fields are, incidentally. However, when I try and submit step two, I get the following error:

ErrorException in f8ededd3fac4e77e742cef8446129760 line 10:
Trying to get property of non-object (View: /home/vagrant/Code/myapp/resources/views/book/show.blade.php)

The fact that it's showing the error in show.blade.php suggests to me that it's trying to return to Step One, but I don't see why it would do that - surely it should either redirect back to Step Two if there are validation errors, or carry on to Step Three and, for now, just return a string?

EDIT: Ah-ha! I've just switched out the custom Form Request for a generic Request, and it works. So it's a problem in the custom Request, it would appear. Or the fact that it's trying to validate in any case... hmmm.

jjackson's avatar

It's not sending the proper variables to your blade template.

Trying to get property of non-object (View: /home/vagrant/Code/myapp/resources/views/book/show.blade.php)

Btw did you solve this problem?

Alexmg86's avatar

Hi! in the documentation https://laravel.com/docs/5.2/validation

Validating Arrays

Validating array form input fields doesn't have to be a pain. For example, to validate that each e-mail in a given array input field is unique, you may do the following:

$validator = Validator::make($request->all(), [
    'person.*.email' => 'email|unique:users',
    'person.*.first_name' => 'required_with:person.*.last_name',
]);
3 likes

Please or to participate in this conversation.