Laravel 系列入门教程四【最适合中国人的 Laravel 教程】

本篇文章中,我将跟大家一起实现 Article 的新增、编辑和删除功能,仔细解读每一段代码,相信本篇文章看完,你就能够 get Laravel 使用之道。

RESTful 资源控制器

资源控制器是 Laravel 内部的一种功能强大的约定,它约定了一系列对某一种资源进行“增删改查”操作的路由配置,让我们不再需要对每一项需要管理的资源都写 N 行重复形式的路由。中文文档见:<a href=https://d.laravel-china.org/docs/5.5/controllers#resource-controllers rel=nofollow>https://d.laravel-china.org/docs/5.5/controllers#resource-controllers

我们只需要写一行简单的路由:

<div class=highlight highlight-text-html-php> <div class=cnblogs_code>

Route::<span style=color: #0000ff>resource('photo','PhotoController');

就可以得到下面 7 条路由配置:

<a href=https://camo.githubusercontent.com/57f463311031716621afe049a8fcc62989279707/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333732343432323536382e6a70673f743d32 rel=noopener noreferrer target=_blank><img src=https://camo.githubusercontent.com/57f463311031716621afe049a8fcc62989279707/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333732343432323536382e6a70673f743d32 alt= data-canonical-src=https://www.jb51.cc/res/2019/01-31/10/c7c5517c63654a95887920e2c7bee4e8.jpg>

左边是 HTTP 方法,中间是 URL 路径,右边是 控制器中对应的函数,只要某个请求符合这七行中某一行的要求,那么这条请求就会触发第三列的 function。这是 Laravel 对于 RESTful 的规范,它不仅仅帮我们省去了几行路由配置代码,更是如何合理规划 URL 的指路明灯,相信你会从中学到很多。

下面我们正式开始一项一项地实现 Article 的新增、编辑、删除功能:

开始行动

配置资源路由

将当前路由配置中的 Route::get('<span style=color: #ff0000>article','ArticleController@index'); 改成 Route::resource('<span style=color: #ff0000>articles','ArticleController');,哦了。注意,article 单数变成了复数。

修改之前写好的视图文件

由于从单数变成了复数,后台首页及文章列表页的视图文件里的链接也需要修改。

  1. 修改 learnlaravel5/resources/views/admin/home.blade.php 中的 {{ url('admin/article') }} 为 {{ url('admin/articles') }}

  2. 修改 learnlaravel5/resources/views/admin/article/index.blade.php 中的 {{ url('admin/<span style=color: #ff0000>article/create') }} 为 {{ url('admin/<span style=color: #ff0000>articles/create') }};修改 {{ url('admin/<span style=color: #ff0000>article/'.$article->id.'/edit') }} 为 {{ url('admin/<span style=color: #ff0000>articles/'.$article->id.'/edit') }};修改 {{ url('admin/<span style=color: #ff0000>article/'.$article->id) }} 为 {{ url('admin/<span style=color: #ff0000>articles/'.$article->id) }}

新增 Article

新增一篇文章需要两个动作:第一步,获取“新增Article”的页面;第二步,提交数据到后端,插入一篇文章到数据库。我们使用下图中红框内的两条路由规则来实现这两步操作:

<a href=https://camo.githubusercontent.com/b746f92a6f4cd2ce8fcaf9192977f6083174a546/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333732363533323231332e6a70673f743d31 rel=noopener noreferrer target=_blank><img src=https://camo.githubusercontent.com/b746f92a6f4cd2ce8fcaf9192977f6083174a546/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333732363533323231332e6a70673f743d31 alt= data-canonical-src=https://www.jb51.cc/res/2019/01-31/10/bc1e49365d4afd2f2a0ac3c59ea095bd.jpg>

获取“新增Article”的页面

第一个红框里告诉我们应该使用 /admin/articles/create 对应“新增Article”的页面,浏览器使用 GET 方法从服务器获取,对应的是 ArticleController 中的 create() 方法,下面我们手动新建这个方法:

<div class=highlight highlight-text-html-php> <div class=cnblogs_code>

<span style=color: #0000ff>public <span style=color: #0000ff>function<span style=color: #000000> create()
{<span style=color: #0000ff>return view('admin/article/create'<span style=color: #000000>);
}

新增视图文件 learnlaravel5/resources/views/admin/article/create.blade.php

<div class=highlight highlight-text-html-php> <div class=cnblogs_code>

@<span style=color: #0000ff>extends('layouts.app'<span style=color: #000000>)

