10. 更新數(shù)據(jù)及渴求式加載Eager Loading - 從零開始學(xué)Laravel

從零學(xué)Laravel目錄列表

讀取數(shù)據(jù),插入數(shù)據(jù)我們都學(xué)過(guò)了,還有一個(gè)非常重要的就是更新數(shù)據(jù)。

我們打開這個(gè)鏈接:http://localhost:8000/posts/2

QQ20161121-0.png

下面我們要做兩件事:

  1. 我們要編輯這個(gè)評(píng)論。
  2. 建立這個(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è)面,如下:

編輯帖子頁(yè)

然后當(dāng)我們點(diǎn)擊Update Comment按鈕時(shí),這時(shí)候我們的路由該怎么寫,對(duì)于將一條數(shù)據(jù)存入到數(shù)據(jù)庫(kù),我們用post方式,而對(duì)于更新一條數(shù)據(jù),我們應(yīng)該使用patchput方式,我們來(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í)別getpost方法,所以對(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ò)多,我們看一下:

數(shù)據(jù)庫(kù)查詢次數(shù)

如何解決這個(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ù):


查詢次數(shù)

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

好,本節(jié)到這里結(jié)束。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容