Skip navigation

Category Archives: PHP

I’ve been making a fair few forms with the Laravel form-builder using model-binding. A few times I’ve had to make the user select a value for a one-to-many relation.

What’s the problem with model-binding and select-boxes?

In this example we’ll go with the status for a key (‘on loan’,’ at home’, or ‘broken’). The natural choice is a select-box, where the current state should already be chosen if we are editing the key.
The immediate solution is to just useĀ  the ‘state’-property for the model-binding

 {{Form::select('keystatus', $keyStatus, null)}}

However, if you send a collection of models to a select box, you will end up with a weird box:

A botched select-box with json-representation of models - this won't work with model-binding.

A very unusable select-box

As you can see, this is the JSON-representation of the models – this won’t work.

The solution

This first obstacle is solved through a simple foreach-loop:

$statuses = Keystatus::all();
foreach($statuses AS $status){
$statusList[$status->id] = $status->status;
}
$view->with(array('statuses'=>$statusList));

This is taken from my composer-file. As you can see, I get a nice array with the id for key and whatever text I want as the value.

Next step is to put it in the select-box and make the Laravel model-binding work it’s magic.

The tricky thing is, that the status on my key is an object, and doesn’t match whatever is in my array. Instead I put the status_id as the name of my select-box. This way the value in my status_id-column will match one of the keys in the array:

{{Form::select('status_id', $key, null)}}

Don’t forget to set the third parameter (default chosen value) to null. This allows the model-binding to work its magic. The last thing to do, is to adapt my controller to either save the id directly in the status_id-property, or load the status using Status::find($input[“status_id”]); and then associate that to the key:

//Either do this
$key->keystatus_id = $input["keystatus_id"];

//Or do this:
$state = KeysStatus::find($input["keystatus_id"]);
$key->keystatus()->associate($state);

Personally I prefer the first method, as it save me a few calls to the database.

Fork me on GitHub