@section('content'<span style=color: #000000>)
<div <span style=color: #0000ff>class=container><div <span style=color: #0000ff>class=row><div <span style=color: #0000ff>class=col-md-10 col-md-offset-1><div <span style=color: #0000ff>class=panel panel-default><div <span style=color: #0000ff>class=panel-heading>新增一篇文章<div <span style=color: #0000ff>class=panel-body><span style=color: #000000>

                    @<span style=color: #0000ff>if (<span style=color: #008080>count(<span style=color: #800080>$errors) > 0<span style=color: #000000>)<div <span style=color: #0000ff>class=alert alert-danger> 输入不符合要求

<span style=color: #000000>
                            {!! <span style=color: #008080>implode('
',<span style=color: #800080>$errors->all()) !!<span style=color: #000000>}<span style=color: #000000>
                    @<span style=color: #0000ff>endif<form action={{ url('admin/articles') }} method=POST><span style=color: #000000>
                        {!! csrf_field() !!<span style=color: #000000>}<input type=text name=title <span style=color: #0000ff>class=form-control required=required placeholder=请输入标题>
<textarea name=body rows=10 <span style=color: #0000ff>class=form-control required=required placeholder=请输入内容>
<button <span style=color: #0000ff>class=btn btn-lg btn-info>新增文章<span style=color: #000000>
@endsection

点击文章管理页面最上面的“新增”按钮,你将得到以下页面:

<a href=https://camo.githubusercontent.com/229fb5764ae1b8b1624fedbf2e33387ce6e4a47f/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333733333039373439382e6a7067 rel=noopener noreferrer target=_blank><img src=https://camo.githubusercontent.com/229fb5764ae1b8b1624fedbf2e33387ce6e4a47f/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333733333039373439382e6a7067 alt= data-canonical-src=https://www.jb51.cc/res/2019/01-31/10/751aa20d1fefec5327962b9adb136f91.jpg>

视图调用

上文中我使用 return view('admin/article/create'); 返回了视图文件。

view() 方法是 Laravel 中一个全局的方法,用于调用视图文件,他接受一个字符串参数,并会按照这个参数去调取对应的路由,这很容易理解。实际上 'admin/article/create' 跟 'admin.article.create' 是等价的,而且看起来后者更加优雅,不过我个人更推荐前者。代码优雅是好事儿,不过本质上代码是写给人看的,一切提高代码理解成本的行为都是不可取的。

提交数据到后端

“新增Article”的页面已经展示出来,下一步就是提交数据到后端了,理解提交数据,要从 HTML 表单开始。

表单

视图文件中有一个表单:

<div class=highlight highlight-text-html-php> <div class=cnblogs_code>

<form action={{ url('admin/articles') }} method=POST><span style=color: #000000>
    {!! csrf_field() !!<span style=color: #000000>}<input type=text name=title <span style=color: #0000ff>class=form-control required=required placeholder=请输入标题>
<textarea name=body rows=10 <span style=color: #0000ff>class=form-control required=required placeholder=请输入内容>
<button <span style=color: #0000ff>class=btn btn-lg btn-info>新增文章

这是一个非常普通的 HTML form(表单),只有两点需要我们费点心思去理解。

第一,表单的 action。form 是 HTML 规范,在点击了表单中的提交按钮后,浏览器会使用 method 属性的值(GET、POST等)将某些数据组装好发送给 action 的值(URL),这里我们动态生成了一个 URL 作为 action,并且指定了表单提交需要使用 POST 方法。

第二,csrf_field。这是 Laravel 中内置的应对 CSRF 攻击的防范措施,任何 POST PUT PATCH 请求都会被检测是否提交了 CSRF 字段。对应的代码为 learnlaravel5/app/Http/Kernel.php 里的 $middlewareGroups 属性里的 \App\Http\Middleware\VerifyCsrfToken::class 值。

<span style=color: #ff0000>{!! csrf_field() !!} 实际上会生成一个隐藏的 input:<input type=hidden name=_token value=GYZ8OHDAbZICMcEvcTiS82qlZs2XrELklpEl159S>

这一行也可以这么写:

<div class=highlight highlight-text-html-php> <div class=cnblogs_code>

<span style=color: #ff0000><input type=hidden name=_token value={{ csrf_token() }}>

如果你的系统有很多的 Ajax,而你又不想降低安全性,这里的 csrf_token() 函数将会给你巨大的帮助。

后端接收数据

我们在页面中随便填入一些数据,点击提交按钮,这条请求会被分配到那里呢?

<a href=https://camo.githubusercontent.com/b746f92a6f4cd2ce8fcaf9192977f6083174a546/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333732363533323231332e6a70673f743d31 rel=noopener noreferrer target=_blank><img src=https://camo.githubusercontent.com/b746f92a6f4cd2ce8fcaf9192977f6083174a546/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333732363533323231332e6a70673f743d31 alt= data-canonical-src=https://www.jb51.cc/res/2019/01-31/10/bc1e49365d4afd2f2a0ac3c59ea095bd.jpg>

第二个红框告诉我们,应该向 admin/articles 以 POST 方法提交表单,其对应的是 store() 方法。现在我们新建 store 方法:

<div class=highlight highlight-text-html-php> <div class=cnblogs_code>

<span style=color: #0000ff>public <span style=color: #0000ff>function store(Request <span style=color: #800080>$request<span style=color: #000000>)
{<span style=color: #800080>$this->validate(<span style=color: #800080>$request,<span style=color: #000000> ['title' => 'required|unique:articles|max:255','body' => 'required',<span style=color: #000000>
    ]);<span style=color: #800080>$article = <span style=color: #0000ff>new<span style=color: #000000> Article;<span style=color: #800080>$article->title = <span style=color: #800080>$request->get('title'<span style=color: #000000>);<span style=color: #800080>$article->body = <span style=color: #800080>$request->get('body'<span style=color: #000000>);<span style=color: #800080>$article->user_id = <span style=color: #800080>$request->user()-><span style=color: #000000>id;<span style=color: #0000ff>if (<span style=color: #800080>$article-><span style=color: #000000>save()) {<span style=color: #0000ff>return redirect('admin/articles'<span style=color: #000000>);
    } <span style=color: #0000ff>else<span style=color: #000000> {<span style=color: #0000ff>return redirect()->back()->withInput()->withErrors('保存失败!'<span style=color: #000000>);
    }
}

