Check if template exists before rendering

27,219

Solution 1

The service holding the twig engine if configured as default is 'templating'.

Inside your Controller do the following:

if ( $this->get('templating')->exists('AcmeDemoBundle:Foo:bar.html.twig') ) {
     // ...
}

The alternative would be catching exception the render() method throws like this:

 try {
      $this->get('templating')->render('AcmeDemoBundle:Foo:bar.html.twig')
  } catch (\Exception $ex) {
     // your conditional code here.
  }

In a normal controller ...

$this->render('...')

is only an alias for ...

$this->container->get('templating')->renderResponse($view, $parameters, $response);

... while ...

$this->get('...') 

... is an alias for

$this->container->get('...')

Have a look at Symfony\FrameworkBundle\Controller\Controller.

Solution 2

The templating service will be removed in future Symfony versions. The future-proof solution based on the twig service is:

if ($this->get('twig')->getLoader()->exists('AcmeDemoBundle:Foo:bar.html.twig')) {
    // ...
}

Solution 3

In case you need to check for template existance from inside twig templates you have to use the array include methods, as described in the documentation:

{% include ['page_detailed.html', 'page.html'] %}

Solution 4

Maybe also an option:

{% include 'AcmeDemoBundle:Foo:bar.html.twig' ignore missing %}

The ignore missing addition tells twig to simply do nothing, when the template is not found.

Solution 5

You can do it this way using dependency injection:

use Symfony\Component\Templating\EngineInterface;

public function fooAction(EngineInterface $templeEngine)
{
    if ($templeEngine->exists("@App/bar/foo.html.twig")) {
        // ...
    }
    // ...
}

Tested with Symfony 3.4.

Share:
27,219

Related videos on Youtube

K. Weber
Author by

K. Weber

Updated on September 19, 2020

Comments

  • K. Weber
    K. Weber almost 4 years

    is there a way to check if twig template exists before calling to render? A try catch block seems not to work, at least in dev environment, and plus, I prefer a check than the cost of an exception.

    This class TwigEngine has an exists() method, but didn't find examples on use.

  • yuvilio
    yuvilio about 9 years
    This is pretty handy on the template end. Can have an empty template to safely do nothing when tempate is not there {% include ['page_detailed.html', 'page.html', 'empty-catch-all.html'] %}
  • Radhakrishna
    Radhakrishna over 7 years
    Is there a way to include the template if already not exists only ?
  • aalaap
    aalaap over 7 years
    I can't imagine a situation where this would be useful, but it's still a very interesting thing to know of.
  • Admin
    Admin over 7 years
    it is in cases of dynamically loaded templates. Like if you want to include a specific template by a given name and this template with that name doesnt exist and you don't want a 500 come up than this is a possible option
  • Michael
    Michael about 7 years
    Thanks - using this to load in templates dynamically as per comment above.
  • dezlov
    dezlov about 6 years
    Do you have any reference to support your statement that the templating service will be removed in future Symfony versions?
  • Bizmate
    Bizmate over 5 years
    in the way i have seen with latest flex you dont need the @App reference, if the templates are in their default location just the relative path is enough ie i have templates/Email/campaign.html.twig and @App/Email/campaign.html.twig does not work just Email/campaign.html.twig works
  • Nico Haase
    Nico Haase over 5 years
    It should be reference enouhh that Javier is working for SensioLabs ;)
  • rrehbein
    rrehbein about 5 years
    An announcement about deprecating templating: symfony.com/blog/…
  • Anyone
    Anyone about 5 years
    This is no longer the recommended answer, please check javiers answer below.
  • ali6p
    ali6p almost 4 years
    This works for Symfony 3.4.* $this->container->get('templating')->exists('@YourBundle/..P‌​ath../twigName.html.‌​twig') if there is not $this->container use $this->getContainer()->... instead.