首页 » Web技术 » Laravel » 正文

[Laravel 5 教程学习笔记] 十三、子视图与表单重用

前面已经完成了添加文章表单的处理,但是假如我们要修改一篇文章的内容,这时就需要一个修改表单了。这一节就介绍该功能的实现。此外,该部分还涉及到子视图与表单重用的实现。

按照正常的工作流程,我们需要创建路由与视图。所以首先在 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类型为 PUTPATCHDELETE 的三个路由。

现在到 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 ,查看源代码可以看到:

edit-form

除了表单的 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');
    }
PS:该方法中的参数位置是可以随意调换的。

现在需要考虑两个问题:1. 这个表单没有做任何的验证;2. 我们需要创建两个表单,而表单内容基本一样,我们希望通过一个表单就可以实现添加与修改的功能。

首先来解决验证的问题

之前已经创建过一个 app\Http\Requests\CreateArticleRequest.php 文件用来进行创建文章时的表单验证,现在为了简单起见,我们不再创建修改文章的表单验证文件,而是同创建文章共用同一个文件。把该文件重命名为 ArticleRequest.php,并把文件中类名修改为 ArticleRequest 。然后修改控制器中对该文件的引用部分

PS:如果创建文章与修改文章的验证规则不一致,可以在 rules() 方法中进行条件判断,然后返回不同的规则。我们这里需要的规则是一样的,所以不做修改。

现在再次对文章进行修改,可以看到修改也成功了,而且表单验证功能也实现了。

现在解决表单重用问题

因为 create.blade.phpedit.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.phpedit.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.phpedit.blade.php 文件,把上面部分的内容替换为:

@include('articles._form')

此时还有个小问题,就是创建文章与修改文章的表单中,提交按钮都是”Add Article”,而我们希望修改表单的提交按钮为”Update Article”。当然我们可以把按钮部分不提取出来,分别放在两个文件中,然后修改名字,但是为了文件的整洁,我们还是将按钮部分也提取出来,然后通过变量来设置按钮的名称。把表单按钮部分替换为如下:

{!! Form::submit($submitButtonText, ['class' => 'btn btn-primary form-control']) !!}

接着修改  create.blade.phpedit.blade.php 文件:

// create.blade.php文件
@include('articles._form', ['submitButtonText' => 'Add Article'])

// edit.blade.php 文件
@include('articles._form', ['submitButtonText' => 'Update Article'])

此节完!


该篇属于专题:《Laravel 5 基础视频教程学习笔记

本文共 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

      @ dodo resource是把Controller里的Action(php artisan create:controller 生成的那些)都列出来,而any是可以接受GET,POST,PUT,DELETE等提交方式

  • lulu 2016/11/23 09:36

    正在学习Laravel,配合Jeffrey的视频看博主的文章正好,超级感谢!

发表评论