检验成果

填入数据:

<a href=https://camo.githubusercontent.com/5cd99baa6d0af58babecacace279415c3e7a98a7/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333734313339313135382e6a70673f743d31 rel=noopener noreferrer target=_blank><img src=https://camo.githubusercontent.com/5cd99baa6d0af58babecacace279415c3e7a98a7/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333734313339313135382e6a70673f743d31 alt= data-canonical-src=https://www.jb51.cc/res/2019/01-31/10/64bb1fb13299e3b881d9bc6a8b8aa2a8.jpg>

点击按钮,页面跳转到“文章管理”页,将此页面拉到最底部:

<a href=https://camo.githubusercontent.com/6dd2504b32c42dd882489cc4abd9a23ab98f7039/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333734333037353036392e6a7067 rel=noopener noreferrer target=_blank><img src=https://camo.githubusercontent.com/6dd2504b32c42dd882489cc4abd9a23ab98f7039/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333734333037353036392e6a7067 alt= data-canonical-src=https://www.jb51.cc/res/2019/01-31/10/a8c918ac592baa9905d077fd8dbfe3d4.jpg>

恭喜你,文章新增功能完成!

详细注释

下面我已注释的形式细细解析每一段代码的作用:

<div class=highlight highlight-text-html-php> <div class=cnblogs_code>

<span style=color: #0000ff>public <span style=color: #0000ff>function store(Request <span style=color: #800080>$request) <span style=color: #008000>//<span style=color: #008000> Laravel 的依赖注入系统会自动初始化我们需要的 Request 类<span style=color: #000000>{<span style=color: #008000>//<span style=color: #008000> 数据验证<span style=color: #800080>$this->validate(<span style=color: #800080>$request,<span style=color: #008000>//<span style=color: #008000> 必填、在 articles 表中唯一、最大长度 255'body' => 'required',<span style=color: #008000>//<span style=color: #008000> 必填<span style=color: #000000>    ]);<span style=color: #008000>//<span style=color: #008000> 通过 Article Model 插入一条数据进 articles 表<span style=color: #800080>$article = <span style=color: #0000ff>new Article; <span style=color: #008000>//<span style=color: #008000> 初始化 Article 对象<span style=color: #800080>$article->title = <span style=color: #800080>$request->get('title'); <span style=color: #008000>//<span style=color: #008000> 将 POST 提交过了的 title 字段的值赋给 article 的 title 属性<span style=color: #800080>$article->body = <span style=color: #800080>$request->get('body'); <span style=color: #008000>//<span style=color: #008000> 同上<span style=color: #800080>$article->user_id = <span style=color: #800080>$request->user()->id; <span style=color: #008000>//<span style=color: #008000> 获取当前 Auth 系统中注册的用户,并将其 id 赋给 article 的 user_id 属性

    // 将数据保存到数据库,通过判断保存结果,控制页面进行不同跳转<span style=color: #0000ff>if (<span style=color: #800080>$article-><span style=color: #000000>save()) {<span style=color: #0000ff>return redirect('admin/articles'); <span style=color: #008000>//<span style=color: #008000> 保存成功,跳转到 文章管理 页} <span style=color: #0000ff>else<span style=color: #000000> {<span style=color: #008000>//<span style=color: #008000> 保存失败,跳回来路页面,保留用户的输入,并给出提示<span style=color: #0000ff>return redirect()->back()->withInput()->withErrors('保存失败!'<span style=color: #000000>);
    }
}

