Laravel 使用相同的表单进行创建和编辑

Posted

技术标签:

【中文标题】Laravel 使用相同的表单进行创建和编辑【英文标题】:Laravel use same form for create and edit 【发布时间】:2014-05-15 15:48:40 【问题描述】:

我对 Laravel 很陌生,我必须创建一个用于创建的表单和一个用于编辑的表单。在我的表单中,我有很多 jquery ajax 帖子。我想知道 Laravel 是否确实为我提供了一种简单的方法来使用相同的表单进行编辑和创建,而无需在我的代码中添加大量逻辑。我不想在表单加载时每次为字段分配值时检查是否处于编辑或创建模式。关于如何以最少的编码完成此任务的任何想法?

【问题讨论】:

我不会那样做,分开负责创建和编辑的表单和控制器方法。 Laravel 提供了很好且简单的方法来为你填充表单字段 查看有关使用[Forms and html][laravel.com/docs/html]的文档,尤其是“打开一个新的模型表单” 另外,看看这个***问题***.com/questions/17510355/… 【参考方案1】:

在路由中使用any

Route::any('cr', [CreateContent::class, 'create_content'])
->name('create_resource');

在控制器中使用

User::UpdateOrCreate([id=>$user->id], ['field_name'=>value, ...]);

【讨论】:

【参考方案2】:

您可以在单个刀片文件中使用@$variable 进行创建和编辑。变量未定义时不会出错。

<input name="name" value="@$your_variable->name">

【讨论】:

“STFU”操作符在这里是一个hackfix。检查应该在变量渲染之前完成。【参考方案3】:

我喜欢使用model binding 表单,因此我可以轻松地用相应的值填充表单的字段,所以我采用这种方法(例如使用user 模型):

@if(isset($user))
     Form::model($user, ['route' => ['updateroute', $user->id], 'method' => 'patch']) 
@else
     Form::open(['route' => 'createroute']) 
@endif

     Form::text('fieldname1', Input::old('fieldname1')) 
     Form::text('fieldname2', Input::old('fieldname2')) 
    -- More fields... --
     Form::submit('Save', ['name' => 'submit']) 
 Form::close() 

所以,例如,从一个控制器,我基本上使用相同的形式来创建和更新,比如:

// To create a new user
public function create()

    // Load user/createOrUpdate.blade.php view
    return View::make('user.createOrUpdate');


// To update an existing user (load to edit)
public function edit($id)

    $user = User::find($id);
    // Load user/createOrUpdate.blade.php view
    return View::make('user.createOrUpdate')->with('user', $user);

【讨论】:

这是一种少写多做的好方法,我的大多数管理控制器都使用这种方法和resource/Restful控制器:-) 您还可以采用将表单拆分为部分的方法 - 完整表单或表单部分的较小视图。然后,您可以拥有两个包装器 - 一个用于创建,一个用于更新,每个都可以提取他们需要的表单部分。根据您的用例的复杂程度,以及创建与更新表单是否应该与最终用户完全一致,这可能比将其全部压缩到具有多个条件部分的一个视图中更易于管理。 它不再是 Laravel 核心的一部分。 @Lee,我知道。检查此答案的日期。它很久以前就得到了回答并且是有效的,所以...... 我对这个解决方案有点吃力,因为我是初学者,解决方案没有明确说明我必须在 routes/web.php 中定义 createroute/updateroute【参考方案4】:

希望对你有帮助!!

form.blade.php

@php
$name         = $user->name ?? null;
$email        = $user->email ?? null;
$info         = $user->info ?? null;
$role         = $user->role ?? null;
@endphp

<div class="form-group">
        !! Form::label('name', 'Name') !!
        !! Form::text('name', $name, ['class' => 'form-control']) !!
</div>

<div class="form-group">
        !! Form::label('email', 'Email') !!
        !! Form::email('email', $email, ['class' => 'form-control']) !!
</div>

<div class="form-group">
        !! Form::label('role', 'Função') !!
        !! Form::text('role', $role, ['class' => 'form-control']) !!
</div>

<div class="form-group">
        !! Form::label('info', 'Informações') !!
        !! Form::textarea('info', $info, ['class' => 'form-control']) !!
