Laravel 表单模型绑定

Posted

技术标签:

【中文标题】Laravel 表单模型绑定【英文标题】:Laravel form model binding 【发布时间】:2013-05-28 05:46:02 【问题描述】:

我一直在阅读有关此功能的信息:http://laravel.com/docs/html#form-model-binding

它看起来很整洁,但有几件事我不确定。

我是否需要在控制器操作中添加任何代码来处理此表单?那是什么样子的?

我想在表单中绑定的模型(用户)有一个单独的地址表。所以我希望能够填写用户模型的字段,以及相关地址模型的字段。我可以使用 form-model-binding 做到这一点,还是必须手动处理表单?

或者,如果失败了,我可以对用户字段使用表单模型绑定,但手动处理地址字段吗?

【问题讨论】:

【参考方案1】:

在 Laravel 5.1 中用于关系模型绑定,您只需要预先加载关系表:

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

并在视图中将字段名称设置为数组:

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

【讨论】:

【参考方案2】:

您不需要控制器中的任何其他代码来处理此表单。所有(命名的)表单变量都将在 Input::all() 中。

你传入的模型($user)

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

只是您需要的任何记录,如果您涉及多个表,则必须执行类似的操作

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

并将这个组合模型传递给您的 Form::model()。

如何命名输入完全取决于您,因为您必须编写逻辑来处理您的表单。但是,在我看来 users_address[street] 输入地址很好,因为您最终会得到一个地址列数组,您可以立即将其传递给您的 UserAddress 模型。

<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>

如果你在控制器中执行dd( Input::all() ),你会得到这样的结果:

该结果由 Kint 的 dd() 提供:https://github.com/raveren/kint。真的很有帮助。

如果您的表单只有来自单个模型的字段,您的更新方法可以非常简单,如下所示:

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.');

在稍微复杂一点的表单上,编码人员将不得不向他们的控制器添加更多逻辑,在你的情况下,通过更多的研究,我认为你可以做到这一点:

public function update($id)

    $user = User::find($id);

    $inputs = Input::all();

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

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

        ...
    

    ...

【讨论】:

这很漂亮。那么如何格式化字段名称属性中的属性名称呢?喜欢users_address.streetusers_address[street] 或其他方式? 另外,如果我通过 Auth:user() 检索用户怎么办?我可以 Auth:user()->leftJoin('users_addresses', 'users.id', '=', 'users_addresses.user_id') 吗? dd() 会生成漂亮的可折叠数组视图吗?以前从未见过。看起来像krumo,但可能更好。无论如何,我认为模型表单绑定在将字段保存到模型方面做了一些神奇的事情。文档说了一些关于使您的表单输入名称与模型的字段名称匹配的内容。也许这只是为了填充字段?但如果是这种情况,是否有一个标准可以遵循来填充地址字段? dd() 来自 Kint 包,上面贴了一个链接。据我所知,对于简单的表格,表格模型在某种程度上是神奇的。刚刚添加了一个例子。您只需要$user-&gt;update(Input::all()) 即可保存您的表单。 Auth:user() 已经是一个模型,我不确定你是否可以对它进行新的查询,但是在 Laravel 中进行所有这些注入,一切皆有可能。但是你可以在你的用户模型中添加一个新的属性,然后像 $user->user_with_address 一样调用它,它会做任何你需要的事情来让你的用户使用你的地址。

以上是关于Laravel 表单模型绑定的主要内容,如果未能解决你的问题,请参考以下文章

Laravel:重复字段(和字段组):表单模型绑定

Laravel 5 表单模型绑定复选框值

laravel 5.2 中的表单模型绑定

Laravel形式模型绑定

使用 Laravel 表单模型绑定和复选框更新多对多 Eloquent 关系

Laravel 5.0 路由模型绑定在销毁操作中不起作用