编辑 Article

这两行路由配置可以满足我们的需求:

<a href=https://camo.githubusercontent.com/bb3287fe21c74aae3f8fe8a0e0f2080ea0ca268b/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333830363539313030362e6a70673f743d31 rel=noopener noreferrer target=_blank><img src=https://camo.githubusercontent.com/bb3287fe21c74aae3f8fe8a0e0f2080ea0ca268b/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333830363539313030362e6a70673f743d31 alt= data-canonical-src=https://www.jb51.cc/res/2019/01-31/10/afbaee8e655af88c58a3fe3bf01b99e1.jpg>

上面一行:展示“编辑某一篇文章”的表单;下面一行:上传数据并到数据库更新这篇文章。

这个就当做第二个小作业留给你们,尝试自己去构建吧<span style=text-decoration: line-through>这里面还有个小坑,参考我的代码就可以迅速地解决呦

删除 Article

删除某个资源跟新增、编辑相比最大的不同就是运行方式的不同:删除按钮看起来是一个独立的按钮,其实它是一个完整的表单,只不过只有这一个按钮暴露在页面上:

<div class=highlight highlight-text-html-php> <div class=cnblogs_code>

<form action={{ url('admin/articles/'.<span style=color: #800080>$article->id) }} method=POST style=display: inline;><span style=color: #000000>
    {{ method_field('DELETE'<span style=color: #000000>) }}
    {{ csrf_field() }}<button type=submit <span style=color: #0000ff>class=btn btn-danger>删除

大家可能注意到了这句代码 {{ method_field('DELETE') }},这是什么意思呢?这是 Laravel 特有的请求处理系统的特殊约定。虽然 DELETE 方法在 <a href=http://www.ietf.org/rfc/rfc2616.txt rel=nofollow>RFC2616 中是可以携带 body 的(甚至 GET 方法都是可以携带的),但是由于历史的原因,不少 web server 软件都将 DELETE 方法和 GET 方法视作不可携带 body 的方法,有些 web server 软件会丢弃 body,有些干脆直接认为请求不合法拒绝接收。所以在这里,Laravel 的请求处理系统要求所有非 GET 和 POST 的请求全部通过 POST 请求来执行,再将真正的方法使用 _method 表单字段携带给后端。上面小作业中的小坑便是这个,PUT/PATCH 请求也要通过 POST 来执行。

在控制器中增加删除文章对应的是 destroy 方法:

<div class=highlight highlight-text-html-php> <div class=cnblogs_code>

<span style=color: #0000ff>public <span style=color: #0000ff>function destroy(<span style=color: #800080>$id<span style=color: #000000>)
{
    Article::find(<span style=color: #800080>$id)-><span style=color: #000000>delete();<span style=color: #0000ff>return redirect()->back()->withInput()->withErrors('删除成功!'<span style=color: #000000>);
}

点击删除按钮,检验效果:

<a href=https://camo.githubusercontent.com/95024dbf84cabfbc35ac176df731b58bdd8c4db7/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333832323639363336332e6a7067 rel=noopener noreferrer target=_blank><img src=https://camo.githubusercontent.com/95024dbf84cabfbc35ac176df731b58bdd8c4db7/687474703a2f2f716e2e6c7677656e68616e2e636f6d2f323031372d31312d31312d31353130333832323639363336332e6a7067 alt= data-canonical-src=https://www.jb51.cc/res/2019/01-31/10/f45ae7b3b7659fedc79985dea8be7a16.jpg>

恭喜你,文章新增、编辑、删除功能构建成功!

<p style=text-align: right><span style=font-size: 12px>转载他处,侵权联系删除

相关文章

laravel的dd函数不生效怎么办
看不懂laravel文档咋办
安装laravel框架出现command怎么办
Laravel开发API怎么使用事务
laravel怎么构建复杂查询条件
laravel如何实现防止被下载