template_from_string 的替代方案,用于处理调用自定义 Twig 函数的字符串

Alternative to template_from_string for processing strings with calls to custom Twig functions

除了使用 template_from_string() 评估包含对自定义 Twig 函数(或与此相关的任何其他复杂 Twig 代码)的调用的字符串之外,还有其他方法吗?

这是我现在拥有的代码的简化版本。

{% set content = {
    'item_1' : {
        'images' : {
            'src': 'assets/images/img_1-600.jpg',
            'srcset': "{{ assets('assets/images/img_1-600.jpg') }} 600w, {{ assets('assets/images/img_1-1200.jpg') }} 1200w",
        }
    }
    # additional items follow
}

{% for data in content %}
    <img src="{{ data.images.src }}" srcset="{{ include(template_from_string(data.images.srcset)) }}" alt="">
{% endfor %}

assets() 函数只是 return 是给定路径的静态资产的修订版本(即 assets('assets/images/img_1-600.jpg) 呈现为类似 'assets/images/img_1-600-a4c2254a6d.jpg).

问题始于 img srcset 属性,该属性可能变得相当复杂并且通常包含对需要 return 静态资产修订值的多个资产的引用。

现在我知道我可以修改 assets() 函数来支持那种复杂的场景,但我想保持简单,让 assets() 只处理 1:1 转换.

通过使用 Twig 提供的功能来实现这一点的唯一方法似乎是 template_from_string() 结合 include,这本身并不可怕,但对于评估和渲染这样的简单操作来说确实有点笨重一个字符串。

更不用说 template_from_string 需要默认加载 StringLoaderExtension(),出于性能原因我想再次避免使用它。

为了避免任何额外的插件,您可以直接连接变量

{% set content = {
    'item_1' : {
        'images' : {
            'src': 'assets/images/img_1-600.jpg',
            'srcset': assets('assets/images/img_1-600.jpg')~'  600w,'~assets('assets/images/img_1-1200.jpg')~' 1200w',
        }
    }
} %}

虽然连接方法不是一个坏主意,但经过深思熟虑后我得出结论,这是使用自定义 Twig 函数更有意义的地方之一。

与简单连接相比,支持使用函数的主要论据是,使用函数无需担心正确格式化模板代码(即忘记资产和大小之间的 space srcset 属性值中的描述符)。

这种方法还完全消除了使用 template_from_string() 或其他扩展依赖项的需要。

这是最终的解决方案。

模板代码,简单明了,有很多概述。

{% set content = {
    'item_1' : {
        'images' : {
            'src': 'assets/images/img-600.jpg',
            'srcset': srcset([
                [ assets('assets/images/img-600.jpg'), '600w' ],
                [ assets('assets/images/img-800.jpg'), '800w' ],
                [ assets('assets/images/img-1000.jpg'), '1000w' ],
                [ assets('assets/images/img-1200.jpg'), '1200w' ]
            ]),
        }
    }
    # additional items follow
}

{% for data in content %}
    <img src="{{ data.images.src }}" srcset="{{ data.images.srcset }}" alt="">
{% endfor %}

实际的 Twig 函数称为 srcset,用于根据上述模板中提供的数据为 srcset 属性生成值。

public function srcset(array $srcset)
{
    $output = [];
    foreach ($srcset as $set) {
        // Both parameters need to exist or the set isn't added to the output...
        if (!(isset($set[0]) && isset($set[1]))) {
            // ... just some exception handling that isn't of relevance for the question
            // ...
            continue;
        }
        $output[] = sprintf('%s %s', $set[0], $set[1]);
    }

    return implode(', ', $output);
}