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 就真正入门啦~~
以上所述就是本文的全部内容了,希望大家能够喜欢。