</div>

<a class="btn btn-danger float-right" href=" route('users.index') ">CANCELAR</a>

create.blade.php

@extends('layouts.app')

@section('title', 'Criar usuário')

@section('content')
        !! Form::open(['action' => 'UsersController@store', 'method' => 'POST'])  !!
            @include('users.form')
            <div class="form-group">
                !! Form::label('password', 'Senha') !!
                !! Form::password('password', ['class' => 'form-control']) !!
            </div>
            <div class="form-group">
                !! Form::label('password', 'Confirmação de senha') !!
                !! Form::password('password_confirmation', ['class' => 'form-control']) !!
            </div>
            !! Form::submit('ADICIONAR', array('class' => 'btn btn-primary')) !!
        !! Form::close() !!
@endsection

edit.blade.php

@extends('layouts.app')

@section('title', 'Editar usuário')

@section('content')
        !! Form::model($user, ['route' => ['users.update', $user->id], 'method' => 'PUT']) !!
            @include('users.form', compact('user'))
            !! Form::submit('EDITAR', ['class' => 'btn btn-primary']) !!
        !! Form::close() !!
        <a href="route('users.editPassword', $user->id)">Editar senha</a>
@endsection

UsersController.php

use App\User;

Class UsersController extends Controller 
  #... 
    public function create()
    
        return view('users.create';
    

    public function edit($id)
    
        $user  = User::findOrFail($id);
        return view('users.edit', compact('user');
    

【讨论】:

【参考方案5】:

为创建添加一个空对象到视图。

return view('admin.profiles.create', ['profile' => new Profile()]);

旧函数有第二个参数,默认值,如果你把对象的字段传递给那里,输入可以被重用。

<input class="input" type="text" name="name" value="old('name', $profile->name)">

对于表单操作,您可以使用正确的端点。

<form action=" $profile->id == null ? '/admin/profiles' :  '/admin/profiles/' . $profile->id  " method="POST">

对于更新,您必须使用 PATCH 方法。

@isset($profile->id)
  method_field('PATCH')
@endisset

【讨论】:

您可以使用$profile-&gt;exists 而不是$profile-&gt;id,这样与模型无关;) 这应该是正确的答案。对于那些不(想要)使用 LaravelCollective Form 包的人。如果你真的和网页设计师一起工作,我们应该尽可能地在刀片视图中坚持纯 html。这不是VMC的重点吗?只是,请注意 post 与 patch 方法。 同意。这是正确的方法。按照建议使用 ->exists 。表单库强加了太多的布局,一般来说是有用的。迟早你会意识到你无法让它做你想做的事,并且忘记了如何编写简单的 html 表单输入。 novate.co.uk/reusing-form-in-laravel-for-both-create-and-update 另一个提示是,如果操作 url 取决于逻辑,您可以从控制器传递它的值。它将逻辑排除在视图之外,因此更简洁。 有没有更好的方法来处理子对象?目前我有old('stat_file_date', !empty($data_request-&gt;enrollment_data-&gt;stat_file_date) ? $data_request-&gt;enrollment_data-&gt;stat_file_date : null),它可以工作,但真的很麻烦......问题是在尝试创建新对象时,没有任何子对象,因此它无法获取值并抛出异常“尝试获取属性” stat_file_date' 非对象"【参考方案6】:

例如,您的控制器,检索数据并放置视图

class ClassExampleController extends Controller


    public function index()
       

        $test = Test::first(1);

        return view('view-form',[
            'field' => $test,
        ]);
    

在同一个表单中添加默认值,创建和编辑,很简单

<!-- view-form file -->
<form action=" 
    isset($field) ? 
    @route('field.updated', $field->id) : 
    @route('field.store')
">
    <!-- Input case -->
    <input name="name_input" class="form-control" 
    value=" isset($field->name) ? $field->name : '' ">
</form>

而且,您记得添加 csrf_field,以防 POST 方法请求。因此,重复输入,并选择元素,比较每个选项

<select name="x_select">
@foreach($field as $subfield)

    @if ($subfield == $field->name)
        <option val="i" checked>
    @else
        <option val="i" >
    @endif

@endforeach
</select>

【讨论】:

【参考方案7】:

您可以在Controller 中使用表单绑定和 3 种方法。这就是我的工作

class ActivitiesController extends BaseController 
    public function getAdd() 
        return $this->form();
    
    public function getEdit($id) 
        return $this->form($id);
    
    protected function form($id = null) 
        $activity = ! is_null($id) ? Activity::findOrFail($id) : new Activity;

        //
        // Your logic here
        //

        $form = View::make('path.to.form')
            ->with('activity', $activity);

        return $form->render(); 
    

在我看来,我有

 Form::model($activity, array('url' => "/admin/activities/form/$activity->id", 'method' => 'post')) 
 Form::close() 

【讨论】:

【参考方案8】:
    Article is a model containing two fields - title and content 
    Create a view as pages/add-update-article.blade.php   

        @if(!isset($article->id))
            <form method = "post" action="add-new-article-record">
            @else
             <form method = "post" action="update-article-record">
            @endif
                 csrf_field()  

                <div class="form-group">
                    <label for="title">Title</label>            
                    <input type="text" class="form-control" id="title" placeholder="Enter title" name="title" value=$article->title>
                    <span class="text-danger"> $errors->first('title') </span>
                </div>
                <div class="form-group">
                    <label for="content">Content</label>
                    <textarea class="form-control" rows="5" id="content" name="content">
                    $article->content

                    </textarea>
                    <span class="text-danger"> $errors->first('content') </span>
                </div>
                <input type="hidden" name="id" value=" $article->id "> 
                <button type="submit" class="btn btn-default">Submit</button>
            </form>

Route(web.php): Create routes to controller 

        Route::get('/add-new-article', 'ArticlesController@new_article_form');
        Route::post('/add-new-article-record', 'ArticlesController@add_new_article');
        Route::get('/edit-article/id', 'ArticlesController@edit_article_form');
        Route::post('/update-article-record', 'ArticlesController@update_article_record');

Create ArticleController.php
       public function new_article_form(Request $request)
    
        $article = new Articles();
        return view('pages/add-update-article', $article)->with('article', $article);
    

    public function add_new_article(Request $request)
    
        $this->validate($request, ['title' => 'required', 'content' => 'required']);
        Articles::create($request->all());
        return redirect('articles');
    

    public function edit_article_form($id)
    
        $article = Articles::find($id);
        return view('pages/add-update-article', $article)->with('article', $article);
    

    public function update_article_record(Request $request)
    
        $this->validate($request, ['title' => 'required', 'content' => 'required']);
        $article = Articles::find($request->id);
        $article->title = $request->title;
        $article->content = $request->content;
        $article->save();
        return redirect('articles');
     

【讨论】:

您可以在其中添加一些文字来解释它与原始 Q 的关系。【参考方案9】:

用户控制器.php

use View;

public function create()

    return View::make('user.manage', compact('user'));


public function edit($id)

    $user = User::find($id);
    return View::make('user.manage', compact('user'));

user.blade.php

@if(isset($user))
     Form::model($user, ['route' => ['user.update', $user->id], 'method' => 'PUT']) 
@else
     Form::open(['route' => 'user.store', 'method' => 'POST']) 
@endif

// fields

 Form::close() 

【讨论】:

【参考方案10】:

您应该使用findOrNew() 方法,而不是创建两种方法——一种用于创建新行,另一种用于更新。所以:

public function edit(Request $request, $id = 0)

    $user = User::findOrNew($id);
    $user->fill($request->all());
    $user->save();

【讨论】:

【参考方案11】:

在你的控制器中很容易做到:

public function create()

    $user = new User;

    $action = URL::route('user.store');

    return View::('viewname')->with(compact('user', 'action'));


public function edit($id)

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

    $action = URL::route('user.update', ['id' => $id]);

    return View::('viewname')->with(compact('user', 'action'));

而你只需要这样使用:

 Form::model($user, ['action' => $action]) 

    Form::input('email') 
    Form::input('first_name') 

 Form::close() 

【讨论】:

谢谢安东尼奥。如果你能帮忙,你的代码的第二部分是做什么的,它在哪里做 Form::model、Form::input 和 Form::close()? 根据创建或更新使用 POST 或 PATCH 方法如何处理? form:model 将不起作用,因为您没有使用 PATCH 或 PUT! 怎么用patch代替? 我的代码有问题,我花了几分钟才发现应该使用“url”而不是“action”。像这样: Form::model($user, ['url' => $action]) 希望这对其他人有所帮助。【参考方案12】:

在 Rails 中,它有 form_for 助手,所以我们可以创建一个类似于 form_for 的函数。

我们可以制作一个Form宏,例如在resource/macro/html.php中:

(如果你不知道如何设置宏,你可以谷歌“laravel 5 Macro”)

Form::macro('start', function($record, $resource, $options = array())
    if ((null === $record || !$record->exists()) ? 1 : 0) 
        $options['route'] = $resource .'.store';
        $options['method'] = 'POST';
        $str = Form::open($options);
     else 
        $options['route'] = [$resource .'.update', $record->id];
        $options['method'] = 'PUT';
        $str = Form::model($record, $options);
    
    return $str;
);

控制器:

public function create()

    $category = null;
    return view('admin.category.create', compact('category'));


public function edit($id)

    $category = Category.find($id);
    return view('admin.category.edit', compact('category'));

然后在视图中_form.blade.php:

!! Form::start($category, 'admin.categories', ['class' => 'definewidth m20']) !!
// here the Form fields
!! Form::close() !!

然后查看create.blade.php:

@include '_form'

然后查看edit.blade.php:

@include '_form'

【讨论】:

【参考方案13】:

简单干净:)

