不寫 JavaScript,就讓網站變成 SPA!Laravel Livewire 初體驗 (下)

程式技術
sharkHead

此篇文章為下篇,還沒有看過上篇的朋友,建議可以先看完上篇文章

繼續之前的文章,我們已經有了回覆區塊,也完成了對回覆表單的內容進行即時驗證,本篇文章會完成將回覆的內容存進資料庫,並在回覆表單底下顯示所有的回覆。

新建回覆的 Model 與資料表

首先在專案內輸入以下指令,新建一個 Reply 的 Model 與 migration。

php artisan make:model Reply -m

上述指令會生成兩個檔案。

  • app/Models/Reply.php
  • database/migrations/2021_02_05_155509_create_replies_table.php

migration 檔名前半段的日期是抓取現在的時間。

因為我們需要存儲留言內容,所以得先在 Reply.php 中設定 $fillable 屬性。

<?php

...

class Reply extends Model
{
    use HasFactory;
    // fillable 屬性是用來設定可以被批量賦值的資料表欄位
    protected $fillable = ['content'];
}

再來是設定 migration 檔案,新增 content 這個欄位。

<?php

...

class CreateRepliesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('replies', function (Blueprint $table) {
            $table->id();
            // 新增一個 content 欄位
            $table->string('content')->comment('回覆內容');
            $table->timestamps();
        });
    }

    ...
}

執行 migrate 指令,創建資料表。

php artisan migrate

儲存留言內容與顯示所有留言

先在 resources/views/livewire/replies.blade.php 的回覆表單中新增一個送出回覆的按鈕。

            ...
            <div class="d-flex justify-content-between">
                <!-- 錯誤訊息顯示 -->
                <div class="d-flex justify-content-center align-items-center">
                    @error('content') <span class="text-danger">{{ $message }}</span> @enderror
                </div>
                <!-- 使用 wire:click 觸發 Replies.php 的 store 方法 -->
                <button wire:click="store" class="btn btn-primary">回覆</button>
            </div>
            ...

可以發現這裡使用新的 Livewire component 語法 wire:click="store",當按鈕被點擊時,就會觸發 app/Http/Livewire/Replies.phpstore() 方法。

因為 Replies.php 中還沒有 store() 方法,我們需要將其補上。

<?php

...
use App\Models\Reply;

class Replies extends Component
{
    ...

    // 儲存回覆
    public function store()
    {
        // 通過驗證才會進行後續操作
        $this->validate();
        
        // 儲存留言至資料庫
        Reply::create([
            'content' => $this->content,
        ]);

        // 清空回覆表單的內容
        $this->content = '';
    }

    public function render()
    {
        return view('livewire.replies');
    }
}

這個時候可以嘗試留言並送出回覆表單,成功送出表單的話,表單內容就會被清空,連線至資料庫查看,應該就會發現裡面多了一筆剛剛留言的資料。

顯示回覆列表與刪除回覆

接下來實作顯示所有回覆的回覆列表,當留言回覆成功時,下方的回覆列表會立即顯示剛剛成功的留言。

首先在 replies.php 中的回覆表單底下新增個回覆列表區塊,並用剛剛的 wire:click,實作一個刪除回覆的按鈕。

<div>
    <!-- 評論回覆 -->
    ...

    <!-- 回覆列表 -->
    @if ($replies->count() > 0)
        <div class="card shadow mb-4">
            <div class="card-body p-4">
                <ul class="list-group list-group-flush">
                    @foreach ($replies as $reply)
                        <li class="list-group-item" name="reply-{{ $reply->id }}" id="reply-{{ $reply->id }}">

                            <div class="row">
                                <div class="col-10 d-flex justify-content-start align-items-center">
                                    <!-- 回覆內容 -->
                                    <div class="d-flex flex-column">
                                        <div class="card-text">
                                            {!! nl2br(e($reply->content)) !!}
                                        </div>
                                    </div>
                                </div>

                                <div class="col-2 d-flex justify-content-end align-items-center">
                                    <!-- 回覆刪除按鈕 -->
                                    <button onclick="confirm('您確定要刪除此回覆嗎?') || event.stopImmediatePropagation()"
                                    wire:click="destroy({{ $reply->id }})" class="btn btn-danger">
                                        刪除
                                    </button>
                                </div>
                            </div>

                        </li>
                    @endforeach
                </ul>
            </div>
        </div>
    @endif
</div>

這裡使用 $replies 這個變數接收所有的回覆資料,但目前後端並未傳送此資料,等會需要在 Replies.php 中補上。

一般來說,刪除資料都需要經過二次確認避免使用者誤點,這樣使用者體驗也會比較好,因此在這裡加上下面一行,確保按下刪除按鈕後會對使用者進行二次確認。

onclick="confirm('您確定要刪除此回覆嗎?') || event.stopImmediatePropagation()"

更新 Replies.php,補上 destroy() 方法,還有使用 ORM 操作取得所有回覆資料並傳送至前端。

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Models\Reply;

class Replies extends Component
{
    ...

    // 刪除回覆
    public function destroy(Reply $reply)
    {
        $reply->delete();
    }

    public function render()
    {
        return view('livewire.replies', [
            // 傳送所有回覆資料至前端
            'replies' => Reply::all()
        ]);
    }
}

一個簡單的即時更新留言板就這麼完成啦!

2021_07_14_19_34_39_60eecbcf8c4cc.png

 

Livewire 的上手難度很低,呈現的效果卻非常好,雖然面對複雜的前端架構應該還是無法與目前主流的前端框架(React 與 Vue)相比。

但是如果網站只需要一些簡單的前後端資料交換,那麼 Livewire 可以說是非常不錯的選擇!

感謝您的閱讀~

參考資料

sharkHead
written by
sharkHead

後端打工仔,在下班後喜歡研究各種不同的技術。稍微擅長 PHP,並偶爾涉獵前端開發。個性就像動態語言般隨興,但渴望做事能像囉嗦的靜態語言那樣嚴謹。

0 則留言