38

I have a function in my controller that returns array of entities so in my twig template I do this to iterate over elements:

{% 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 %}

In my controller I have also this PHP function:

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);
        }
    }
}

I can call it in this way:

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

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

It's possible access to the PHP function from Twig template in order to get all the possible combinations of elements in entity? How?

** UPDATE **

This is the function that returns entities processed after by Twig Template:

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;
} 
Reynier
  • 2,420
  • 11
  • 51
  • 91
  • 1
    Why don't you process it forehand in the controller and send both `$items` and `$combinations` to the view? – MGP Sep 06 '13 at 20:20
  • @ManuelGutierrez I try but don't know how to, any ideas on this? – Reynier Sep 06 '13 at 20:26
  • just get `$items` from the database as usual, then pass it to your `DetailCombination()` function on the controller, save it on another variable `$combinations` and pass both to the view, all these steps would be on the same controller function. – MGP Sep 09 '13 at 14:39

8 Answers8

30

Its not possible to access any PHP function inside Twig directly.

What you can do is write a Twig extension. A common structure is, writing a service with some utility functions, write a Twig extension as bridge to access the service from twig. The Twig extension will use the service and your controller can use the service too.

Take a look: http://symfony.com/doc/current/cookbook/templating/twig_extension.html

Cheers.

createproblem
  • 1,542
  • 16
  • 30
16

There is already a Twig extension that lets you call PHP functions form your Twig templates like:

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

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

See official extension repository.

umpirsky
  • 9,902
  • 13
  • 71
  • 96
6

I am surprised the code answer is not posted already, it's a one liner.

You could just {{ categeory_id | getVariations }}

It's a one-liner:
Twig2:

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

Twig 3:

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

Twig 3 but as function instead of a filter:

$this->twig->addFunction(new \Twig\TwigFunction('getVariantsFunc', 'getVariations'));
John
  • 7,507
  • 3
  • 52
  • 52
4

You can check your all defined function by

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

this will give you array of all functions in if your function exist in it you can use it like:

 {{ user.myfunction({{parameter}}) }}
Abhinav bhardwaj
  • 2,657
  • 25
  • 21
  • Thank you, this was very helpful for me! Could you please show me how I might define/pass a callback function? i.e calling array_map PHP function within a Twig template - {{ function('array_map', callback, myarray) }}, possible? – zumek Nov 03 '18 at 00:46
3

I know this is an old thread. But with symfony 3.3 I did this:

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

Symfony docs

Refilon
  • 3,334
  • 1
  • 27
  • 51
1

While I agree with the comments about passing in variables from your controller you can also register undefined functions when setting up the twig environment

$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;
    });

This is from the Twig recipe page

Haven't tried calling a function on an object as the original question requested

Cuespeak
  • 149
  • 1
  • 13
0

This worked for me (using Slim Twig-View):

$twig->getEnvironment()->addFilter(
   new \Twig_Filter('md5', function($arg){ return md5($arg); })
);

This creates a new filter named md5 which returns the MD5 checksum of the argument.

Magnus
  • 17,157
  • 19
  • 104
  • 189
-7

If you really know what you do and you don't mind the evil ways, this is the only additional Twig extension you'll ever need:

function evilEvalPhp($eval, $args = null)
{
    $result = null;
    eval($eval);
    return $result;
}
solarbaypilot
  • 71
  • 1
  • 2
  • 2
    You are wrong in your answer, createproblems answer is NOT causing any security issues like the off-topic PHP code you posted here. You are also wrong about your off-topic Twig comment. I can't even imagine how some people these days are still old fashioned ruining their project by using PHP as templating engine. It has long ago grown out of that and is one of the best methods to make absolutely horrible code. – John Sep 20 '17 at 02:32
  • 1
    John, why would anybody think that PHP-code in the view-layer would create horrible code? That's a lie. Have a look e.g. at the default view-renderer in Zend Framkework 1 and 2 (https://framework.zend.com/manual/2.4/en/modules/zend.view.php-renderer.scripts.html) or in Wordpress etc. My php code is not off-topic, as it allows to call PHP function from Twig template! – solarbaypilot Sep 29 '17 at 08:06