madebyraygun/craft-block-loader

Craft CMS 矩阵块和嵌套条目的上下文加载器。

3.0.0 2024-09-24 00:37 UTC

This package is auto-updated.

Last update: 2024-09-24 00:39:01 UTC


README

这是一个 Craft CMS 矩阵块和嵌套条目的上下文加载器。请与 Craft 组件库 结合使用,以格式化您的块上下文,以便与组件库协同工作。

Craft 组件库示例 仓库中查看示例实现。

需求

此插件需要 Craft CMS 5.0 或更高版本,以及 PHP 8.2 或更高版本。

安装

此插件不在 Craft 插件商店中提供,但已发布在 Packagist 上,可以使用 Composer 进行安装。

从终端

composer require madebyraygun/craft-block-loader
php craft plugin/install block-loader

配置

默认情况下,插件将使用 craft/modules/blocks 目录中的 modules\blocks 命名空间初始化所有块类定义,因此请确保您已设置适当的 自动加载配置。通常您会在

"autoload": {
  "psr-4": {
    "modules\\blocks": "modules/blocks"
  }
}

ContextBlock 类在 CraftCMS 的模块初始化逻辑之外工作,但它应遵守您定义的目录结构的 PSR-4 标准。要更改这些默认值,请创建一个 block-loader.php 文件到您的 Craft 配置目录中,以更改此目录。

示例配置

return [
  'blocksNamespace' => 'modules\blocks',
  'scanNewFiles' => false,
  'enableCaching' => true,
];

扫描新文件

根据您定义的 namespace 自动检测可用的 ContextBlock 类,但自动加载器将在您运行 composer dump-autoload -a 重新生成自动加载器类映射之前不会抓取文件更改。这可能在开发过程中略显繁琐。相反,您可以将 scanNewFiles 设置为 true,插件将在每次请求时扫描目录中的新文件。请注意,这 不推荐 用于生产环境,因为可能会影响性能。

用法

使用提供的命名空间 modules\blocks 定义的每个类都与 矩阵字段Ckeditor 字段 内的每个条目块配对。您需要从 ContextBlock 类扩展并实现 getContext 方法以返回您的块上下文数据。

示例: AnchorBlock.php

namespace modules\blocks;

use craft\elements\Entry;
use madebyraygun\blockloader\base\ContextBlock;

class AnchorBlock extends ContextBlock
{
    public function getContext(Entry $block): array
    {
        return [
            'anchorId' => $block->anchorId,
        ];
    }
}

不是很令人兴奋,但希望您能看出这为您提供了返回任何所需自定义数据的机会。

更复杂的示例可以扩展 ContextBlockSettings 类以在每个块的基础上更改设置。设置选项包括

  • fieldHandle:在 matrixckeditor 字段内的 entry 类型处理。默认情况下,这是基于类名自动生成的。例如:类 RichTextBlock 将在您的字段中查找 richText 处理。
  • templateHandle:用于标识每个块的句柄。这可以是您用于在模板中标识块的任何 ID。
  • eagerFields:是否 提前加载字段 以提高相关或嵌套元素的性能。以字段句柄数组的形式传递,例如 ['cards.image','cards.author']
  • cacheable:查询的结果是否应该被缓存(在大型页面上提高性能)
namespace modules\blocks;

use craft\elements\Entry;
use madebyraygun\blockloader\base\ContextBlock;

class RichTextBlock extends ContextBlock
{
    public function setSettings(): void
    {
        $this->settings
            ->templateHandle('richTextColumns')
            ->eagerFields([
                'richTextColumns',
            ]);
    }

    public function getContext(Entry $block): array
    {
        $columnsTable = $block->richTextColumns->all();
        $columns = [];
        foreach ($columnsTable as $column) {
            $columns[] = [
                'body' => $body = ($field ? (string) $field : '');
            ];
        }
        return [
            'align' => $block->align->value ?? 'left',
            'width' => $block->width->value ?? 'default',
            'columns' => $columns,
        ];
    }
}

在你的条目模板中

{% set blocks = entry.blocksFromField('contentBlocks') %}
{% for item in blocks %}
  {% include '@content-blocks/' ~ item.templateHandle with item.context %}
{% endfor %}

缓存

插件将缓存上下文块设置中定义为 cacheable 的所有块。这将提高不随每次请求更改其上下文的块的性能。每次保存条目时都会清除块缓存,只影响与保存的条目相关的块。

如果您需要全局清除所有条目的缓存,可以从 Craft 控制面板的 实用工具 > 缓存 > 块上下文数据 项中进行操作,或者从终端运行 php craft clear-caches/block-loader 命令。

此外,您可以通过将 block-loader.php 配置文件中的 enableCaching 设置为 false 来完全禁用所有块的缓存。这在开发环境中很有用,您希望立即看到块的更改。但您可能希望在生产环境中启用缓存以提高性能。

Ckeditor 字段

无论字段类型(MatrixCkeditor)如何,您都可以在条目上调用 blocksFromField 函数。插件将自动检测字段类型并以相同的格式返回块。然而,对于 Ckeditor 字段,markup 默认情况下被包装成一个块,您可以将上下文传递给特定的组件或直接渲染 markup

{% set blocks = entry.blocksFromField('ckEditorFieldHandle') %}
{% for item in blocks %}
  {% if item.templateHandle == 'markup' %}
    {{ item.context.content|raw }}
  {% else %}
    {% include '@content-blocks/' ~ item.templateHandle with item.context %}
  {% endif %}
{% endfor %}

要对 markup 上下文块进行更高级的预处理,您可以创建一个从 ContextBlock 类扩展并实现 getMarkupContext 方法的自定义类。为了使此类自动调用,必须将 fieldHandle 设置为 markup。或者只需将类命名为 MarkupBlock,插件将自动从类名派生模板句柄作为 markup

namespace modules\blocks;
use madebyraygun\blockloader\base\ContextBlock;

class MarkupBlock extends ContextBlock
{
    public function getMarkupContext(string $markup): array
    {
        // do some preprocessing on the markup before rendering
        $markup = preg_replace('/<p>/', '<p class="prose">', $markup);
        return [
            'content' => $markup,
        ];
    }
}