Skip to content

Base Manager

WNCMS 提供 ModelManager 作为所有 Manager classes 的基础。它集中管理资料撷取、过滤、排序、快取与分页。

概述

ModelManager 是一个抽象类别,位于:

Wncms\Services\Managers\ModelManager

每个具体的 Manager(如 PostManagerLinkManager)都应该继承它,并实作必要的方法:getModelClass()buildListQuery()

主要特性

  • 统一的查询建构:标准化的方式来建构查询(tags、keywords、status 等)
  • 快取支援:整合 WNCMS Cache 机制以提升效能
  • 网站范围:自动套用 multi-site 过滤(若启用)
  • 分页与限制:内建 countoffsetpage_size 处理
  • Eager loading:简化关联载入
  • 可扩充性:易于覆写方法来客制化行为

必须实作的方法

getModelClass()

php
abstract public function getModelClass(): string;

用途: 回传此 Manager 所处理的 Model class 名称。

范例:

php
public function getModelClass(): string
{
    return wncms()->getModelClass('post');
}

此方法使用 wncms()->getModelClass() 来尊重 config/wncms.php 中的 model 覆写设定。

buildListQuery()

php
abstract protected function buildListQuery(array $options): mixed;

用途: 定义如何建构清单查询。此方法套用过滤条件、排序、限制等。

参数:

参数类型说明
$optionsarray过滤、排序、分页相关选项

预期回传: 一个 Eloquent Builder 实例或原始 query。

范例:

php
protected function buildListQuery(array $options): mixed
{
    $q = $this->query();

    $this->applyTagFilter($q, $options['tags'] ?? [], $options['tag_type'] ?? 'post_category');
    $this->applyKeywordFilter($q, $options['keywords'] ?? [], ['title', 'content']);
    $this->applyStatus($q, 'status', $options['status'] ?? 'published');
    $sort = $options['sort'] ?? 'id';
    $direction = $options['direction'] ?? 'desc';
    $this->applyOrdering($q, $sort, $direction, $sort === 'random');

    return $q;
}

常用公开方法

get(array $options = []): ?Model

撷取单一记录。

常见选项:

