Check if custom twig function exists and then called

I check if a custom Twig function exists:

{% if methodExist('sg_datatables_render') %} {{ sg_datatables_render(datatable) }} {% else %} {{ datatable_render((datatable)) }} {% endif %} 

methodExist is a simple Twig_Function :

  /** * @param $name * @return bool */ public function methodExist($name){ if($this->container->get('twig')->getFunction($name)){ return true; }else{ return false; } } 

But I get an exception:

 Unknown "sg_datatables_render" function. Did you mean "datatable_render"? 500 Internal Server Error - Twig_Error_Syntax 
+1
source share
1 answer

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; } // You could add some kind of error handling here return $fn->getCallable()(...$args); }, ['needs_environment' => true])); 

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.
+1
source

All Articles