讀取數(shù)據(jù),插入數(shù)據(jù)我們都學(xué)過(guò)了,還有一個(gè)非常重要的就是更新數(shù)據(jù)。
我們打開這個(gè)鏈接:http://localhost:8000/posts/2

下面我們要做兩件事:
- 我們要編輯這個(gè)評(píng)論。
- 建立這個(gè)評(píng)論與用戶之間的關(guān)系,通常我們要知道是誰(shuí)發(fā)表了這個(gè)評(píng)論.
好,我們先來(lái)做編輯評(píng)論的這個(gè)功能,簡(jiǎn)單的流程是我點(diǎn)擊這個(gè)評(píng)論,跳轉(zhuǎn)到編輯評(píng)論的頁(yè)面,然后保存這個(gè)評(píng)論。
我們先來(lái)想一下,顯示編輯評(píng)論的這個(gè)頁(yè)面的路由該怎么寫,通常是這樣表達(dá)的,我要編輯某個(gè)帖子下的某個(gè)評(píng)論,那可能會(huì)這么寫:
// 編輯屬于帖子ID為3的評(píng)論ID為1的評(píng)論
// posts/3/comments/1/edit
posts/{post}/comments/{comment}/edit
嗯,上面的路由可以清晰的表達(dá)我們想要的意思,能很好的表達(dá)出具體功能的意思,但是路徑太深了,我們簡(jiǎn)化下:
Route::get('comments/{comment}/edit', 'CommentsController@edit');
好的,我們到CommentsController中寫上edit()方法:
public function edit(Comment $comment)
{
// 加載視圖層,并傳遞$comment數(shù)據(jù)到視圖
return view('comments.edit', compact('comment'));
}
然后,我們到pages/show.blade.php中為我們的評(píng)論都加上一個(gè)編輯的鏈接:
<ul class="list-group">
@foreach ($post->comments as $comment)
<li class="list-group-item">
{{ $comment->content }}
<a href="/comments/{{ $comment->id }}/edit">Edit</a>
</li>
@endforeach
</ul>
下一步呢,當(dāng)然是建立我們的comments/edit.balde.php視圖層,路徑為resources/views/comments/edit.balde.php
@extends('layout')
@section('content')
<h1>Edit the Comment</h1>
<form method="{{-- 未知 --}}" action="{{-- 這里的路徑現(xiàn)在還沒(méi)寫 --}}">
{{ csrf_field() }}
<div class="form-group">
<textarea name="content" class="form-control">{{ $comment->content }}</textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Update Comment</button>
</div>
</form>
@stop
訪問(wèn):http://localhost:8000/posts/2 點(diǎn)擊Edit,跳轉(zhuǎn)到http://localhost:8000/comments/11/edit頁(yè)面,如下:

