'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...



Solution 1:[1]

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

Solution 2:[2]

I might be missing something of the original intent, but I found this easy to achieve by extending Twig with a template function that I called cancel

public function cancel($msg = '') {
        throw new Twig\Error\Error("Process cancelled with msg: $msg");
}

As you can see, it simply throws an Exception. Outside the template this is caught and handled.

In the template I write this:

{{ cancel('My reason for cancelling') }}

And, as far as I can tell from my tests, the template processing stops there.

To add the extension follow the normal procedure.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 DarkBee
Solution 2 pgr