Symfony 检查自定义细枝函数是否存在,然后调用它

Symfony 检查自定义细枝函数是否存在,然后调用它,symfony,twig,Symfony,Twig,我测试是否存在自定义细枝函数: {% if methodExist('sg_datatables_render') %} {{ sg_datatables_render(datatable) }} {% else %} {{ datatable_render((datatable)) }} {% endif %} methodExist是一个简单的Twig\u函数: /** * @param $name * @return bool */ public functio

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

{% if methodExist('sg_datatables_render') %}
    {{ sg_datatables_render(datatable) }}
 {% else %}
    {{ datatable_render((datatable)) }}
{% endif %}
methodExist
是一个简单的
Twig\u函数

 /**
 * @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\u datatables\u render(datatable)}}
似乎总是在
sg\u datatables\u render
未注册为细枝函数时导致
Twig\u Error\u语法
异常

然后我尝试了类似的东西。它很难看,但我想知道它是否有效。其思想是创建一个不存在的函数,以避免引发异常:

$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)}}
像这样的东西确实管用(耶!):

然后在细枝上:

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


解决方案2:
{{fn('sg_datatables_render',datatable)}
这里有一个更一般的方法。创建附加的细枝函数以伴随
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) }}

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

$twig->addFunction(new Twig_Function('methodExists', function(Twig_Environment $twig, $name) {
     return $twig->getFunction($name) !== false;
 }, ['needs_environment' => true]));
  • 我在函数名的末尾添加了
    s
    ,因为该函数检查方法/函数是否存在s
  • 我添加了
    ['needs\u environment'=>true]
    ,这样我就可以使用
    $twig
    而不是
    $this->container->get('twig')
    。(这一点值得向yceruto致敬。)
  • getFunction
    如果函数不存在,则返回
    false
    ,因此我将函数体简化为单行返回语句

  • 您是否完全确定在这种情况下不会在别处调用
    sg\u datatables\u render
    ?顺便说一句,通过将
    'needs\u environment'=>true
    选项传递到
    methodExist
    定义,您可以使用
    environment$twig
    作为此函数的第一个参数,因此,
    容器
    调用将消失。。。尝试
    dump(methodExist('sg\u datatables\u render'))
    了解发生了什么。
    $twig->addFunction(new Twig_Function('methodExists', function(Twig_Environment $twig, $name) {
         return $twig->getFunction($name) !== false;
     }, ['needs_environment' => true]));