oofbar / craft-twig-toolbox

创建自己的 Twig 辅助工具。

安装次数: 1,242

依赖项: 0

建议者: 0

安全: 0

星标: 12

关注者: 2

分支: 0

公开问题: 0

类型:craft 插件

1.1.0 2024-06-10 22:51 UTC

This package is auto-updated.

Last update: 2024-09-10 23:19:15 UTC


README

将业务逻辑从您的 Twig 模板中分离出来的最简单方法。

此插件所做的只是注册一个 Twig 扩展——其余的都由您自己决定!使用 Twig Toolbox,您终于可以开始清理每个模板顶部的混乱...

用法

Twig Toolbox 允许您将自定义过滤器、函数、全局变量和测试注入到 Craft 的模板引擎中。

要开始使用,请从 Craft 插件商店安装插件,或使用 Composer

composer require oofbar/craft-twig-toolbox
php craft plugins/install twig-toolbox

然后,将以下内容复制到 config/twig-toolbox.php

<?php return [
    'filters' => [],
    'functions' => [],
    'globals' => [],
    'tests' => [],
];

💡 如果你想挑战自己,编写 自己的 Twig 扩展 是了解自定义模块开发的好方法。

让我们看看每个语言特性如何使用的一些示例。

过滤器

→ 关于 Twig 过滤器 的文档

filters 键应包含字母数字键,其值可以是 函数可调用。过滤器 始终 至少有一个参数!

示例

<?php return [
    'filters' => [
        'salePrice' => function(float $price): float {
            return $price * 0.9;
        },
    ],
];
<div class="product">
    <div class="sku">{{ product.sku }}</div>
    <span class="price price--default">{{ product.price | money }}</span>
    <span class="price price--members">{{ product.price | salePrice | money }}</span>
</div>

函数

→ 关于 Twig 函数 的文档

functions 数组中的每个项目都应该有一个字母数字键,以及一个 函数 作为其值。函数需要声明预期的参数,并在适当的情况下明确返回一个值。

😄 您可以在函数中使用几乎任何 Craft API!

示例

<?php return [
    'functions' => [
        'getDeals' => function(): array {
            return Entry::find()
                ->section('products')
                ->onSale(true)
                ->all();
        },
        'log' => function(mixed $message): void {
            Craft::getLogger()->log($message);
        },
    ],
];
{# Use to fetch data for a loop... #}
{% for deal in getDeals() %}
    <div class="deal">
        <div class="title">{{ deal.title }}</div>
        <div class="expiry">{{ deal.saleEndDate | date('short') }}</div>
    </div>
{% else %}
    {# ...or just do something silently! #}
    {% do log('We didn’t show a user any deals!') %}

    <div class="empty">Sorry, there is nothing on sale right now.</div>
{% endfor %}

全局变量

→ 关于 Twig 全局变量 的文档

全局变量最好少用,并且只用于简单的值。Craft 4 中的新 自定义配置 几乎是等效的!

⚠️ 注意您分配给全局变量的内容!调用某些 Craft 或插件 API 可能会在系统初始化时导致竞争条件。

示例

<?php return [
    'globals' => [
        'cutoffTime' => (new \DateTime)->modify('midnight'),
    ],
];
<h2>Prices are valid until {{ cutoffTime | date }}!</h2>

测试

→ 关于 Twig 测试 的文档

测试有点像函数,但仅在使用 Twig 的 is 操作符时可用。它们可以极大地提高模板的可读性——尤其是当逻辑很复杂时。

示例

<?php

use craft\elements\User;

return [
    'tests' => [
        'expensive' => function(float $value): bool {
            return $value > 10.0;
        },
        'member' => function(User $user): bool {
            return $user->isInGroup('members');
        },
    ],
];
{% set image = product.image.one() %}

{% if product.price is expensive %}
    <img src="{{ image.url }}" class="shiny-effect">
{% else %}
    <img src="{{ image.url }}">
{% endif %}

技巧 + 技巧

可调用

PHP 有一个特殊的“类型”用于 可调用 值。这包括我们之前使用的匿名函数或“闭包”,以及一些使添加代理到原生 PHP 和 Craft 函数变得简单的其他语法。

use craft\helpers\Number;

return [
    'filters' => [
        // Built-in PHP functions:
        'chunk' => 'array_chunk',
        // Craft helper proxy:
        'roman' => [Number::class, 'upperRoman'],
    ],
];

处理类型

一些上述功能可以通过接受特殊的 mixed 类型或联合类型来变得更加灵活。例如,expensive 测试可以像这样进行一些类型检查和标准化...

<?php

use craft\elements\Entry;

return [
    'tests' => [
        'expensive' => function(float|Entry $value): bool {
            // Normalize an Entry into a scalar field value:
            if ($value instanceof Entry) {
                $value = $value->price;
            }

            return $value > 10.0;
        },
    ],
];

...然后,模板可以读取得更加流畅

{% if product is not expensive %}
    <button>Buy two!</button>
{% endif %}

参数化

filtersfunctions 可以接受参数来定制它们的行为。如果你发现自己正在添加许多类似的辅助工具,请花点时间考虑如何使用一个或多个参数将它们合并和参数化。

HTML 辅助工具

考虑一下,Twig 如何帮助你生成 HTML,而不是试图自己构建它!

<?php return [
    'functions' => [
        'bem' => function(string $base, array $flags): string {
            $classNames = [$base];

            // Create BEM-style class names, ignoring empty flags:
            foreach (array_filter($flags) as $flag) {
                $classNames[] = "{$base}--{$flag}";
            }

            return join(' ', array_unique($classNames));
        },
    ],
];
<div class="{{ bem('product', [
    product is expensive ? 'expensive' : null,
    currentUser is member ? 'member-pricing' : null,
]) }}">
    {{ product.title }}
</div>

帮助 + 支持

如果你在开始时遇到困难,请在 GitHub 上创建一个问题,我们会尽力帮助你!如果你需要关于特定项目任务的支持(如找到合适的 Craft API),我们建议你在 更广泛的社区 中提出。