选项类型说明
idint以 ID 撷取
slugstring以 slug 撷取
namestring以 name 撷取
withsarray要 eager load 的 relations
wheresarray额外的 where 条件
cachebool是否使用快取(预设 true
secondsint快取时间(秒),预设为 gss('data_cache_time')3600

范例:

php
$post = wncms()->post()->get(['slug' => 'hello-world']);

getList(array $options = []): mixed

撷取记录集合或分页结果。

常见选项:

选项类型说明
pageint分页页码
page_sizeint每页笔数
countint限制笔数(不分页时使用,0 = 不限制)
offsetint跳过笔数
cachebool是否使用快取(预设 true
secondsint快取时间(秒),预设为 gss('data_cache_time')3600
withsarray要 eager load 的 relations
wheresarray额外的 where 条件
sortstring建议使用的排序栏位
directionstring建议使用的排序方向:ascdesc

范例:

php
$posts = wncms()->post()->getList([
    'page_size' => 10,
    'status' => 'published',
    'sort' => 'created_at',
    'direction' => 'desc',
]);

排序参数规范

建议在 Manager 对外选项中优先使用 sortdirection

run(array $options = []): mixed

在没有快取的情况下执行 buildListQuery()

范例:

php
$query = wncms()->post()->run([
    'tags' => ['news'],
    'count' => 5,
]);

回传的是 Builder 实例,你可以继续链结额外的查询方法。

内建的过滤 Helpers

ModelManager 提供多个 helper 方法来简化过滤逻辑:

Method说明
applyIds($q, $column, $ids)依 ID 过滤
applyExcludeIds($q, $column, $ids)排除特定 ID
applyTagFilter($q, $tags, $type)依 tag 类型过滤
applyExcludedTags($q, $excludedTagIds)排除特定 tag ID
applyKeywordFilter($q, $keywords, $columns)套用关键字搜寻
applyStatus($q, $column, $status)依状态过滤
applyWebsiteId($q, $websiteId)依网站 ID 限定范围
applyOrdering($q, $column, $sequence, $isRandom)套用排序
applyLimit($q, $count)限制笔数
applyOffset($q, $offset)跳过记录
applyWiths($q, $relations)Eager load 多个关联

这些方法确保所有 WNCMS Manager 的行为一致。

多站点模式 Helper

Manager 也提供集中式模式检查方法:

php
public function getModelMultiWebsiteMode(): string
public function isModelWebsiteScoped(): bool

这些方法会优先使用模型方法(getMultiWebsiteMode() / getWebsiteMode()),因此可以尊重运行时模式覆写。

显式 false 选项值

ModelManager 现在会把显式传入的 false 视为有效过滤值(例如 status => false),而不是当作空值忽略。

当你需要过滤布林栏位时,可直接这样写:

php
$items = wncms()->advertisement()->getList([
    'status' => false,
]);

AdvertisementManager 现在支援按广告类型过滤(一种或多种)。

单一类型可使用 type

php
$items = wncms()->advertisement()->getList([
    'type' => 'image',
]);

多类型可使用 types

php
$items = wncms()->advertisement()->getList([
    'types' => ['image', 'card'],
]);

快取支援

ModelManagerwncms()->cache() 整合,自动处理快取键生成与失效。

设定属性:

属性类型说明
$cacheKeyPrefixstring用于生成快取键的前缀(例如 wncms_post
$cacheTagsstring/array快取标签,用于批次失效(例如 ['posts']
$shouldAuthbool是否在快取键中包含使用者 ID(预设 false

范例:

php
protected string $cacheKeyPrefix = 'wncms_product';
protected string|array $cacheTags = ['products'];
protected bool $shouldAuth = false;

快取会在 get()getList() 中自动启用,除非明确设定 cache => false

扩充 ModelManager

要建立自订 Manager:

  1. 继承 ModelManager
  2. 实作 getModelClass()
  3. 实作 buildListQuery()
  4. (选用)覆写 get()getList() 来自订行为

自订 App Manager 解析

当你用动态方式呼叫 manager(例如 wncms()->post())时,WNCMS 会依照这个顺序解析:

  1. App\Services\Managers\{Name}Manager
  2. Wncms\Services\Managers\{Name}Manager

App manager 会优先透过 Laravel container 解析,因此建构子相依性可自动注入。

WNCMS 也支援单复数别名查找。例如 wncms()->catalog_item()wncms()->catalog_items() 都可解析到 App\Services\Managers\CatalogItemManager

范例:

php
namespace App\Services\Managers;

use Wncms\Services\Managers\ModelManager;

class ProductManager extends ModelManager
{
    protected string $cacheKeyPrefix = 'wncms_product';
    protected string|array $cacheTags = ['products'];

    public function getModelClass(): string
    {
        return wncms()->getModelClass('product');
    }

    protected function buildListQuery(array $options): mixed
    {
        $q = $this->query();

        $this->applyTagFilter($q, $options['tags'] ?? [], 'product_category');
        $this->applyKeywordFilter($q, $options['keywords'] ?? [], ['name', 'description']);
        $this->applyStatus($q, 'status', $options['status'] ?? 'active');

        return $q;
    }
}

详细指南请参阅 Create a Manager

核心对齐说明

  • Core 已移除 BannerManager。横幅/广告位请统一使用 AdvertisementManagerwncms()->advertisement())。
  • StarterManager 现已改为基于 ModelManager 的脚手架模板,用于复制后快速创建新 manager。
  • SettingManager 仍为特殊的键值管理器,不继承 ModelManager,以保持 gss() / uss() 依赖的 get($key, $fallback)update($key, $value) API。
  • SettingManager 仍已对齐动态模型解析:查询前会通过 wncms()->getModelClass('setting') 解析模型类。

Tag 模型兼容性

ModelManager::applyTagFilter() 现在接受弹性输入(mixed),并动态解析 tag 模型类。

解析顺序:

  1. config('wncms.models.tag.class')config('wncms.models.tag')
  2. wncms()->getModelClass('tag')

这样可兼容 package/custom tag 模型实例,不再强依赖继承 Wncms\Models\Tag

用 ❤️ 制作,献给 WNCMS