Page 和评论将使用 Eloquent 提供的“一对多关系”。最终,我们将得到一个个人博客系统的雏形,并布置一个大作业,供大家实战练习。
1. 初识 Eloquent
Laravel Eloquent ORM 是 Laravel 中非常重要的部分,也是 Laravel 能如此流行的原因之一。中文文档在:
1. http://laravel-china.org/docs/5.0/eloquent
2. http://www.golaravel.com/laravel/docs/5.0/eloquent/
在前面的教程中已经建立好的 learnlaravel5/app/Page.php 就是一个 Eloquent Model 类:
1
2
3
4
5
6
7
8
9
|
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Page extends Model {
//
}
|
若想进一步了解 Eloquent,推荐阅读系列文章:深入理解 Laravel Eloquent
2. 创建 Comment 模型
首先我们要新建一张表来存储 Comment,命令行运行:
php artisan make:model Comment
成功以后,修改 migration 文件 learnlaravel5/database/migrations/***_create_comments_table.php 的相应位置为:
1
2
3
4
5
6
7
8
9
10
|
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( 'page_id' );
$table ->timestamps();
});
|
之后运行:
php artisan migrate
去数据库里瞧瞧,comments 表已经躺在那儿啦。
3. 建立“一对多关系”
修改 Page 模型:
1
2
3
4
5
6
7
8
9
10
11
12
|
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Page extends Model {
public function hasManyComments()
{
return $this ->hasMany( 'App\Comment' , 'page_id' , 'id' );
}
}
|
搞定啦~ Eloquent 中模型间关系就是这么简单。
模型间关系中文文档:http://laravel-china.org/docs/5.0/eloquent#relationships
4. 前台提交功能
修改 Comment 模型:
1
2
3
4
5
6
7
8
9
|
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model {
protected $fillable = [ 'nickname' , 'email' , 'website' , 'content' , 'page_id' ];
}
|
增加一行路由:
Route::post('comment/store', 'CommentsController@store');
运行以下命令创建 CommentsController 控制器:
php artisan make:controller CommentsController
修改 CommentsController:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<?php namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Redirect, Input;
use App\Comment;
class CommentsController extends Controller {
public function store()
{
if (Comment::create(Input::all())) {
return Redirect::back();
} else {
return Redirect::back()->withInput()->withErrors( '评论发表失败!' );
}
}
}
|
修改视图 learnlaravel5/resources/views/pages/show.blade.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
@ extends ( '_layouts.default' )
@section( 'content' )
<h4>
<a href= "/" >⬅️返回首页</a>
</h4>
<h1 style= "text-align: center; margin-top: 50px;" >{{ $page ->title }}</h1>
<hr>
<div id= "date" style= "text-align: right;" >
{{ $page ->updated_at }}
</div>
<div id= "content" style= "padding: 50px;" >
<p>
{{ $page ->body }}
</p>
</div>
<div id= "comments" style= "margin-bottom: 100px;" >
@ if ( count ( $errors ) > 0)
<div class = "alert alert-danger" >
<strong>Whoops!</strong> There were some problems with your input.<br><br>
<ul>
@ foreach ( $errors ->all() as $error )
<li>{{ $error }}</li>
@ endforeach
</ul>
</div>
@ endif
<div id= "new" >
<form action= "{{ URL('comment/store') }}" method= "POST" >
<input type= "hidden" name= "_token" value= "{{ csrf_token() }}" >
<input type= "hidden" name= "page_id" value= "{{ $page->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 ( $page ->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>
@endsection
|
前台评论功能完成。
查看效果:
5. 后台管理功能
修改基础视图 learnlaravel5/resources/views/app.blade.php 为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
<!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>Laravel</title>
<link href= "/css/app.css" rel= "stylesheet" >
<!-- Fonts -->
<link href= 'http://fonts.useso.com/css?family=Roboto:400,300' rel= 'stylesheet' type= 'text/css' >
</head>
<body>
<nav class = "navbar navbar-default" >
<div class = "container-fluid" >
<div class = "navbar-header" >
<button type= "button" class = "navbar-toggle collapsed" data-toggle= "collapse" data-target= "#bs-example-navbar-collapse-1" >
<span class = "sr-only" >Toggle Navigation</span>
<span class = "icon-bar" ></span>
<span class = "icon-bar" ></span>
<span class = "icon-bar" ></span>
</button>
<a class = "navbar-brand" href= "#" >Learn Laravel 5</a>
</div>
<div class = "collapse navbar-collapse" id= "bs-example-navbar-collapse-1" >
<ul class = "nav navbar-nav" >
<li><a href= "/admin" >后台首页</a></li>
</ul>
<ul class = "nav navbar-nav" >
<li><a href= "/admin/comments" >管理评论</a></li>
</ul>
<ul class = "nav navbar-nav navbar-right" >
@ if (Auth::guest())
<li><a href= "/auth/login" >Login</a></li>
<li><a href= "/auth/register" >Register</a></li>
@ else
<li class = "dropdown" >
<a href= "#" class = "dropdown-toggle" data-toggle= "dropdown" role= "button" aria-expanded= "false" >{{ Auth::user()->name }} <span class = "caret" ></span></a>
<ul class = "dropdown-menu" role= "menu" >
<li><a href= "/auth/logout" >Logout</a></li>
</ul>
</li>
@ endif
</ul>
</div>
</div>
</nav>
@yield( 'content' )
<!-- Scripts -->
<script src= "//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js" ></script>
<script src= "//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/js/bootstrap.min.js" ></script>
</body>
</html>
|
修改后台路由组(增加了一行):
1
2
3
4
5
6
|
Route::group([ 'prefix' => 'admin' , 'namespace' => 'Admin' , 'middleware' => 'auth' ], function ()
{
Route::get( '/' , 'AdminHomeComtroller@index' );
Route::resource( 'pages' , 'PagesController' );
Route::resource( 'comments' , 'CommentsController' );
});
|
创建 Admin\CommentsController :
php artisan make:controller Admin/CommentsController
Admin/CommentsController 要有 查看所有、查看单个、POST更改、删除四个接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
<?php namespace App\Http\Controllers\Admin;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Comment;
use Redirect, Input;
class CommentsController extends Controller {
public function index()
{
return view( 'admin.comments.index' )->withComments(Comment::all());
}
public function edit( $id )
{
return view( 'admin.comments.edit' )->withComment(Comment::find( $id ));
}
public function update(Request $request , $id )
{
$this ->validate( $request , [
'nickname' => 'required' ,
'content' => 'required' ,
]);
if (Comment::where( 'id' , $id )->update(Input::except([ '_method' , '_token' ]))) {
return Redirect::to( 'admin/comments' );
} else {
return Redirect::back()->withInput()->withErrors( '更新失败!' );
}
}
public function destroy( $id )
{
$comment = Comment::find( $id );
$comment -> delete ();
return Redirect::to( 'admin/comments' );
}
}
|
接下来创建两个视图:
learnlaravel5/resources/views/admin/comments/index.blade.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
@ extends ( 'app' )
@section( 'content' )
<div class = "container" >
<div class = "row" >
<div class = "col-md-10 col-md-offset-1" >
<div class = "panel panel-default" >
<div class = "panel-heading" >管理评论</div>
<div class = "panel-body" >
<table class = "table table-striped" >
<tr class = "row" >
<th class = "col-lg-4" >Content</th>
<th class = "col-lg-2" >User</th>
<th class = "col-lg-4" >Page</th>
<th class = "col-lg-1" >编辑</th>
<th class = "col-lg-1" >删除</th>
</tr>
@ foreach ( $comments as $comment )
<tr class = "row" >
<td class = "col-lg-6" >
{{ $comment ->content }}
</td>
<td class = "col-lg-2" >
@ if ( $comment ->website)
<a href= "{{ $comment->website }}" >
<h4>{{ $comment ->nickname }}</h4>
</a>
@ else
<h3>{{ $comment ->nickname }}</h3>
@ endif
{{ $comment ->email }}
</td>
<td class = "col-lg-4" >
<a href= "{{ URL('pages/'.$comment->page_id) }}" target= "_blank" >
{{ App\Page::find( $comment ->page_id)->title }}
</a>
</td>
<td class = "col-lg-1" >
<a href= "{{ URL('admin/comments/'.$comment->id.'/edit') }}" class = "btn btn-success" >编辑</a>
</td>
<td class = "col-lg-1" >
<form action= "{{ URL('admin/comments/'.$comment->id) }}" method= "POST" style= "display: inline;" >
<input name= "_method" type= "hidden" value= "DELETE" >
<input type= "hidden" name= "_token" value= "{{ csrf_token() }}" >
<button type= "submit" class = "btn btn-danger" >删除</button>
</form>
</td>
</tr>
@ endforeach
</table>
</div>
</div>
</div>
</div>
</div>
@endsection
|
learnlaravel5/resources/views/admin/comments/edit.blade.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
@ extends ( 'app' )
@section( 'content' )
<div class = "container" >
<div class = "row" >
<div class = "col-md-10 col-md-offset-1" >
<div class = "panel panel-default" >
<div class = "panel-heading" >编辑评论</div>
<div class = "panel-body" >
@ if ( count ( $errors ) > 0)
<div class = "alert alert-danger" >
<strong>Whoops!</strong> There were some problems with your input.<br><br>
<ul>
@ foreach ( $errors ->all() as $error )
<li>{{ $error }}</li>
@ endforeach
</ul>
</div>
@ endif
<form action= "{{ URL('admin/comments/'.$comment->id) }}" method= "POST" >
<input name= "_method" type= "hidden" value= "PUT" >
<input type= "hidden" name= "_token" value= "{{ csrf_token() }}" >
<input type= "hidden" name= "page_id" value= "{{ $comment->page_id }}" >
Nickname: <input type= "text" name= "nickname" class = "form-control" required= "required" value= "{{ $comment->nickname }}" >
<br>
Email:
<input type= "text" name= "email" class = "form-control" required= "required" value= "{{ $comment->email }}" >
<br>
Website:
<input type= "text" name= "website" class = "form-control" required= "required" value= "{{ $comment->website }}" >
<br>
Content:
<textarea name= "content" rows= "10" class = "form-control" required= "required" >{{ $comment ->content }}</textarea>
<br>
<button class = "btn btn-lg btn-info" >提交修改</button>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
|
后台管理功能完成,查看效果:
6. 大作业
依赖于 Page 的评论功能已经全部完成,个人博客系统雏形诞生。在本系列教程的最后,布置一个大作业:构建出 Article 的前后台,并且加上 Article 与 Comment 的一对多关系,加入评论和评论管理功能。在做这个大作业的过程中,你将会反复地回头去看前面的教程,反复地阅读中文文档,会仔细阅读我的代码,等你完成大作业的时候,Laravel 5 就真正入门啦~~
以上所述就是本文的全部内容了,希望大家能够喜欢。