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

本文是本系列教程的完结篇,我们将一起给 Article 加入评论功能,让游客在前台页面可以查看、提交、回复评论,并完成后台评论管理功能,可以删除、编辑评论。Article 和评论将使用 Laravel Eloquent 提供的“一对多关系”功能大大简化模型间关系的复杂度。最终,我们将得到一个个人博客系统的雏形,并布置一个大作业,供大家实战练习。

本篇文章中我将会使用一些 Laravel 的高级功能,这些高级功能对新手理解系统是不利的,但熟手使用这些功能可以大幅提升开发效率。

回顾 Eloquent

前面我们已经说过,Laravel Eloquent ORM 是 Laravel 中最强大的部分,也是 Laravel 能如此流行最重要的原因。中文文档在:<a href=https://d.laravel-china.org/docs/5.5/eloquent rel=nofollow>https://d.laravel-china.org/docs/5.5/eloquent

learnlaravel5/app/Article.php 就是一个最简单的 Eloquent Model 类:

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

<?<span style=color: #000000>php

namespace App;

<span style=color: #0000ff>use<span style=color: #000000> Illuminate\Database\Eloquent\Model;

<span style=color: #0000ff>class Article <span style=color: #0000ff>extends<span style=color: #000000> Model
{<span style=color: #008000>//
}

若想进一步了解 Eloquent 推荐阅读系列文章:<a href=https://lvwenhan.com/laravel/421.html rel=nofollow>深入理解 Laravel Eloquent

构建评论系统

基础规划

我们需要新建一个表专门用来存放每一条评论,每一条评论都属于某一篇文章。评论之间的层级关系比较复杂,本文为入门教程,主要是为了带领大家体验模型间关系,就不再做过多的规划了,将“回复别人的评论”暂定为简单的在评论内容前面增加 <a class=user-mention href=https://github.com/johnlui data-hovercard-type=user data-hovercard-url=/hovercards?user_id=2127912 data-octo-click=hovercard-link-click data-octo-dimensions=link_type:self>@johnlui 这样的字符串。

建立 Model 类和数据表

创建名为 Comment 的 Model 类,并顺便创建附带的 migration,在 learnlaravel5 目录下运行命令:

<div class=highlight highlight-source-shell> <div class=cnblogs_code>

php artisan make:model Comment -m

这样一次性建立了 Comment 类和 learnlaravel5/database/migrations/2017_11_11_151823_create_comments_table.php 两个文件。填充该文件的 up 方法,给 comments 表增加字段:

<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> up()
{
    Schema::create('comments',<span style=color: #0000ff>function (Blueprint <span style=color: #800080>$table<span style=color: #000000>) {<span style=color: #800080>$table->increments('id'<span style=color: #000000>);<span style=color: #800080>$table-><span style=color: #0000ff>string('nickname'<span style=color: #000000>);<span style=color: #800080>$table-><span style=color: #0000ff>string('email')-><span style=color: #000000>nullable();<span style=color: #800080>$table-><span style=color: #0000ff>string('website')-><span style=color: #000000>nullable();<span style=color: #800080>$table->text('content')-><span style=color: #000000>nullable();<span style=color: #800080>$table-><span style=color: #0000ff>integer('article_id'<span style=color: #000000>);<span style=color: #800080>$table-><span style=color: #000000>timestamps();
    });
}

之后运行命令:

<div class=highlight highlight-source-shell> <div class=cnblogs_code>

php artisan migrate

去数据库里瞧瞧,comments 表已经躺在那儿啦。

建立“一对多关系”

在 Article 模型中增加一对多关系的函数:

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

<?<span style=color: #000000>php

namespace App;

<span style=color: #0000ff>use<span style=color: #000000> Illuminate\Database\Eloquent\Model;

<span style=color: #0000ff>class Article <span style=color: #0000ff>extends<span style=color: #000000> Model
{<span style=color: #0000ff>public <span style=color: #0000ff>function<span style=color: #000000> hasManyComments()
    {<span style=color: #0000ff>return <span style=color: #800080>$this->hasMany('App\Comment','article_id','id'<span style=color: #000000>);
    }
}

搞定啦!Eloquent 中模型间关系就是这么简单!

模型间关系中文文档:<a href=http://laravel-china.org/docs/5.1/eloquent-relationships rel=nofollow>http://laravel-china.org/docs/5.1/eloquent-relationships扩展阅读:<a href=https://lvwenhan.com/laravel/423.html rel=nofollow>深入理解 Laravel Eloquent(三)——模型间关系(关联)

构建前台 UI

让我们修改前台的视图文件,想办法把评论功能加进去。

创建前台的 ArticleController 类

运行命令:

<div class=highlight highlight-source-shell> <div class=cnblogs_code>

php artisan make:controller ArticleController

增加路由:

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

Route::get('article/{id}','ArticleController@show');

此处的 {id} 指代任意字符串,在我们的规划中,此字段为文章 ID,为数字,但是本行路由却会尝试匹配所有请求,所以当你遇到了奇怪的路由调用的方法跟你想象的不一样时,记得检查路由顺序。路由匹配方式为前置匹配:任何一条路由规则匹配成功,会立刻返回结果,后面的路由便没有了响应的机会。

