I want to use form model binding in Laravel. The following (simplified) example works fine:
{{ Form::model($user, array('class'=>'form-horizontal')) }}
{{ Form::token() }}
{{ Form::label('email', 'Email Address') }}
{{ Form::text('email') }}
{{ Form::close() }}
However, I want to use arrays in the name
attributes, as is pretty standard nowadays. In other words, have user[email]
as the field name, so that I get all the form elements in one array in the backend.
Is this possible with model binding? When I use {{ Form::text('user[email]') }}
the email does not get filled in. I tried adding array('user'=>$user)
in the Form::model
function in case it needed a nested value, but no luck.
Form::model(array('user' => $user))
is the correct solution, BUT unfortunately the implementation of form model binding is pretty bad as it does not easily work on a nested, mixed set of arrays and objects. See https://github.com/laravel/framework/pull/5074
You could try Form::model(array('user' => $user->toArray()))
or Form::model((object) array('user' => $user))
.
You could do something like this assuming that you would have a single $user
and multiple $types
Form::macro('userTypes', function($user,$types)
{
foreach ($types as $type) {
$concat = $user . "_" . $type;
return '<input type="{$type}" name="{$concat}">';
}
});
And customize the output with your form style, even adding more complexity to the function might be required.
And then simply calling it for example
$user = "johndoe";
$types = array("email","text");
Form::userTypes($user,$types);
That would result in
<input type="email" name="johndoe_email">
<input type="text" name="johndoe_phone">
If you want to do it in a single line and assuming that you would have a single $user
and a single$type
you could do something like
Form::macro('userType', function($user,$type)
{
return '<input type="{$type}" name="{$user[$type]}">';
});
And with the call
$user = [ "mail" => "some_mail_value" ];
Form::userType($user,"mail");
Would result in
<input type="mail" name="some_mail_value">
Or perhaps you'd like something that would work with a single $user key-value array as :
Form::macro('userType', function($user)
{
$keys = array_keys($user);
foreach ($keys as $key => $value) {
return '<input type="{$key}" name="{$value}">';
}
});
And with the call
$user = ["mail" => "mail_value" , "text" => "text_value"];
Form::userType($user);
That would result in
<input type="mail" name="mail_value">
<input type="text" name="text_value">
And finally I didn't find a direct way to do it with default form model binding, as It requires the field name to be the same as the model attribute, but you could do a workaround as
Form::macro('customBind', function($user_model,$type)
{
return '<input type={$type} name="user[{$type}]" value="{$user_model->$type}">';
});
And then
$user = new User();
$user->email = "johndoe@gmail.com";
Form::customBind($user,"email");
Which would produce something like
<input type="email" name="user[email]" value="johndoe@gmail.com">
The takeaway point is that basically the solution to your problem is creating a Macro, I have provided some workarounds on this but you will need to refine this to your specific needs.