前面已经完成了添加文章表单的处理,但是假如我们要修改一篇文章的内容,这时就需要一个修改表单了。这一节就介绍该功能的实现。此外,该部分还涉及到子视图与表单重用的实现。
按照正常的工作流程,我们需要创建路由与视图。所以首先在 app/routes.php 中添加显示修改内容的路由:
Route::get('articles/{id}/edit', 'ArticlesController@edit');
这时在命令行输入下面的命令:
D:\wamp\www\laravel5>php artisan route:list
可以看到,列出了当前所有的路由。然而除了上面的路由,我们还需要保存修改的路由、删除文章的路由等。Laravel提供了一种方法来直接生成我们需要的所有的路由:resource
。现在编辑路由文件,注释掉所有与文章有关的路由,然后添加下面一段代码:
Route::resource('articles', 'ArticlesController');
这时,再次到命令行运行 php artisan route:list
,可以看到,除了刚才已经有的那些路由,还多出了Method
类型为 PUT
、PATCH
、DELETE
的三个路由。
现在到 ArticlesController.php 控制器文件添加下面的方法:
public function edit($id){ $article = Article::findOrFail($id); return view('articles.edit', compact('article')); }
接着,创建 resources\views\articles\edit.blade.php 文件:
@extends('main') @section('content') <h1>Edit {!! $article->title !!}</h1> <hr/> {!! Form::open(['method' => 'PATCH', 'action' => ['ArticlesController@update', $article->id]]) !!} <div class="form-group"> {!! Form::label('title', 'Title:') !!} {!! Form::text('title', null, ['class' => 'form-control']) !!} </div> <div class="form-group"> {!! Form::label('body', 'Body:') !!} {!! Form::textarea('body', null, ['class' => 'form-control']) !!} </div> <div class="form-group"> {!! Form::label('published_at', 'Publish on:') !!} {!! Form::input('date', 'published_at', date('Y-m-d'), ['class' => 'form-control']) !!} </div> <div class="form-group"> {!! Form::submit('Add Article', ['class' => 'btn btn-primary form-control']) !!} </div> {!! Form::close() !!} @if ($errors->any()) <div class="alert alert-danger"> @foreach($errors->all() as $error) <p>{{ $error }}</p> @endforeach </div> @endif @stop
表单部分就是从 create.blade.php 中复制过来的,只不过修改了 Form::open()
中表单提交地址。这时访问 http://laravel.dev/articles/1/edit ,查看源代码可以看到:
除了表单的 action
部分改变了之外,还多出了一个值为 PATCH
的隐藏域。
现在还有一个问题,我们要修改文章,但是表单里却没有出现文章的内容。多亏了Laravel的表单模型绑定,我们只需要简单的把上面视图中 Form::open()
部分替换成下面的代码:
{!! Form::model($article, ['method' => 'PATCH', 'action' => ['ArticlesController@update', $article->id]]) !!}
这时刷新表单,可以看到文章的内容已经显示在表单中了,只不过发布日期字段还没有变,这个留到后面再做处理。
现在在控制器中添加处理方法:
public function update($id, Request $request){ $article = Article::findOrFail($id); $article->update($request->all()); return redirect('articles'); }
现在需要考虑两个问题:1. 这个表单没有做任何的验证;2. 我们需要创建两个表单,而表单内容基本一样,我们希望通过一个表单就可以实现添加与修改的功能。
首先来解决验证的问题
之前已经创建过一个 app\Http\Requests\CreateArticleRequest.php 文件用来进行创建文章时的表单验证,现在为了简单起见,我们不再创建修改文章的表单验证文件,而是同创建文章共用同一个文件。把该文件重命名为 ArticleRequest.php,并把文件中类名修改为 ArticleRequest
。然后修改控制器中对该文件的引用部分。
rules()
方法中进行条件判断,然后返回不同的规则。我们这里需要的规则是一样的,所以不做修改。现在再次对文章进行修改,可以看到修改也成功了,而且表单验证功能也实现了。
现在解决表单重用问题
因为 create.blade.php 与 edit.blade.php 中错误提示的代码是一样的,所以我们先把该部分提出出来。创建 resources\views\errors\list.blade.php:
@if ($errors->any()) <div class="alert alert-danger"> @foreach($errors->all() as $error) <p>{{ $error }}</p> @endforeach </div> @endif
然后修改 create.blade.php 与 edit.blade.php 文件,把上面部分的内容替换为:
@include('errors.list')
现在来做表单部分的提取。
由于表单提交位置不同,所以我们只把 Form::open()
与 Form::close()
中间的部分提出来放到 resources\views\articles\_form.blade.php 文件中:
<div class="form-group"> {!! Form::label('title', 'Title:') !!} {!! Form::text('title', null, ['class' => 'form-control']) !!} </div> <div class="form-group"> {!! Form::label('body', 'Body:') !!} {!! Form::textarea('body', null, ['class' => 'form-control']) !!} </div> <div class="form-group"> {!! Form::label('published_at', 'Publish on:') !!} {!! Form::input('date', 'published_at', date('Y-m-d'), ['class' => 'form-control']) !!} </div> <div class="form-group"> {!! Form::submit('Add Article', ['class' => 'btn btn-primary form-control']) !!} </div>
然后修改 create.blade.php 与 edit.blade.php 文件,把上面部分的内容替换为:
@include('articles._form')
此时还有个小问题,就是创建文章与修改文章的表单中,提交按钮都是”Add Article”,而我们希望修改表单的提交按钮为”Update Article”。当然我们可以把按钮部分不提取出来,分别放在两个文件中,然后修改名字,但是为了文件的整洁,我们还是将按钮部分也提取出来,然后通过变量来设置按钮的名称。把表单按钮部分替换为如下:
{!! Form::submit($submitButtonText, ['class' => 'btn btn-primary form-control']) !!}
接着修改 create.blade.php 与 edit.blade.php 文件:
// create.blade.php文件 @include('articles._form', ['submitButtonText' => 'Add Article']) // edit.blade.php 文件 @include('articles._form', ['submitButtonText' => 'Update Article'])
此节完!
该篇属于专题:《Laravel 5 基础视频教程学习笔记》
IT疯狂女 2015/06/04 15:06
我猜博主是一个代码大大
dodo 2015/11/10 18:44
Route::resource 和 Route::any 有哪些区别?为什么要用 php artisan route:list 去查对应的类型,有别的方式吗?
Specs 2015/11/11 09:37
@ resource是把Controller里的Action(php artisan create:controller 生成的那些)都列出来,而any是可以接受GET,POST,PUT,DELETE等提交方式
lulu 2016/11/23 09:36
正在学习Laravel,配合Jeffrey的视频看博主的文章正好,超级感谢!
Specs 2016/11/27 05:31
@ 额 就是看的他的那个视频