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'));
    }

在看下咱們的語句查詢次數:
查詢次數

關於熱加載和懶加載的具體區別,之後再說,你們如今能夠不用區分的去使用它們。

好,本節到這裏結束。

相關文章
相關標籤/搜索