I test if a custom Twig function exists:
{% if methodExist(\'sg_datatables_render\') %}
{{ sg_datatables_render(datatable) }}
{% else %}
{{ datatable_re
I tried to replicate this, and indeed, {{ sg_datatables_render(datatable) }}
seems to always cause a Twig_Error_Syntax
exception when sg_datatables_render
has not been registered as a Twig function.
I then tried something like this. It's ugly, but I wanted to know if it works. The idea is that a non-existing function will be created to avoid the exception being thrown:
$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 it didn't work. I also tried to add a simple callback function to the new function with no success.
I tried the same trick with filters, i.e.:
{% if filterExists('sg_datatables_render') %}
{{ datatable|sg_datatables_render }}
{% else %}
{{ datatable|datatable_render }}
{% endif %}
It didn't work either.
{{ renderDatatable(datatable) }}
Something like this does work (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 is specific to rendering datatables, i.e. it's not a general/multipurpose function like your methodExist
is, but it works. You can of course try to create a more general implementation yourself.
{{ fn('sg_datatables_render', datatable) }}
Here's a more general approach. Create an additional Twig function to accompany 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]));
Then you could modify your original code to this:
{% 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) }}
Here's how I'd write the methodExist
function:
$twig->addFunction(new Twig_Function('methodExists', function(Twig_Environment $twig, $name) {
return $twig->getFunction($name) !== false;
}, ['needs_environment' => true]));
s
to the end of the function's name because the function checks whether a method/function exists.['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 doesn't exist (see the docs), so I simplified the function body to a single-line return statement.