Skip to content

Create a Controller

Controllers 定義在 WNCMS 中處理請求的邏輯。根據您的使用案例,您將擴展 WNCMS 的內建 base controllers 以獲得正確的上下文。

選擇正確的 Base

使用案例擴展自命名空間視圖 / 回應
Backend(後台 CRUD 頁面)Wncms\Http\Controllers\Backend\BackendControllerApp\Http\Controllers\Backendbackend.{model_plural}.*
Frontend(主題頁面)Wncms\Http\Controllers\Frontend\FrontendControllerApp\Http\Controllers\Frontendfrontend.theme.{theme}.*
API(JSON 端點)Wncms\Http\Controllers\Api\V1\ApiControllerApp\Http\Controllers\Api\V1JSON 回應
自訂 base(罕見)Wncms\Http\Controllers\ControllerApp\Http\Controllers任意選擇

避免直接擴展 base Controller,除非您正在建立新的 controller 層級或專門的抽象。

範例:Backend Controller

php
namespace App\Http\Controllers\Backend;

use Illuminate\Http\Request;
use Wncms\Http\Controllers\Backend\BackendController;

class PostController extends BackendController
{
    public function index(Request $request)
    {
        $query = $this->modelClass::query();
        $this->applyBackendListWebsiteScope($query);
        // 對預設應顯示全部資料的頁面,可改用:
        // $this->applyBackendListWebsiteScope($query, $request, true);

        if ($keyword = $request->get('keyword')) {
            $query->where('title', 'like', "%{$keyword}%");
        }

        $posts = $query->orderByDesc('id')->paginate(20);

        return $this->view("backend.{$this->plural}.index", [
            'page_title' => __('wncms::word.model_management', ['model_name' => __('wncms::word.' . $this->singular)]),
            'posts' => $posts,
        ]);
    }
}

Backend 多站點 create/update 模式

對於使用 WNCMS singlemulti 網站模式的模型,建議使用 controller 共用 helper 解析並同步網站關聯:

php
$websiteIds = $this->resolveModelWebsiteIds($this->modelClass);

if ($this->supportsWncmsMultisite($this->modelClass) && empty($websiteIds)) {
    return back()->withInput()->withErrors(['message' => __('wncms::word.website_not_found')]);
}

$post = $this->modelClass::create($payload);
$this->syncModelWebsites($post, $websiteIds);

對於大多數 backend controller,也可直接使用更高階 helper:

php
$post = $this->modelClass::create($payload);
$this->syncBackendMutationWebsites($post);

在 backend form-items 中,網站輸入建議使用共用 partial:

blade
@include('wncms::backend.common.website_selector', ['model' => $post, 'websites' => $websites ?? []])

Backend 手動 sort 欄位排序模式

對使用業務排序欄位(例如 sort)的模型,建議將該欄位作為列表預設排序,並僅把 id desc 當作次排序:

php
$sort = in_array($request->sort, $this->modelClass::SORTS) ? $request->sort : 'sort';
$direction = in_array($request->direction, ['asc', 'desc']) ? $request->direction : 'desc';

$query->orderBy($sort, $direction);

if ($sort !== 'id') {
    $query->orderBy('id', 'desc');
}

這樣可確保後台列表排序穩定,且順序更新後可直接驗證結果。

範例:Frontend Controller

php
namespace App\Http\Controllers\Frontend;

use Wncms\Http\Controllers\Frontend\FrontendController;

class PageController extends FrontendController
{
    public function show(string $slug)
    {
        $page = wncms()->getModelClass('page')::where('slug', $slug)->first();

        abort_unless($page, 404);

        return $this->view("frontend.theme.{$this->theme}.pages.show", compact('page'));
    }
}

範例:API Controller

php
namespace App\Http\Controllers\Api\V1;

use Illuminate\Http\Request;
use Wncms\Http\Controllers\Api\V1\ApiController;

class LinkController extends ApiController
{
    public function index(Request $request)
    {
        $links = wncms()->link()->getList([
            'status' => 'active',
            'page_size' => (int) $request->input('page_size', 20),
        ]);

        return response()->json([
            'status' => 'success',
            'data' => $links,
        ]);
    }
}

命名和 Routes

  • 使用複數 route 前綴(例如 postslinks)。

  • 將 route 名稱與複數慣例匹配(posts.indexlinks.editfrontend.links.single)。

  • 在正確的 route 檔案中註冊:

    • routes/backend.php 用於 backend controllers。
    • routes/frontend.php 用於 frontend controllers。
    • routes/api.php 用於 API controllers。

總結

  1. 決定上下文 — backend、frontend 或 API。
  2. 擴展適當的 base controller。
  3. 遵循命名慣例 用於 route 名稱和視圖資料夾。
  4. 使用 WNCMS helpers 例如 wncms()->getModelClass()wncms()->cache()wncms()->view()
  5. 保持 controllers 精簡 — 盡可能將業務邏輯移至 Managers 或 Resources。

用 ❤️ 製作,獻給 WNCMS