本教程示例代码见: https://github.com/johnlui/Learn-Laravel-5

在任何地方卡住,最快的办法就是去看示例代码。

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

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

回顾 Eloquent

前面我们已经说过,Laravel Eloquent ORM 是 Laravel 中最强大的部分,也是 Laravel 能如此流行最重要的原因。中文文档在: http://laravel-china.org/docs/5.1/eloquent

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

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
//
}

若想进一步了解 Eloquent,推荐阅读系列文章: 深入理解 Laravel Eloquent

开始构建评论系统

基础规划

我们需要新建一个表专门用来存放数据库,每条评论都属于某一篇文章。评论之间的层级关系比较复杂,本文为入门教程,主要是为了带领大家体验模型间关系,就不在做过多的规划,将“回复别人的评论”暂定为简单的在评论内容前面增加@john 这样的字符串。

建立 Model 类和数据表

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

php artisan make:model Comment -m

这样一次性建立了 Comment 类和 2016_06_03_220325_create_comments_table 两个文件。修改 migration 文件的 up 方法为:

public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->increments('id');
$table->string('nickname');
$table->string('email')->nullable();
$table->string('website')->nullable();
$table->text('content')->nullable();
$table->integer('article_id');
$table->timestamps();
});
}

之后运行命令:

php artisan migrate

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

建立“一对多关系”

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

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
public function hasManyComments()
{
return $this->hasMany('App\Comment', 'article_id', 'id');
}
}

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

构建前台 UI

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

创建前台的 ArticleController 类

运行命令:

php artisan make:controller ArticleController

增加路由:

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

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

给 ArticleController 增加 show 函数:

public function show($id)
{
return view('article/show')->withArticle(Article::with('hasManyComments')->find($id));
}

创建前台文章展示视图

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

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <title>Learn Laravel 5</title> <link href="//cdn.bootcss.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<script src="//cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
<script src="//cdn.bootcss.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
</head> <div id="content" style="padding: 50px;"> <h4>
<a href="/"><< 返回首页</a>
</h4> <h1 style="text-align: center; margin-top: 50px;">{{ $article->title }}</h1>
<hr>
<div id="date" style="text-align: right;">
{{ $article->updated_at }}
</div>
<div id="content" style="margin: 20px;">
<p>
{{ $article->body }}
</p>
</div> <div id="comments" style="margin-top: 50px;"> @if (count($errors) > 0)
<div class="alert alert-danger">
<strong>操作失败</strong> 输入不符合要求<br><br>
{!! implode('<br>', $errors->all()) !!}
</div>
@endif <div id="new">
<form action="{{ url('comment') }}" method="POST">
{!! csrf_field() !!}
<input type="hidden" name="article_id" value="{{ $article->id }}">
<div class="form-group">
<label>Nickname</label>
<input type="text" name="nickname" class="form-control" style="width: 300px;" required="required">
</div>
<div class="form-group">
<label>Email address</label>
<input type="email" name="email" class="form-control" style="width: 300px;">
</div>
<div class="form-group">
<label>Home page</label>
<input type="text" name="website" class="form-control" style="width: 300px;">
</div>
<div class="form-group">
<label>Content</label>
<textarea name="content" id="newFormContent" class="form-control" rows="10" required="required"></textarea>
</div>
<button type="submit" class="btn btn-lg btn-success col-lg-12">Submit</button>
</form>
</div> <script>
function reply(a) {
var nickname = a.parentNode.parentNode.firstChild.nextSibling.getAttribute('data');
var textArea = document.getElementById('newFormContent');
textArea.innerHTML = '@'+nickname+' ';
}
</script> <div class="conmments" style="margin-top: 100px;">
@foreach ($article->hasManyComments as $comment) <div class="one" style="border-top: solid 20px #efefef; padding: 5px 20px;">
<div class="nickname" data="{{ $comment->nickname }}">
@if ($comment->website)
<a href="{{ $comment->website }}">
<h3>{{ $comment->nickname }}</h3>
</a>
@else
<h3>{{ $comment->nickname }}</h3>
@endif
<h6>{{ $comment->created_at }}</h6>
</div>
<div class="content">
<p style="padding: 20px;">
{{ $comment->content }}
</p>
</div>
<div class="reply" style="text-align: right; padding: 5px;">
<a href="#new" onclick="reply(this);">回复</a>
</div>
</div> @endforeach
</div>
</div> </div> </body>
</html>

构建评论存储功能

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

php artisan make:controller CommentController

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

Route::post('comment', 'CommentController@store');

给这个类增加 store 函数:

public function store(Request $request)
{
if (Comment::create($request->all())) {
return redirect()->back();
} else {
return redirect()->back()->withInput()->withErrors('评论发表失败!');
}
}

批量赋值

我们采用批量赋值方法来减少存储评论的代码, 批量赋值中文文档 。

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

protected $fillable = ['nickname', 'email', 'website', 'content', 'page_id'];

检查成果

前台文章展示页:

提交几条评论之后:

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

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

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

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