然后當(dāng)我們點(diǎn)擊Update Comment按鈕時(shí),這時(shí)候我們的路由該怎么寫,對(duì)于將一條數(shù)據(jù)存入到數(shù)據(jù)庫(kù),我們用post方式,而對(duì)于更新一條數(shù)據(jù),我們應(yīng)該使用patch或put方式,我們來(lái)寫這個(gè)路由:
// 更新評(píng)論ID為X的評(píng)論
Route::patch('comments/{comment}', 'CommentsController@update');
進(jìn)入CommentsController編寫update()方法:
public function update(Request $request, Comment $comment)
{
// update()只會(huì)更新Comment模型中$fillable允許的字段
$comment->update($request->all());
// 跳轉(zhuǎn)到該評(píng)論所屬的帖子頁(yè)
return redirect('posts/' . $comment->post->id);
}
下面修改下視圖:
@extends('layout')
@section('content')
<h1>Edit the Comment</h1>
<form method="POST" action="/comments/{{ $comment->id }}">
{{ method_field('PATCH') }}
{{ csrf_field() }}
<div class="form-group">
<textarea name="content" class="form-control">{{ $comment->content }}</textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Update Comment</button>
</div>
</form>
@stop
上面有一點(diǎn)要注意,我們現(xiàn)在是使用了PATCH的請(qǐng)求,但是表單中的method只能識(shí)別get和post方法,所以對(duì)于patch, put, delete這些方法,我們要這么寫:
<form method="POST" action="">
{{ method_field('PATCH') }}
</form>
當(dāng)然也可以直接這么寫:
<form method="POST" action="">
<input type="hidden" name="_method" value="PATCH">
</form>
我們的編輯評(píng)論的最簡(jiǎn)單的功能做完了,下面我們看下如何為評(píng)論添加用戶,我們先創(chuàng)建一個(gè)users的migration文件,默認(rèn)安裝laravel的時(shí)候都是有這個(gè)文件的,我們最初把它刪除了,現(xiàn)在再來(lái)創(chuàng)建一下:
php artisan make:migration create_users_table --create=users
編輯下這個(gè)文件的up()函數(shù):
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('username')->unique();
$table->string('email')->unique();
$table->string('password');
$table->timestamps();
});
}
然后在create_comments_table.php這個(gè)migration文件中,添加user_id外鍵:
$table->integer('user_id')->unsigned()->index();
現(xiàn)在如果我們直接執(zhí)行php artisan migrate, users表可以被創(chuàng)建,但是我們?cè)赾omments的migration文件中添加的user_id外鍵是不會(huì)被創(chuàng)建的,對(duì)于這種添加一個(gè)字段,我們也要單獨(dú)寫一個(gè)migration文件。
不過(guò)在項(xiàng)目的初期,我們也可以直接更改migration文件,然后執(zhí)行:
php artisan migrate:refresh
上面這條命令會(huì)清空所有的表并重新創(chuàng)建,需慎用, 如果只想撤銷上一次的migrate,可以使用php artisan migrate:rollback命令,該命令會(huì)執(zhí)行migration文件中的down()方法。
這里我們執(zhí)行下php artisan migrate:refresh
我們進(jìn)入tinker, 重新插入一些數(shù)據(jù):
>>> namespace App;
=> null
>>> $user = New User;
=> App\User {#634}
>>> $user->username = 'zhoujiping';
=> "zhoujiping"
>>> $user->email = 'zhoujiping@zhoujiping.com';
=> "zhoujiping@zhoujiping.com"
>>> $user->password = bcrypt('123456');
=> "$2y$10$OM9pBb.xU58hvulnyhq1jeiWPxi8SbddYBW.rhhttEJMraBuVyWdq"
>>> $user->save();
=> true
>>> $post = New Post;
=> App\Post {#627}
>>> $post->title = 'My First Post';
=> "My First Post"
>>> $post->save();
=> true
>>> $comment = New Comment;
=> App\Comment {#639}
>>> $comment->user_id = 1;
=> 1
>>> $comment->content = 'The content of the comment';
=> "The content of the comment"
>>> $post->addComment($comment);
=> App\Comment {#639
user_id: 1,
content: "The content of the comment",
post_id: 1,
updated_at: "2016-11-21 06:02:33",
created_at: "2016-11-21 06:02:33",
id: 1,
}
我們?cè)俚?code>pages/show.blade.php視圖,加上用戶的用戶名:
<ul class="list-group">
@foreach ($post->comments as $comment)
<li class="list-group-item">
{{ $comment->content }}
<a href="/comments/{{ $comment->id }}/edit">Edit</a>
<a href="#" class="pull-right">{{ $comment->user->username }}</a>
</li>
@endforeach
</ul>
不要忘記去Comment.php中寫上評(píng)論與用戶的關(guān)系
public function user()
{
return $this->belongsTo(User::class);
}
像上面這樣寫,程序跑通沒(méi)有問(wèn)題,但是我們看{{ $comment->user->username }}這條語(yǔ)句會(huì)在每次循環(huán)的時(shí)候都去查詢一次用戶表信息,導(dǎo)致數(shù)據(jù)庫(kù)的查詢次數(shù)過(guò)多,我們看一下:

如何解決這個(gè)問(wèn)題呢,laravel提供了熱加載和懶加載的方式可以解決這個(gè)問(wèn)題,我們進(jìn)入到
postsController文件中,修改下show()函數(shù):
public function show(Post $post)
{
$post = Post::with('comments.user')->find($post->id);
return view('posts.show', compact('post'));
}
我們看這句話Post::with('comments.user'), 意思是查詢的時(shí)候加載post的關(guān)系comments, 而.user是指加載comments的關(guān)系時(shí),還需要加載comments的關(guān)系user。 這樣就能解決多次查詢的問(wèn)題了。
我們把上面的代碼優(yōu)化下,因?yàn)槲覀円呀?jīng)做了Post的路由模型綁定,我們可以使用懶加載,所以代碼改成這樣:
public function show(Post $post)
{
$post->load('comments.user');
return view('posts.show', compact('post'));
}
在看下我們的語(yǔ)句查詢次數(shù):

關(guān)于熱加載和懶加載的具體區(qū)別,以后再說(shuō),大家現(xiàn)在可以不用區(qū)分的去使用它們。
好,本節(jié)到這里結(jié)束。