给 ArticleController 增加 show 函数:

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

<span style=color: #0000ff>public <span style=color: #0000ff>function show(<span style=color: #800080>$id<span style=color: #000000>)
{<span style=color: #0000ff>return view('article/show')->withArticle(Article::with('hasManyComments')->find(<span style=color: #800080>$id<span style=color: #000000>));
}

别忘了在顶部引入 Model 类,否则会报类找不到的错误:

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

....<span style=color: #0000ff>use<span style=color: #000000> App\Article;

<span style=color: #0000ff>class ArticleController <span style=color: #0000ff>extends<span style=color: #000000> Controller
{
....

创建前台文章展示视图

新建 learnlaravel5/resources/views/article/show.blade.php 文件:

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

<html lang=en>
<meta charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=edge><meta name=viewport content=width=device-width,initial-scale=1><link href=//cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css rel=stylesheet><script src=//cdn.bootcss.com/jquery/2.2.4/jquery.min.js><script src=//cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js><div id=content style=padding: 50px;><h1 style=text-align: center; margin-top: 50px;>{{ <span style=color: #800080>$article->title }}[object Object]<div id=date style=text-align: right;><span style=color: #000000>
            {{ <span style=color: #800080>$article-><span style=color: #000000>updated_at }}<div id=content style=margin: 20px;><div id=comments style=margin-top: 50px;><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<div id=new><form action={{ url('comment') }} method=POST><span style=color: #000000>
                    {!! csrf_field() !!<span style=color: #000000>}<input type=hidden name=article_id value={{ <span style=color: #800080>$article->id }}><div <span style=color: #0000ff>class=form-group><input type=text name=nickname <span style=color: #0000ff>class=form-control style=width: 300px; required=required><div <span style=color: #0000ff>class=form-group><input type=email name=email <span style=color: #0000ff>class=form-control style=width: 300px;><div <span style=color: #0000ff>class=form-group><input type=text name=website <span style=color: #0000ff>class=form-control style=width: 300px;><div <span style=color: #0000ff>class=form-group><textarea name=content id=newFormContent <span style=color: #0000ff>class=form-control rows=10 required=required><button type=submit <span style=color: #0000ff>class=btn btn-lg btn-success col-lg-12>Submit<div <span style=color: #0000ff>class=conmments style=margin-top: 100px;><span style=color: #000000>
@<span style=color: #0000ff>foreach (<span style=color: #800080>$article->hasManyComments <span style=color: #0000ff>as <span style=color: #800080>$comment<span style=color: #000000>)
<div <span style=color: #0000ff>class=one style=border-top: solid 20px #efefef; padding: 5px 20px;><div <span style=color: #0000ff>class=nickname data={{ <span style=color: #800080>$comment->nickname }}><span style=color: #000000>
@<span style=color: #0000ff>if (<span style=color: #800080>$comment-><span style=color: #000000>website)
<a href={{ <span style=color: #800080>$comment->website }}><span style=color: #000000>
@<span style=color: #0000ff>else<span style=color: #000000>
@<span style=color: #0000ff>endif<div <span style=color: #0000ff>class=content><p style=padding: 20px;><span style=color: #000000>
                                {{ <span style=color: #800080>$comment-><span style=color: #000000>content }}
<div <span style=color: #0000ff>class=reply style=text-align: right; padding: 5px;><a href=#new onclick=reply(this);>回复<span style=color: #000000>
@<span style=color: #0000ff>endforeach

构建评论存储功能

我们需要创建一个 CommentsController 控制器,并增加一条“存储评论”的路由。运行命令:

<div class=highlight highlight-source-shell> <div class=cnblogs_code>

php artisan make:controller CommentController

控制器创建成功,接下来我们增加一条路由:

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

Route::post('comment','CommentController@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: #0000ff>if (Comment::create(<span style=color: #800080>$request-><span style=color: #000000>all())) {<span style=color: #0000ff>return redirect()-><span style=color: #000000>back();
    } <span style=color: #0000ff>else<span style=color: #000000> {<span style=color: #0000ff>return redirect()->back()->withInput()->withErrors('评论发表失败!'<span style=color: #000000>);
    }
}

此处 Comment 类请自己引入。

批量赋值

我们采用批量赋值方法来减少存储评论的代码,<a href=https://d.laravel-china.org/docs/5.5/eloquent#mass-assignment rel=nofollow>批量赋值中文文档。

给 Comment 类增加 $fillable 成员变量:

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

<span style=color: #0000ff>protected <span style=color: #800080>$fillable = ['nickname','email','website','content','article_id'];

检查成果

前台文章展示页:

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

提交几条评论之后:

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

恭喜你,前台评论功能构建完成!

【大作业】构建后台评论管理功能

评论跟 Article 一样,是一种可以管理的资源列表。2015 版教程的最后,我风风火火地罗列了一堆又一堆的代码,其实对还没入门的人几乎没用。在此,我将这个功能作为大作业布置给大家。大作业嘛,当然是没有标准答案的,但有效果图:

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

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

在做这个大作业的过程中,你将会反复地回头去看前面的教程,反复地阅读中文文档,会仔细阅读我的代码,等你完成大作业的时候,Laravel 就真正入门啦~~

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

相关文章

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