2016 版 Laravel 系列入门教程(五)【最适合中国人的 Laravel 教程】的更多相关文章

  1. 2016 版 Laravel 系列入门教程

    2016 版 Laravel 系列入门教程 (1) - (5) http://www.golaravel.com/post/2016-ban-laravel-xi-lie-ru-men-jiao-ch ...

  2. Laravel 5 系列入门教程(一)【最适合中国人的 Laravel 教程】

    Laravel 5 系列入门教程(一)[最适合中国人的 Laravel 教程] 分享⋅ johnlui⋅ 于 2年前 ⋅ 最后回复由 skys215于 11个月前 ⋅ 17543 阅读   原文发表在 ...

  3. Laravel 系列入门教程(三)【最适合中国人的 Laravel 教程】

    在本篇文章中,我们将尝试构建一个带后台的简单博客系统.我们将会使用到 路由.MVC.Eloquent ORM 和 blade 视图系统. 简单博客系统规划 我们在教程一中已经新建了一个继承自 Eloq ...

  4. 2016 版 Laravel 系列入门教程(三)【最适合中国人的 Laravel 教程】

    本教程示例代码见: https://github.com/johnlui/Learn-Laravel-5 在任何地方卡住,最快的办法就是去看示例代码. 在本篇文章中,我们将尝试构建一个带后台的简单博客 ...

  5. 2016 版 Laravel 系列入门教程(一)【最适合中国人的 Laravel 教程】

    本教程示例代码见: https://github.com/johnlui/Learn-Laravel-5 在任何地方卡住,最快的办法就是去看示例代码. 本文基于 Laravel 5.2 版本,无奈 5 ...

  6. 2016 版 Laravel 系列入门教程(四)【最适合中国人的 Laravel 教程】

    本教程示例代码见: https://github.com/johnlui/Learn-Laravel-5 在任何地方卡住,最快的办法就是去看示例代码. 本篇文章中,我将跟大家一起实现 Article ...

  7. 2016 版 Laravel 系列入门教程(二)【最适合中国人的 Laravel 教程】

    本教程示例代码见: https://github.com/johnlui/Learn-Laravel-5 在任何地方卡住,最快的办法就是去看示例代码. 本篇文章中,我将跟宝宝们一起学习 Laravel ...

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

    本文是本系列教程的完结篇,我们将一起给 Article 加入评论功能,让游客在前台页面可以查看.提交.回复评论,并完成后台评论管理功能,可以删除.编辑评论.Article 和评论将使用 Laravel ...

  9. Laravel 系列入门教程(二)【最适合中国人的 Laravel 教程】

    本篇文章中,我将跟大家一起体验 Laravel 框架最重要的部分——路由系统. 如果你读过 2015 版的教程,你会发现那篇文章里大书特书的 Auth 系统构建已经被 Laravel 捎带手给解决了. ...

随机推荐

  1. openfire+asmack搭建的安卓即时通讯(四) 15.4.10

    之前的教程不知道你们成功了没,,,没成功可以问我啊=-= 第四篇博文是要实现发送消息的功能. 首先在我们登陆后的活动的layout里添加这样的两个控件,一个EditText和一个Button用于发送数 ...

  2. matlab生成HEX文件-任意信号 大于64K长度

    HEX文件格式不赘述,写里直接放上代码.请批评改正. %%convert a signal data into hex file format % data format:16bit % signal ...

  3. jquery和css自定义video播放控件

    下面介绍一下通过jquery和css自定义video播放控件. Html5 Video是现在html5最流行的功能之一,得到了大多数最新版本的浏览器支持.包括IE9,也是如此.不同的浏览器提供了不同的 ...

  4. Codeforces Round #FF/#255 D DZY Loves Modification --贪心+优先队列

    题意:给你一个矩阵,每次选某一行或者某一列,得到的价值为那一行或列的和,然后该行每个元素减去p.问连续取k次能得到的最大总价值为多少. 解法: 如果p=0,即永远不减数,那么最优肯定是取每行或每列那个 ...

  5. Android代码优化----Application节点的模板写法及UI工具类

    一. MyApplication类的编写: 新建一个类MyApplication,继承自Application.代码如下: MyApplication.java: package com.smyhva ...

  6. 利用OpacityMask制作打洞效果

    起因 项目上存在一个连线功能,在设计的原型中,在连线中间文字上下各有15像素的空白.接手的同事觉得没思路,问我能不能在不影响连线后面的背景情况下解决该问题.我就抽了点时间给他写了个Demo.回家后趁热 ...

  7. HTTP请求与响应方式

    HTTP请求格式 当浏览器向Web服务器发出请求时,它向服务器传递了一个数据块,也就是请求信息,HTTP请求信息由3部分组成: l   请求方法URI协议/版本 l   请求头(Request Hea ...

  8. 阻塞与非阻塞IO step by step

    谈到IO,阻塞.非阻塞,异步.同步是绕不开的话题.说实话,我也没搞清楚,网上查了许多资料,大家众说纷纭,一种比较靠谱的说法是:”在处理 IO 的时候,阻塞和非阻塞都是同步 IO,使用使用了特殊的API ...

  9. [Erlang37]error/1 exit/1 exit/2 throw/1的区别

    1. error/1 主要是系统用来定义内部错误的: Erlang内建的run time error 一共有10种: function_clause/case_clause/if_clause/bad ...

  10. vim常用命令汇总

    vim常用命令汇总: http://www.cnblogs.com/softwaretesting/archive/2011/07/12/2104435.html 定位 本行第一个字符 ctrl+$ ...