从Twig模板调用PHP函数

39
我在控制器中有一个返回实体数组的函数,因此在我的Twig模板中,我会这样迭代元素:
{% for groupName, entity in items %}
    <ul>
        <ul>
            {% for element in entity %}
                <li>{{ element.getLabel }}</li>
                <li><input type="text" name="detail[{{ element.getId }}]" id="pd_{{ element.getId }}" /><input type="text" name="price[{{ element.getId }}]" id="pd_price_{{ element.getId }}" /><input type="text" name="stock[{{ element.getId }}]" id="pd_stock_{{ element.getId }}" /></li>
            {% endfor %}
        </ul>
    </ul>
{% endfor %}

在我的控制器中,我还有这个PHP函数:

private function DetailCombination($arr, $level, &$result, $curr = array()) {
    for ($i = 0; $i < count($arr); $i++) {
        $new = array_merge($curr, array($arr[$i]));
        if ($level == 1) {
            sort($new);
            if (!in_array($new, $result)) {
                $result[] = $new;
            }
        } else {
            combinations($arr, $level - 1, $result, $new);
        }
    }
}

我可以这样称呼它:

for ($i = 0; $i < count($arr); $i++) {
    $this->DetailCombination($arr, $i + 1, $result);
}

// TEST
foreach ($result as $arr) {
    echo join(" ", $arr) . '<br>';
}

如何从Twig模板访问PHP函数以获取实体元素的所有可能组合?

** 更新 **

这是返回在Twig模板中处理后的实体的函数:

private function getVariations($category_id) {
    $items = array();

    $em = $this->getDoctrine()->getManager();
    $entityCategory = $em->getRepository('CategoryBundle:Category')->find($category_id);

    foreach ($entityCategory->getProductDetails() as $entity) {
        if ($entity->getToProduct() == 1) {
            foreach ($entity->getDetailGroup() as $group) {
                if (!array_key_exists($group->getName(), $items)) {
                    $items [$group->getName()] = array();
                }

                $items [$group->getName()] [] = $entity;
            }
        } 
    }

    return $items;
} 

1
为什么不在控制器中预处理并将 $items$combinations 一起发送到视图呢? - MGP
@ManuelGutierrez 我尝试了但不知道怎么做,你有什么想法吗? - Reynier
只需像往常一样从数据库中获取 $items,然后将其传递给控制器上的 DetailCombination() 函数,在另一个变量 $combinations 上保存它并将两者都传递到视图中,所有这些步骤都将在同一个控制器函数中完成。 - MGP
8个回答

31

无法直接在Twig中访问任何PHP函数。

您可以编写一个Twig扩展。常见的结构是编写一些实用函数的服务,编写一个桥接Twig扩展以从Twig访问该服务。Twig扩展将使用该服务,并且您的控制器也可以使用该服务。

请参考:http://symfony.com/doc/current/cookbook/templating/twig_extension.html

干杯。


16

已经有一个Twig扩展可以让您从Twig模板中调用PHP函数,例如:

Hi, I am unique: {{ uniqid() }}.

And {{ floor(7.7) }} is floor of 7.7.

请参考官方扩展仓库


FTR:该扩展名为Twig PHP Function(截至2023年07月)。 - jave.web

6

我很惊讶代码答案还没有被发布,这是一行代码。

你可以只用 {{ categeory_id | getVariations }}

这是一个一行的代码:
Twig2:

$twig->addFilter('getVariations', new Twig_Filter_Function('getVariations'));

Twig 3:

$this->twig->addFilter(new \Twig\TwigFilter('getVariations','getVariations'));

将Twig 3作为函数而不是过滤器:

$this->twig->addFunction(new \Twig\TwigFunction('getVariantsFunc', 'getVariations'));

4

您可以通过以下方式检查所有定义的函数

$arr = get_defined_functions();
print_r($arr);

这将给您一个包含所有函数的数组,如果您的函数存在其中,您可以像这样使用它:

 {{ user.myfunction({{parameter}}) }}

谢谢,这对我非常有帮助!您能否向我展示如何定义/传递回调函数?例如在Twig模板中调用array_map PHP函数 - {{ function('array_map', callback, myarray) }},是否可行? - zumek

3

我知道这是一个旧的主题。但在Symfony 3.3中,我做了以下操作:

{{ render(controller(
    'AppBundle\\Controller\\yourController::yourAction'
)) }}

Symfony docs


1

虽然我同意关于从控制器传入变量的评论,但您也可以在设置twig环境时注册未定义的函数。

$twig->registerUndefinedFunctionCallback(function ($name) {
        // security
        $allowed = false;
        switch ($name) {
            // example of calling a wordpress function
            case 'get_admin_page_title':
                $allowed = true;
                break;
        }

        if ($allowed && function_exists($name)) {
            return new Twig_Function_Function($name);
        }

        return false;
    });

这段文字来源于Twig食谱页面
原问题要求调用对象上的函数,但我尚未尝试过。

对于那些在2023年寻找文档的人:https://twig.symfony.com/doc/3.x/recipes.html - Sandra

0
这对我有用(使用Slim Twig-View):
$twig->getEnvironment()->addFilter(
   new \Twig_Filter('md5', function($arg){ return md5($arg); })
);

这将创建一个名为md5的新过滤器,它返回参数的MD5校验和


-7

如果你真的知道你在做什么,而且你不介意邪恶的方式,这是你唯一需要的额外Twig扩展:

function evilEvalPhp($eval, $args = null)
{
    $result = null;
    eval($eval);
    return $result;
}

2
你的回答是错误的,createproblems的回答并没有像你在这里发布的与主题无关的PHP代码一样引起任何安全问题。你对于与主题无关的Twig评论也是错误的。 我甚至无法想象现在还有些人如此守旧,通过使用PHP作为模板引擎来破坏他们的项目。 它早已不再是这样了,而且是制作绝对可怕的代码的最佳方法之一。 - John
1
约翰,为什么会有人认为视图层的PHP代码会产生可怕的代码呢?这是个谎言。例如,在Zend Framework 1和2(https://framework.zend.com/manual/2.4/en/modules/zend.view.php-renderer.scripts.html)或WordPress等中,请查看默认的视图渲染器。我的PHP代码不是题外话,因为它允许从Twig模板调用PHP函数! - solarbaypilot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接