iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 24
0

https://ithelp.ithome.com.tw/upload/images/20200929/20113602lmvuOyhMbW.jpg

看完文章後,會想要留下自己的感想或發表意見。本篇就開始來實作文章留言功能。

新增 Comment Model 和相關檔案

依然還是新增 Model 和相關檔案:

php artisan make:model Comment -mf

和規劃資料表結構,commenter_id 欄位是留言的用戶 ID:

database/migrations/2020_09_26_093544_create_comments_table.php

Schema::create('comments', function (Blueprint $table) {
    $table->id();
    $table->text('content');
    $table->foreignId('post_id')->constrained()->onDelete('cascade');
    $table->foreignId('commenter_id')->constrained('users')->onDelete('cascade');
    $table->timestamps();
});

然後跑 Migrate:

php artisan migrate

還有 Comment Model 的一些基本設定和關聯:

app/Comment.php

protected $fillable = [
    'content',
];

protected $casts = [
    'post_id' => 'integer',
    'commenter_id' => 'integer',
];

public function post()
{
    return $this->belongsTo(Post::class);
}

public function commenter()
{
    return $this->belongsTo(User::class);
}

在 Post 裡也要新增 comments 關聯:

app/Post.php

public function comments()
{
    return $this->hasMany(Comment::class);
}

然後配置 Comment 的假文 Factory:

database/factories/CommentFactory.php

$factory->define(Comment::class, function (Faker $faker) {
    return [
        'content' => $faker->realText(20),
    ];
});

這次就不新增 Seeder,直接在 PostSeeder 裡隨機產生 Comment:

database/seeds/PostSeeder.php

use App\Comment;

public function run()
{
    factory(Post::class, 12)->make()->each(function (Post $post) {
        ...

        factory(Comment::class, random_int(0, 3))->make()
            ->each(function (Comment $comment) use ($post) {
                $comment->commenter()->associate(User::inRandomOrder()->first());
                $comment->post()->associate($post);
                $comment->save();
            });
    });
}

留言功能路由

為了讓 Controller 直接產生在 Post 下,執行 Artisan 新增此 Resource Controller:

php artisan make:controller Post/CommentController -r --model=Comment

留言只會用到儲存和刪除留言兩個方法,其他可以不用,路由也一樣 (用 only 指定):

routes/web.php

// Comments
Route::resource('posts.comments', 'Post\CommentController')->shallow()->only('store', 'destroy');

那這個陌生的 shallow() 到底是什麼?先看這裡我們用到了嵌套路由,產生出來的路由表會長這樣:

Method URI Name Action
POST posts/{post}/comments posts.comments.store App\Http\Controllers\Post\CommentController@store
DELETE posts/{post}/comments/{comment} posts.comments.destroy App\Http\Controllers\Post\CommentController@destroy

但會發現,有些路由會同時有父層 ID (post) 和子層 ID (comment),既然有了 comment ID 這個資源的唯一 ID,那前面的父層 post ID 就不需要了。套用 shallow() 後就會把多餘的部分去除,變成淺層嵌套路由:

Method URI Name Action
POST posts/{post}/comments posts.comments.store App\Http\Controllers\Post\CommentController@store
DELETE comments/{comment} comments.destroy App\Http\Controllers\Post\CommentController@destroy

新增 CommentPresenter

php artisan make:presenter CommentPresenter

app/Presenters/CommentPresenter.php

<?php

namespace App\Presenters;

use AdditionApps\FlexiblePresenter\FlexiblePresenter;
use App\Concens\HasAuthUser;

class CommentPresenter extends FlexiblePresenter
{
    use HasAuthUser;

    public function values(): array
    {
        return [
            'id' => $this->id,
            'content' => $this->content,
            'commenter' => UserPresenter::make($this->commenter)->get(),
            'created_at' => $this->created_at->diffForHumans(),
        ];
    }
}

總結

前置作業已準備好,下一篇可以開始新增留言了!

Lightning 範例程式碼:https://github.com/ycs77/lightning

參考資料


上一篇
Day 23 Lightning 喜歡文章功能的問題
下一篇
Day 25 Lightning 新增留言
系列文
關於我用 Laravel 寫 SPA 卻不寫 API 的那檔事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言