php – Laravel form model binding-ThrowExceptions

Exception or error:

I’ve been reading about this feature: http://laravel.com/docs/html#form-model-binding

And it looks really neat, but there are couple of things that I’m not certain about.

Do I need to put any code in the controller action to process this form? What does that look like?

The model (User) I want to bind in my form has a separate table for addresses. So I want to be able to fill out the User model’s fields, but also the fields for the related Address model. Can I do that with form-model-binding, or do I have to handle the form manually?

Or, failing that, can I use form model binding for the user fields, but manually handle the address fields?

How to solve:

You don’t need any different code in your controller to process this form. All your (named) form variables will be in Input::all().

The model ($user) you pass in

Form::model($user, array('route' => array('user.update', $user->id)))

Is just any record you need to, if you have more than one table involved, you’ll have to do something like

$user = User::where('id',$userID)
           ->leftJoin('users_addresses', 'users_addresses.user_id', '=', 'users.id')
           ->first();

And pass this composed model to your Form::model().

How you name your inputs is entirely up to you, because you’ll have to write the logic to process your form. But, in my opinion users_address[street] for the address inputs is good, because you’ll end up with an array of addresses columns that you can pass right away to your UserAddress model.

<html>
    <head>
        <title></title>
    </head>
    <body>
        {{ Form::model($user, array('route' => array('user.update', $user->id))) }}
            {{ Form::label('first_name', 'First Name:', array('class' => 'address')) }}
            {{ Form::text('first_name') }}

            {{ Form::label('last_name', 'Last Name:', array('class' => 'address')) }}
            {{ Form::text('last_name') }}

            {{ Form::label('email', 'E-Mail Address', array('class' => 'address')) }}
            {{ Form::text('email') }}

            {{ Form::label('address[street1]', 'Address (Street 1)', array('class' => 'address')) }}
            {{ Form::text('address[street1]') }}

            {{ Form::label('address[street2]', 'Address (Street 2)', array('class' => 'address')) }}
            {{ Form::text('address[street2]') }}

            {{ Form::label('ddress[city]', 'City', array('class' => 'address')) }}
            {{ Form::text('address[city]') }}

            {{ Form::label('address[state]', 'State', array('class' => 'address')) }}
            {{ Form::text('address[state]') }}

            {{ Form::label('address[zip]', 'Zip Code', array('class' => 'address')) }}
            {{ Form::text('address[zip]') }}

            {{ Form::submit('Send this form!') }}
        {{ Form::close() }}
    </body>
</html>

And if you do dd( Input::all() ) in your controller, you’ll get something like this:

This is the Input::all() result
This result is provided by Kint’s dd(): https://github.com/raveren/kint. Really helpful.

If your form just have fields from a single Model, your update method can be very simple and look something like:

public function update($id)
{
    $user = User::find($id);

    if (!$user->update(Input::all())) {
        return Redirect::back()
                ->with('message', 'Something wrong happened while saving your model')
                ->withInput();
    }

    return Redirect::route('user.saved')
                ->with('message', 'User updated.');
}

On forms a little bit more complex, coders will have to add more logic to their controllers, in you case with a little bit more of research I think you can make this happen:

public function update($id)
{
    $user = User::find($id);

    $inputs = Input::all();

    if (!$user->update($inputs)) {
            $address = new UserAddress($inputs['address']);

        $user->address()->save($address);

        ...
    }

    ...
}

Answer´╝Ü

In Laravel 5.1 for relation model binding you just need to eager load relation table(s):

$user = User::with(['address'])->find($id);

And in view set fields names as array:

{!! Form::model($user, ['route' => ['user.update', $user->id]]) !!}
    {!! Form::text('address[street]') !!}
    {!! Form::text('address[number]') !!}
{!! Form::close() !!}

Leave a Reply

Your email address will not be published. Required fields are marked *