10. 更新数据及渴求式加载Eager Loading - 从零开始学Laravel

从零开始学Laravel目录php

读取数据,插入数据咱们都学过了,还有一个很是重要的就是更新数据。html

咱们打开这个连接:http://localhost:8000/posts/2laravel

QQ20161121-0.png

下面咱们要作两件事:数据库

  1. 咱们要编辑这个评论。bash

  2. 创建这个评论与用户之间的关系,一般咱们要知道是谁发表了这个评论.函数

好,咱们先来作编辑评论的这个功能,简单的流程是我点击这个评论,跳转到编辑评论的页面,而后保存这个评论。post

咱们先来想一下,显示编辑评论的这个页面的路由该怎么写,一般是这样表达的,我要编辑某个帖子下的某个评论,那可能会这么写:优化

// 编辑属于帖子ID为3的评论ID为1的评论
// posts/3/comments/1/edit
posts/{post}/comments/{comment}/edit

嗯,上面的路由能够清晰的表达咱们想要的意思,能很好的表达出具体功能的意思,可是路径太深了,咱们简化下:this

Route::get('comments/{comment}/edit', 'CommentsController@edit');

好的,咱们到CommentsController中写上edit()方法:spa

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方式,而对于更新一条数据,咱们应该使用patchput方式,咱们来写这个路由:

// 更新评论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只能识别getpost方法,因此对于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'));
    }

在看下咱们的语句查询次数:
查询次数

关于热加载和懒加载的具体区别,之后再说,你们如今能够不用区分的去使用它们。

好,本节到这里结束。

相关文章
相关标签/搜索