I tried to reproduce this, and indeed, {{ sg_datatables_render(datatable) }} seems to always throw a Twig_Error_Syntax exception when sg_datatables_render not registered as a Twig function.
Then I tried something like this. This is ugly, but I wanted to know if it works. The idea is that a non-existent function is created to avoid an exception:
$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]));
But that did not work. I also tried adding a simple callback function to a new function without success.
I tried the same filter trick, that is:
{% if filterExists('sg_datatables_render') %} {{ datatable|sg_datatables_render }} {% else %} {{ datatable|datatable_render }} {% endif %}
That didn't work either.
Solution 1: {{ renderDatatable(datatable) }}
Something like this works (yay!):
$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]));
And then in Twig:
{{ renderDatatable(datatable) }}
The renderDatatable function renderDatatable specific for data rendering, i.e. Not a generic / multi-purpose function like your methodExist , but it works. You can, of course, try to create a more general implementation yourself.
Solution 2: {{ fn('sg_datatables_render', datatable) }}
Here's a more general approach. Create an additional Twig function to accompany the methodExist :
$twig->addFunction(new Twig_Function('fn', function(Twig_Environment $twig, $name, ...$args) { $fn = $twig->getFunction($name); if ($fn === false) { return null; }
Then you can change your source code:
{% if methodExist('sg_datatables_render') %} {{ fn('sg_datatables_render', datatable) }} {% else %} {{ datatable_render((datatable)) }} {% endif %}
Or even use the ternary operator:
{{ methodExist('sg_datatables_render') ? fn('sg_datatables_render', datatable) : datatable_render(datatable) }}
PS
This is how I write the methodExist function:
$twig->addFunction(new Twig_Function('methodExists', function(Twig_Environment $twig, $name) { return $twig->getFunction($name) !== false; }, ['needs_environment' => true]));
- I added
s to the end of the function name because the function checks if the method / function s exists. - I added
['needs_environment' => true] , so I can use $twig instead of $this->container->get('twig') . (Kudos to yceruto for this tip.) getFunction returns false if the function does not exist ( see the docs ), so I simplified the function body to a single-line return statement.