Harold Harold - 2 months ago 13
Twig Question

Symfony/Twig: Stop rendering the rest of a template

I've been searching the internet for this, but I can't find anything regarding this.

I'm creating a simple twig template that is going to be used on multiple locations, but requires some variables.

I want to be able to do something like this:

{% if some_variable is not defined %}
<h1>Some variable was not defined.<h1>
-- stop rendering the rest of the template --
{% endif %}

{{ some_variable }} is defined here.


The reason I'm asking this is really simple.
I don't want my entire template to be indented in one or more
if
-statements, since it'll clutter the entire file very easy.

I know the workaround would be to create multiple templates, but multiple files for a simple condition sounds kind of overkill to me.

If this doesn't exist natively, I'm okay creating an extension for this if anyone can tell me how- and if this can be achieved.

Thanks in advance!

P.S. Don't answer with
{% else %}
, thats exactly the thing I'm trying to avoid here...

Answer

What you ask for is not natively supported.
To achieve such a thing you would need to go through a lot of trouble.

Twig templates are compiled into PHP, extended by the base template of Twig it self. When looking through in the base template you'll see that eventually the function doDisplay will be called. An example of the contents of this function is as follows

    protected function doDisplay(array $context, array $blocks = array())
    {
        // line 1
        echo "\t<div id=\"null_wrapper\">
\t\t<div class=\"invoice_price\">\t\t\t
\t\t\t<div>
\t\t\t\t";
        // line 4
        echo twig_escape_filter($this->env, $this->getAttribute((isset($context["forms"]) ? $context["forms"] : $this->getContext($context, "forms")), "getTextfield", array(0 => "#label_Quantity#", 1 => "txt_new_quantity", 2 => ((array_key_exists("txt_quantity", $context)) ? (_twig_default_filter((isset($context["txt_quantity"]) ? $context["txt_quantity"] : $this->getContext($context, "txt_quantity")), 1)) : (1)), 3 => ((array_key_exists("errors", $context)) ? (_twig_default_filter((isset($context["errors"]) ? $context["errors"] : $this->getContext($context, "errors")), "")) : ("")), 4 => "", 5 => "smallinput"), "method"), "html", null, true);
        echo "
\t\t\t</div>
\t\t\t<div class=\"clear\"></div>
\t\t\t<div>
\t\t\t\t";
        // line 8
        echo twig_escape_filter($this->env, $this->getAttribute((isset($context["forms"]) ? $context["forms"] : $this->getContext($context, "forms")), "getTextfield", array(0 => "#label_Unit_price#", 1 => "txt_new_price_excl", 2 => ((array_key_exists("txt_new_price_excl", $context)) ? (_twig_default_filter((isset($context["txt_new_price_excl"]) ? $context["txt_new_price_excl"] : $this->getContext($context, "txt_new_price_excl")), "")) : ("")), 3 => ((array_key_exists("errors", $context)) ? (_twig_default_filter((isset($context["errors"]) ? $context["errors"] : $this->getContext($context, "errors")), "")) : ("")), 4 => "", 5 => "smallinput"), "method"), "html", null, true);
        echo "<span>";
        echo twig_escape_filter($this->env, getSiteConfigValue("CURRENCY"), "html", null, true);
        echo "</span>
\t\t\t</div>
\t\t\t<div class=\"clear\"></div>
\t\t\t<div>
\t\t\t\t";

As you can see the output is sent to the browser immediately (and catched by ob_start in the base template), so even you could exit out of a template the chance exist you'll end up with broken HTML.

TL:DR The only way to achieve such a thing is to override the compiler of twig, which compiles the twig template into PHP, perhaps you could write your own node, as this renders/compiles as well