读取数据,插入数据我们都学过了,还有一个非常重要的就是更新数据。
我们打开这个链接:http://localhost:8000/posts/2
下面我们要做两件事:
我们要编辑这个评论。
建立这个评论与用户之间的关系,通常我们要知道是谁发表了这个评论.
好,我们先来做编辑评论的这个功能,简单的流程是我点击这个评论,跳转到编辑评论的页面,然后保存这个评论。
我们先来想一下,显示编辑评论的这个页面的路由该怎么写,通常是这样表达的,我要编辑某个帖子下的某个评论,那可能会这么写:
// 编辑属于帖子ID为3的评论ID为1的评论
// posts/3/comments/1/edit
posts/{post}/comments/{comment}/edit
嗯,上面的路由可以清晰的表达我们想要的意思,能很好的表达出具体功能的意思,但是路径太深了,我们简化下:
Route::get('comments/{comment}/edit', 'CommentsController@edit');
好的,我们到CommentsController
中写上edit()
方法:
public function edit(Comment $comment)
{
// 加载视图层,并传递$comment数据到视图
return view('comments.edit', compact('comment'));
}
然后,我们到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>
</li>
@endforeach
</ul>
下一步呢,当然是建立我们的comments/edit.balde.php视图层,路径为resources/views/comments/edit.balde.php
@extends('layout')
@section('content')
<h1>Edit the Comment</h1>
<form method="{{-- 未知 --}}" action="{{-- 这里的路径现在还没写 --}}">
{{ 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
访问:http://localhost:8000/posts/2 点击Edit,跳转到http://localhost:8000/comment...页面,如下:
然后当我们点击Update Comment按钮时,这时候我们的路由该怎么写,对于将一条数据存入到数据库,我们用post
方式,而对于更新一条数据,我们应该使用patch
或put
方式,我们来写这个路由:
// 更新评论ID为X的评论
Route::patch('comments/{comment}', 'CommentsController@update');
进入CommentsController编写update()
方法:
public function update(Request $request, Comment $comment)
{
// update()只会更新Comment模型中$fillable允许的字段
$comment->update($request->all());
// 跳转到该评论所属的帖子页
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
上面有一点要注意,我们现在是使用了PATCH
的请求,但是表单中的method只能识别get
和post
方法,所以对于patch, put, delete
这些方法,我们要这么写:
<form method="POST" action="">
{{ method_field('PATCH') }}
</form>
当然也可以直接这么写:
<form method="POST" action="">
<input type="hidden" name="_method" value="PATCH">
</form>
我们的编辑评论的最简单的功能做完了,下面我们看下如何为评论添加用户,我们先创建一个users
的migration文件,默认安装laravel的时候都是有这个文件的,我们最初把它删除了,现在再来创建一下:
php artisan make:migration create_users_table --create=users
编辑下这个文件的up()函数:
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
这个migration文件中,添加user_id
外键:
$table->integer('user_id')->unsigned()->index();
现在如果我们直接执行php artisan migrate
, users
表可以被创建,但是我们在comments的migration文件中添加的user_id
外键是不会被创建的,对于这种添加一个字段,我们也要单独写一个migration文件。
不过在项目的初期,我们也可以直接更改migration文件,然后执行:
php artisan migrate:refresh
上面这条命令会清空所有的表并重新创建,需慎用, 如果只想撤销上一次的migrate,可以使用php artisan migrate:rollback
命令,该命令会执行migration文件中的down()
方法。
这里我们执行下php artisan migrate:refresh
我们进入tinker
, 重新插入一些数据:
>>> 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,
}
我们再到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
中写上评论与用户的关系
public function user()
{
return $this->belongsTo(User::class);
}
像上面这样写,程序跑通没有问题,但是我们看{{ $comment->user->username }}
这条语句会在每次循环的时候都去查询一次用户表信息,导致数据库的查询次数过多,我们看一下:
如何解决这个问题呢,laravel提供了热加载和懒加载的方式可以解决这个问题,我们进入到postsController
文件中,修改下show()
函数:
public function show(Post $post)
{
$post = Post::with('comments.user')->find($post->id);
return view('posts.show', compact('post'));
}
我们看这句话Post::with('comments.user')
, 意思是查询的时候加载post的关系comments, 而.user
是指加载comments
的关系时,还需要加载comments的关系user
。 这样就能解决多次查询的问题了。
我们把上面的代码优化下,因为我们已经做了Post的路由模型绑定,我们可以使用懒加载,所以代码改成这样:
public function show(Post $post)
{
$post->load('comments.user');
return view('posts.show', compact('post'));
}
在看下我们的语句查询次数:
关于热加载和懒加载的具体区别,以后再说,大家现在可以不用区分的去使用它们。
好,本节到这里结束。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。