UserController.php

public function create() 
    $user = new User();

    return View::make('user.edit', compact('user'));


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

    return View::make('user.edit', compact('user'));

edit.blade.php

 Form::model($user, ['url' => ['/user', $user->id]]) 
    Form::text('name') 
   <button>save</button>
 Form::close() 

【讨论】:

干净的代码。但是如果用户取消注册或多次刷新注册页面或重新启动浏览器(即销毁会话)怎么办?表格中会有很多模糊/不完整的条目 $user = new User(); - 它不执行 sql 查询。新条目仅在您的 UPDATE 或 STORE 方法中添加到 sql 中。【参考方案14】:

另一种带有小控制器、两个视图和一个局部视图的干净方法:

UsersController.php

public function create()

    return View::('create');
    

public function edit($id)

    $user = User::find($id);
    return View::('edit')->with(compact('user'));

create.blade.php

 Form::open( array( 'route' => ['users.index'], 'role' => 'form' ) ) 
    @include('_fields')
 Form::close() 

edit.blade.php

 Form::model( $user, ['route' => ['users.update', $user->id], 'method' => 'put', 'role' => 'form'] ) 
    @include('_fields')
 Form::close() 

_fields.blade.php

 Form::text('fieldname1') 
 Form::text('fieldname2') 
 Form::button('Save', ['type' => 'submit']) 

【讨论】:

您如何处理使用保存的内容(如果正在编辑)或提交的内容(如果验证失败)预填充表单字段? 它是自动的。创建/更新失败时:使用输入数组完成重新填充。在 get /edit :由于 Form::model() 从模型中获取数据 我认为这实际上是给出的最干净/最好的答案。 但是如何将所有已编辑的字段实际保存到对象中?我在示例中看到您所做的只是在控制器中查找对象然后创建新视图?你实际保存编辑的位置呢? @SamuelDeBacker @Max 将编辑保存在更新方法上。像$return = DB::transaction(function($id) use ($id) $input = Input::all(); $user = User::find($id); $user-&gt;name = $input['name']; return $user-&gt;save(); ); 这样你就可以if($return) return Redirect::to('user'); else return Redirect::back()-&gt;withInput();

以上是关于Laravel 使用相同的表单进行创建和编辑的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5.5 CRUD 表单选择的正确方法

无法在 Laravel 的编辑表单中检索旧数据

编辑表单刀片 Laravel 中的嵌套循环

Laravel 在商店和更新上的表单请求验证使用相同的验证

为 Laravel 表单字段定义默认值

Laravel 5.2 如何使用多选填充编辑表单?