Laravel Folio 是提供便捷的頁面驅動路由套件,本文將介紹如何使用 Laravel Folio 建立 Blog 服務。

設計

作為一個基礎的 Blog 系統,我們會有以下幾個部分:

  1. 建立頁面 create page
  2. 清單 index page
  3. 顯示 show page
  4. 編輯 edit page

與之對應的,會有幾個動作路由:

  1. store api
  2. update api
  3. destroy api

步驟

官方文檔

安裝組件

$ composer require laravel/folio
$ php artisan folio:install

Model 配置

這邊就簡單帶過,不是這篇文章的重點

$ php artisan make:model Post --all
  1. Relation with user (belongs, has many)
  2. factory seeder

建立 create page

$ php artisan make:folio "posts/create"

生成 resources/views/pages/posts/create.blade.php

<?php
auth()->loginUsingId(1); // 登入機制不在這次討論範圍,直接進行登入

use function Laravel\Folio\{name, middleware};

name('posts.create'); // 命名路由
middleware('auth'); // 建立需要登入
?>

<div>
    <form action="{{ route('posts.store') }}" method="post">
        @method('post')
        @csrf

        Title:<input type="text" name="title">
        Body:<textarea name="body" cols="30" rows="10"></textarea>

        <input type="submit" value="Create">
    </form>
</div>

對應的 Store api:

Route::post('posts/create', function (Request $request) {
    $post = Post::query()->create([
        'user_id' => auth()->id(),
        'title' => $request->input('title'),
        'body' => $request->input('body'),
    ]);

    return redirect()->route('posts.show', [
        'post' => $post
    ]);
})->middleware('auth')->name('posts.store');
  1. 建立 create page ✅

  2. 清單 index page

  3. 顯示 show page

  4. 編輯 edit page

  5. store api ✅

  6. update api

  7. destroy api

清單 index page

$ php artisan make:folio "posts/index"

生成 resources/views/pages/posts/index.blade.php

<?php
use function Laravel\Folio\name;

name('posts.index');
$posts = \App\Models\Post::query()
    ->with('user')
    ->latest()
    ->get();
?>

<div>
    <a href="{{ route('posts.create') }}">Create</a>
    @foreach($posts as $post)
        <h2>
            <a href="{{ route('posts.show', [
                    'post' => $post
                ]) }}">{{ $post->title }}
            </a>
        </h2>
        <p>{{ $post->body }}</p>
        By {{ $post->user->name }}
    @endforeach
</div>
  1. 建立 create page ✅
  2. 清單 index page ✅
  3. 顯示 show page
  4. 編輯 edit page

顯示 show page

// 這邊我使用 Route Model Binding 來獲取 `post`
$ php artisan make:folio "posts/[Post]"

生成 resources/views/pages/posts/[Post].blade.php

<?php
  use function Laravel\Folio\name;
  name('posts.show');
?>

<div>
    <a href="{{ route('posts.index') }}">Back</a>
    <h2>{{ $post->title }}</h2>
    <p>{{ $post->body }}</p>
    By {{ $post->user->name }}

    <a href="{{ route('posts.edit', [
        'post' => $post
    ]) }}">Edit</a>

    <form action="{{ route('posts.destroy', [
        'post' => $post
    ]) }}" method="post">
        @method('delete')
        @csrf
        <button type="submit">Delete</button>
    </form>
</div>
  1. 建立 create page ✅
  2. 清單 index page ✅
  3. 顯示 show page ✅
  4. 編輯 edit page

編輯 edit page

$ php artisan make:folio "posts/[Post]/edit"

生成 resources/views/pages/posts/[Post]/edit.blade.php

<?php
auth()->loginUsingId(1);

use function Laravel\Folio\{name, middleware};
name('posts.edit');
middleware('auth');
?>

<div>
    <form action="{{ route('posts.update', ['post' => $post]) }}" method="post">
        @method('put')
        @csrf

        Title:<input type="text" name="title" value="{{ $post->title }}">
        Body:<textarea name="body" cols="30" rows="10">{{ $post->body }}</textarea>

        <input type="submit" value="Update">
    </form>
</div>

對應的 Update api:

Route::put('posts/{post}', function (Request $request, Post $post) {
    $post = tap($post)->update([
        'user_id' => auth()->id(),
        'title' => $request->input('title'),
        'body' => $request->input('body'),
    ]);

    return redirect()->route('posts.show', [
       'post' => $post
    ]);
})->middleware('auth')->name('posts.update');
  1. 建立 create page ✅

  2. 清單 index page ✅

  3. 顯示 show page ✅

  4. 編輯 edit page ✅

  5. store api ✅

  6. update api ✅

  7. destroy api

destroy api

Route::delete('posts/{post}', function (Request $request, Post $post) {
   $post->delete();

   return redirect()->route('posts.index');
})->middleware('auth')->name('posts.destroy');

總結

如果需求本身只是單純的 content 跟基礎操作用這個套件非常節省時間,原本是需要創建 view / routing來滿足,有了這個之後就可以節省掉創建 routes / controller 等環節,可以針對需求作工具選用與調整。