keepsuit/liquid

PHP 实现的 liquid 标记语言

v0.6.5 2024-08-21 14:17 UTC

README

Latest Version on Packagist Tests Total Downloads

这是 Shopify Liquid 模板引擎的 PHP 版本。

如果你使用 Laravel,可以使用 laravel-liquid 包。

Liquid 是一个具有有趣优点的模板引擎

  • 易于学习,语法简单。
  • 安全性高,因为它不允许用户在您的服务器上运行不安全的代码。
  • 可扩展,允许您添加自己的过滤器和标签。

Shopify Liquid 版本兼容性

与 Shopify Liquid 的区别

  • 错误模式 未实现,解析始终严格。
  • include 标签未实现,因为它已弃用,可以用 render 替换。

安装

您可以通过 composer 安装此包

composer require keepsuit/liquid

用法

创建一个新的模板工厂实例

$factory = \Keepsuit\Liquid\TemplateFactory::new()
    // enable strict variables mode
    ->setStrictVariables()
    // rethrow exceptions instead of rendering them
    ->setRethrowExceptions()
    // set filesystem used to load templates
    ->setFilesystem(new \Keepsuit\Liquid\FileSystems\LocalFileSystem(__DIR__ . '/views'));

然后创建一个新的模板实例,解析 liquid 模板

/** @var \Keepsuit\Liquid\TemplateFactory $factory */

// Parse from string
$template = $factory->parseString('Hello {{ name }}!');

// Parse from template (loaded from filesystem)
$template = $factory->parseTemplate('index');

最后渲染模板

/** @var \Keepsuit\Liquid\TemplateFactory $factory */
/** @var \Keepsuit\Liquid\Template $template */

// Create the render context
$context = $factory->newRenderContext(
    // Environment variables only available in the current context
    environment: [
        'name' => 'John',
    ],
    // Environment variables that are shared with all sub-contexts
    staticEnvironment: []
)

$view = $template->render($context);
// $view = 'Hello John!';

对于高级用例,您还可以流式传输渲染输出(仍处于实验阶段)

/** @var \Keepsuit\Liquid\Template $template */
/** @var \Keepsuit\Liquid\Render\RenderContext $context */

$stream = $template->stream($context);
// $stream is a Generator<string>

数据源

Liquid 支持几乎任何类型的对象,但为了更好地控制模板中可访问的数据,您可以传递您的数据作为 Drop 对象,并更好地控制可访问的数据。Drop 是扩展了 Keepsuit\Liquid\Drop 类的标准 PHP 对象。类的公共属性和公共方法将作为属性在模板中可用。您还可以重写 liquidMethodMissing 方法来处理未定义的属性。

Liquid 提供了一些属性来控制数据源的行为

  • Hidden: 隐藏方法或属性,使其无法从 liquid 访问。
  • Cache: 缓存方法的结果,它将只调用一次,并将结果存储在数据源中。
use Keepsuit\Liquid\Drop;

class ProductDrop extends Drop {
    public function __construct(private Product $product) {}

    public function title(): string {
        return $this->product->title;
    }

    public function price(): float {
        return round($this->product->price, 2);
    }
    
    #[\Keepsuit\Liquid\Attributes\Cache]
    public function expensiveOperation(){
        // complex operation
    }
    
    #[\Keepsuit\Liquid\Attributes\Hidden]
    public function buy(){
        // Do something
    }
}

如果您在领域类中实现了 MapsToLiquid 接口,液体渲染器将自动将您的对象转换为数据源。

use Keepsuit\Liquid\Contracts\MapsToLiquid;

class Product implements MapsToLiquid {
    public function __construct(public string $title, public float $price) {}

    public function toLiquid(): ProductDrop {
        return new ProductDrop($this);
    }
}

高级用法

自定义标签

要创建自定义标签,您需要创建一个扩展 Keepsuit\Liquid\Tag 抽象类(如果标签有主体,则扩展 Keepsuit\Liquid\TagBlock)的类。

use Keepsuit\Liquid\Parse\TagParseContext;
use Keepsuit\Liquid\Render\RenderContext;
use Keepsuit\Liquid\Tag;

class CustomTag extends Tag
{
    public static function tagName(): string
    {
        return 'custom';
    }

    public function render(RenderContext $context): string
    {
        return '';
    }

    public function parse(TagParseContext $context): static
    {
        return $this;
    }
}

注意

查看默认标签的实现,了解如何实现 parserender 方法。

然后您需要在模板工厂中注册该标签

/** @var \Keepsuit\Liquid\TemplateFactory $factory */

$factory->registerTag(CustomTag::class);

自定义过滤器

要创建自定义过滤器,您需要创建一个扩展 Keepsuit\Liquid\Filters\FiltersProvider 抽象类的类。

该类的每个公共方法都将注册为过滤器。

use Keepsuit\Liquid\Filters\FiltersProvider;

class CustomFilters extends FiltersProvider
{
    public function customFilter(string $value): string
    {
        return 'custom '.$value;
    }
}

然后您需要在模板工厂中注册过滤器提供者

/** @var \Keepsuit\Liquid\TemplateFactory $factory */

$factory->registerFilter(CustomFilters::class);

测试

composer test

变更日志

有关最近更改的更多信息,请参阅 CHANGELOG

鸣谢

许可协议

MIT 许可协议(MIT)。有关更多信息,请参阅 许可文件