Skip to content

Backend Controller

Wncms\Http\Controllers\Backend\BackendController后台 CRUD controllers 的基础。它标准化了 model 解析、命名、cache-tag 处理和常见操作(index/create/store/edit/update/destroy/bulk_delete)。为每个后台资源扩展它。

主要职责

  • 从 controller 名称解析 model classPostController → model key postwncms()->getModelClass('post'))。
  • 派生用于视图和标签的资料表 / 单数 / 复数名称。
  • 提供 cache tag 辅助方法和 flush() 方法。
  • 提供具有合理预设值和 AJAX JSON 回应的主观 CRUD 方法。

属性和预设值

属性类型来源预设行为
$modelClassstringgetModelClass()从不含 Controller 的 controller 基础名称,snake-cased,透过 wncms()->getModelClass(...) 解析。
$cacheTagsarraygetModelCacheTags()预设为 [$this->getModelTable()]
$singularstringgetModelSingular()str()->singular($this->getModelTable())
$pluralstringgetModelPlural()str()->plural($this->getModelSingular())

在需要时,在子 controller 中将这些作为 protected 属性覆盖。

可覆盖的辅助方法

php
// 从 controller 名称解析 model class;如需自订映射请覆盖。
public function getModelClass(): string

// 取得底层 Eloquent 资料表名称。
protected function getModelTable()

// 为此资源提供自订 cache tags。
protected function getModelCacheTags(): array

// 自订资源名词。
protected function getModelSingular(): string
protected function getModelPlural(): string

// 为 single/multi 网站模式套用当前网站列表筛选。
protected function applyBackendListWebsiteScope(Builder $q, ?Request $request = null, bool $onlyWhenExplicitFilter = false): void

// 为 create/update 流程解析网站 ID。
protected function resolveBackendMutationWebsiteIds(bool $fallbackToCurrentWhenEmpty = false): array

// 为已创建/更新模型同步网站绑定。
protected function syncBackendMutationWebsites($model, bool $fallbackToCurrentWhenEmpty = false): void

Cache 控制

php
public function flush(string|array|null $tags = null): bool
  • 透过 wncms()->cache()->tags($tag)->flush() 清除已标记的快取。
  • 如果 $tagsnull,使用 $this->cacheTags

多站点列表筛选辅助方法

applyBackendListWebsiteScope() 用于标准化后台 index 列表筛选(仅针对网站模式为 singlemulti 的模型)。

  • 优先读取请求中的 website_id(兼容旧键 website)。
  • 当请求未传筛选值时,回退到 wncms()->website()->get()?->id 当前网站 ID。
  • 仅在模型支持多站点作用域时调用 applyWebsiteScope(...)
  • global 模型或无法解析当前网站时不做任何处理。
  • 对 index 工具列筛选,建议统一使用 website_id 作为请求参数,并兼容读取旧键 website
  • 对需要预设显示全部数据的页面(例如 Posts),第三个参数传 true,仅在请求明确传入 website_id 时才套用网站作用域。
  • 共用网站筛选器应仅在 gss('multi_website') 启用且模型网站模式为 single/multi 时显示;global 模式应隐藏。

明确筛选模式范例:

php
$q = $this->modelClass::query();
$this->applyBackendListWebsiteScope($q, $request, true);

多站点写入辅助方法

在 create/update 流程,建议使用 syncBackendMutationWebsites($model) 保持 global / single / multi 模式兼容。

  • single/multi 模型,会从请求键(website_idwebsite_ids,及旧键)解析网站 ID。
  • 对非管理员用户,会自动将请求网站 ID 与当前用户可访问网站做交集过滤。
  • 预设不会在网站 ID 为空时强制回退到当前网站。
  • 若业务流程需要回退,请改为调用 syncBackendMutationWebsites($model, true)
  • global 模型会安全 no-op。

内建 CRUD 操作

所有操作假设标准的 backend Blade 路径:backend.{plural}.*

  • index(Request $request)

    • $modelClass 上建立基础查询,按 id desc 排序,回传 backend.{plural}.index
    • 传递 page_titlemodels
  • create(int|string|null $id = null)

    • 新实例或载入现有实例用于「复制/编辑为新」模式。
    • 回传 backend.{plural}.createmodel
  • store(Request $request)

    • create($request->all()),然后:

    • 透过 syncBackendMutationWebsites($model) 自动同步网站绑定。

      • 如果是 AJAX:JSON { status, message, redirect }
      • 否则:重定向到 route('{plural}.edit', ['id' => $model->id])
  • edit(int|string $id)

    • 载入 model,回传 backend.{plural}.editmodel
  • update(Request $request, $id)

    • 类似 findOrFail 的行为(如果缺少则回传讯息),update($request->all())
    • 透过 syncBackendMutationWebsites($model) 自动同步网站绑定。
    • 如果是 AJAX:JSON { status, message, redirect }
    • 否则:重定向回编辑页面。
  • destroy($id)

    • 删除 model,呼叫 $this->flush(),重定向到 index 并显示成功讯息。
  • bulk_delete(Request $request)

    • 接受 model_ids 作为 CSV 或阵列,批次删除。
    • 如果是 AJAX:包含已删除数量的 JSON;否则 back() 并显示讯息。

讯息遵循 WNCMS 翻译(例如 __('wncms::word.successfully_updated'))。标题使用 __('wncms::word.' . $this->singular)

最小子类别范例

php
namespace App\Http\Controllers\Backend;

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

class ProductController extends BackendController
{
    // BackendController 会自动解析 'product' → wncms()->getModelClass('product')
    // 除非您覆盖 getModelClass() 或设定 protected $modelClass
}

覆盖范例

php
namespace App\Http\Controllers\Backend;

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

class CustomProductController extends BackendController
{
    protected function getModelClass(): string
    {
        return \App\Models\Product::class; // 自订映射
    }

    protected function getModelCacheTags(): array
    {
        return ['products', 'catalog']; // 自订 tags
    }

    public function index(Request $request)
    {
        // 使用 parent 的逻辑,或完全覆盖
        $query = $this->modelClass::query();
        $this->applyBackendListWebsiteScope($query);

        // 添加自订筛选
        if ($category = $request->input('category')) {
            $query->where('category', $category);
        }

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

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

总结

  • 为每个后台资源扩展 BackendController
  • 依赖自动 model 解析或根据需要覆盖。
  • 使用内建的 CRUD 方法或覆盖以进行自订逻辑。
  • 利用 cache flushing 和 WNCMS 辅助方法保持程式码简洁。

手动 sort 栏位排序模式

如果模型有业务排序栏位(例如 sort),建议将其设为 backend index 的预设排序,这样更新顺序后可立即在列表中看到结果。

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

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

// 当主排序值相同,使用 id 维持稳定顺序。
if ($sort !== 'id') {
    $q->orderBy('id', 'desc');
}

可避免固定追加 orderBy('id', 'desc') 后,让手动排序更新难以在后台列表中验证的问题。

WNCMS 多站点兼容写入模式

当模型支持 WNCMS 多站点方法时,不要在 create()/update() payload 硬写旧版外键栏位(例如 website_id)。建议先用 controller 共享 helper 解析网站 ID,再用 syncModelWebsites(...) 绑定站点关系:

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

$model->update([
    'name' => $request->name,
    'type' => $request->type,
]);

$this->syncModelWebsites($model, $websiteIds);

在后台表单页面,建议复用通用网站选择器 partial,而不是重复写网站输入 UI:

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

用 ❤️ 制作,献给 WNCMS