【问题标题】:Check if a custom Twig function exists and then call it检查是否存在自定义 Twig 函数,然后调用它
【发布时间】:2018-01-12 14:18:13
【问题描述】:

我测试是否存在自定义 Twig 函数:

{% if methodExist('sg_datatables_render') %}
    {{ sg_datatables_render(datatable) }}
 {% else %}
    {{ datatable_render((datatable)) }}
{% endif %}

methodExist 是一个简单的Twig_Function

 /**
 * @param $name
 * @return bool
 */
public function methodExist($name){

    if($this->container->get('twig')->getFunction($name)){
        return true;
    }else{
        return false;
    }
}

但我得到一个例外:

Unknown "sg_datatables_render" function. Did you mean "datatable_render"?
500 Internal Server Error - Twig_Error_Syntax

【问题讨论】:

  • 你完全确定 sg_datatables_render 在这种情况下没有在其他地方调用吗?
  • 顺便说一句,通过将'needs_environment' => true 选项传递给methodExist 定义允许您使用Environment $twig 作为该函数的第一个参数,因此container 调用将消失。跨度>
  • 和...尝试dump(methodExist('sg_datatables_render')) 了解发生了什么。

标签: symfony twig


【解决方案1】:

我试图复制这个,事实上,{{ sg_datatables_render(datatable) }} 似乎总是在 sg_datatables_render 尚未注册为 Twig 函数时导致 Twig_Error_Syntax 异常。

然后我尝试了类似的方法。这很难看,但我想知道它是否有效。这个想法是创建一个不存在的函数来避免抛出异常:

$twig->addFunction(new Twig_Function('methodExist', function(Twig_Environment $twig, $name) {
    $hasFunction = $twig->getFunction($name) !== false;

    if (!$hasFunction) {
        // The callback function defaults to null so I have omitted it here
        return $twig->addFunction(new Twig_Function($name));
    }

    return $hasFunction;
}, ['needs_environment' => true]));

但它没有用。我还尝试在新函数中添加一个简单的回调函数,但没有成功。

我用过滤器尝试了同样的技巧,即:

{% if filterExists('sg_datatables_render') %}
    {{ datatable|sg_datatables_render }}
 {% else %}
    {{ datatable|datatable_render }}
{% endif %}

它也没有用。


解决方案 1:{{ renderDatatable(datatable) }}

这样的事情确实有效(耶!):

$twig->addFunction(new Twig_Function('renderDatatable', function(Twig_Environment $twig, $datatable) {
    $sgFunction = $twig->getFunction('sg_datatables_render');

    if ($sgFunction !== false) {
        return $sgFunction->getCallable()($datatable);
    }

    return $twig->getFunction('datatable_render')->getCallable()($datatable);
}, ['needs_environment' => true]));

然后在 Twig 中:

{{ renderDatatable(datatable) }}

renderDatatable 函数专用于呈现数据表,即它不像您的 methodExist 那样是通用/多用途函数,但它可以工作。您当然可以尝试自己创建一个更通用的实现。


解决方案 2:{{ fn('sg_datatables_render', datatable) }}

这是一种更通用的方法。创建一个额外的 Twig 函数来陪伴methodExist

$twig->addFunction(new Twig_Function('fn', function(Twig_Environment $twig, $name, ...$args) {
     $fn = $twig->getFunction($name);

     if ($fn === false) {
         return null;
     }

     // You could add some kind of error handling here
     return $fn->getCallable()(...$args);
 }, ['needs_environment' => true]));

然后您可以将原始代码修改为:

{% if methodExist('sg_datatables_render') %}
    {{ fn('sg_datatables_render', datatable) }}
 {% else %}
    {{ datatable_render((datatable)) }}
{% endif %}

甚至使用三元运算符:

{{ methodExist('sg_datatables_render') ? fn('sg_datatables_render', datatable) : datatable_render(datatable) }}

PS

下面是我如何编写 methodExist 函数:

$twig->addFunction(new Twig_Function('methodExists', function(Twig_Environment $twig, $name) {
     return $twig->getFunction($name) !== false;
 }, ['needs_environment' => true]));
  1. 我在函数名称的末尾添加了s,因为该函数会检查方法/函数是否存在s
  2. 我添加了['needs_environment' => true],所以我可以使用$twig 而不是$this->container->get('twig')。 (感谢 yceruto 提供的这个技巧。)
  3. getFunction 返回 false 如果函数不存在 (see the docs),所以我将函数体简化为单行返回语句。

【讨论】:

    猜你喜欢
    • 2013-10-20
    • 2015-03-04
    • 2015-07-14
    • 1970-01-01
    • 2015-10-05
    • 2012-11-16
    • 2020-10-11
    • 2016-05-08
    • 1970-01-01
    相关资源
    最近更新 更多