CINXE.COM

Twig - The flexible, fast, and secure PHP template engine

<!DOCTYPE html> <html lang="en"> <head> <meta charset=”utf-8″> <meta name="author" content="Symfony" /> <meta name="language" content="en" /> <meta name="copyright" content="Symfony" /> <meta name="publisher" content="Symfony" /> <meta name="description" content="Twig - The flexible, fast, and secure template engine for PHP" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="icon" href="/favicon.ico" sizes="32x32"> <link rel="icon" href="/favicon-32x32.png" sizes="32x32" type="image/png"> <link rel="apple-touch-icon" href="/apple-touch-icon.png"> <link rel="manifest" href="/site.webmanifest"> <link rel="canonical" href="https://twig.symfony.com/" /> <title>Twig - The flexible, fast, and secure PHP template engine</title> <link rel="preconnect" href="https://connect.symfony.com"> <link rel="stylesheet" href="/assets/styles/app-7bca8a34611ba9363c0784b9710e1376.css"> <link rel="stylesheet" href="https://connect.symfony.com/css/sln.css"> <script> const prefersDark = window.matchMedia('(prefers-color-scheme: dark)'); prefersDark.addEventListener('change', () => { if (localStorage.getItem('user-theme') === 'system') applyTheme('system'); }); const storedTheme = localStorage.getItem('user-theme') || 'system'; const applyTheme = theme => { document.documentElement.setAttribute('data-theme', theme === 'system' ? (prefersDark.matches ? 'dark' : 'light') : theme); document.querySelector('#theme-switcher')?.setAttribute('data-mode', theme); }; applyTheme(storedTheme); document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('.theme-switcher button').forEach(btn => btn.addEventListener('click', () => { localStorage.setItem('user-theme', btn.dataset.theme); applyTheme(btn.dataset.theme); }) ); applyTheme(storedTheme); }); </script> <script type="text/javascript" defer> document.head.appendChild(Object.assign(document.createElement('script'), { src: 'https://connect.symfony.com/sln.js?customize_url=/js/sln_customize.js', async: true, })); </script> <script async="true" data-browser-key="8b625d823f16400c01cd72ffcc7b0ef8deb18c640f26f893480ca5dfad400252" data-sample-rate="1.000000" data-parent-trace-id="7eb8c3eb762c56793aa52625e5e5ce92" data-transaction-name="App\Controller\Actions::home" data-collector="https://ingest.blackfire.io" src="https://admin.pipeline.blackfire.io/js/probe.js"></script></head> <body> <header class="hd"> <div class="hd__container"> <a href="/" class="hd__logo"> <img src="/images/logo.png" width="529" height="379" alt="Twig" srcset="/images/logo.sm.png 209w, /images/logo.md.png 529w" /> </a> <nav class="hd__menu"> <ul> <li> <a class="active" href="/">About</a> </li> <li> <a class="" href="/doc/3.x/">Docs</a> </li> <li> <a class="" href="/play">Playground</a> </li> <li> <a class="" href="/development">Dev</a> </li> </ul> </nav> <div class="hd__title"> <h1><a href="/">Twig</a></h1> <h2>The flexible, fast, and secure<br />template engine for PHP</h2> </div> <a href="https://symfony.com" class="hd__symfony"> <img src="/images/symfony-product.svg" width="767" height="100" alt="a Symfony Product" /> </a> </div> </header> <main class="bd"> <div class="content"> <div class="row"> <div class="intro"> <h2>Twig is a modern template engine for PHP</h2> <ul> <li> <strong>Fast</strong>: Twig <em>compiles</em> templates down to plain optimized PHP code. The overhead compared to regular PHP code was reduced to the very minimum. </li> <li> <strong>Secure</strong>: Twig has a <em>sandbox</em> mode to evaluate untrusted template code. This allows Twig to be used as a template language for applications where users may modify the template design. </li> <li> <strong>Flexible</strong>: Twig is powered by a flexible <em>lexer</em> and <em>parser</em>. This allows the developer to define its own custom tags and filters, and create its own DSL. </li> </ul> </div> <div class="links_intro"> <ul> <li class="learn_more"><a href="/doc/3.x/">Learn more<img class="png_fix" src="/images/arrow.svg" alt="Learn more" height="20" /></a></li> <li class="certification"><a href="https://certification.symfony.com/exams/twig.html">Certification<img class="png_fix" src="/images/arrow.svg" alt="Certification" height="20" /></a></li> <li class="playground"><a href="/play">Playground<img class="png_fix" src="/images/arrow.svg" alt="Playground" height="20" /></a></li> <li class="install_now"><a href="/doc/3.x/intro.html#installation">Install now<img class="rotate-90 png_fix" src="/images/arrow.svg" alt="Install now" height="20" /></a></li> </ul> </div> </div> <div> <div class="section"> <h1 id="what-makes-twig-better-than-php-as-a-template-engine"><a class="headerlink" href="#what-makes-twig-better-than-php-as-a-template-engine" title="Permalink to this headline">What makes Twig better than PHP as a template engine?</a></h1> <p>When it comes to template engines in PHP, many people will tell you that PHP itself is a template engine. But even if PHP started its life as a template language, it did not evolve like one in the recent years. As a matter of fact, it doesn't support many features modern template engines should have nowadays:</p> <ul> <li><p><strong>Concise</strong>: The PHP language is verbose and becomes ridiculously verbose when it comes to output escaping:</p> <div translate="no" data-loc="2" class="notranslate codeblock codeblock-length-sm codeblock-php"> <div class="codeblock-scroll"> <pre class="codeblock-lines">1 2</pre> <pre class="codeblock-code"><code><span class="hljs-meta">&lt;?php</span> <span class="hljs-keyword">echo</span> <span class="hljs-variable"><span class="hljs-variable-other-marker">$</span>var</span> <span class="hljs-meta">?&gt;</span> <span class="hljs-meta">&lt;?php</span> <span class="hljs-keyword">echo</span> htmlspecialchars(<span class="hljs-variable"><span class="hljs-variable-other-marker">$</span>var</span>, ENT_QUOTES, <span class="hljs-string">'UTF-8'</span>) <span class="hljs-meta">?&gt;</span></code></pre> </div> </div> <p>In comparison, Twig has a very concise syntax, which make templates more readable:</p> <div translate="no" data-loc="3" class="notranslate codeblock codeblock-length-sm codeblock-twig"> <div class="codeblock-scroll"> <pre class="codeblock-lines">1 2 3</pre> <pre class="codeblock-code"><code><span class="hljs-template-variable">{{ var }}</span><span class="xml"> </span><span class="hljs-template-variable">{{ var|<span class="hljs-keyword">escape</span> }}</span><span class="xml"> </span><span class="hljs-template-variable">{{ var|e }}</span><span class="xml"> </span><span class="hljs-comment">{# shortcut to escape a variable #}</span></code></pre> </div> </div></li> <li><p><strong>Template oriented syntax</strong> Twig has shortcuts for common patterns, like having a default text displayed when you iterate over an empty array:</p> <div translate="no" data-loc="5" class="notranslate codeblock codeblock-length-sm codeblock-twig"> <div class="codeblock-scroll"> <pre class="codeblock-lines">1 2 3 4 5</pre> <pre class="codeblock-code"><code><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">for</span></span> user in users %}</span><span class="xml"> * </span><span class="hljs-template-variable">{{ user.name }}</span><span class="xml"> </span><span class="hljs-template-tag">{% <span class="hljs-name">else</span> %}</span><span class="xml"> No users have been found. </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endfor</span></span> %}</span></code></pre> </div> </div></li> <li><p><strong>Full Featured</strong>: Twig supports everything you need to build powerful templates with ease: multiple inheritance, blocks, automatic output-escaping, and much more:</p> <div translate="no" data-loc="5" class="notranslate codeblock codeblock-length-sm codeblock-twig"> <div class="codeblock-scroll"> <pre class="codeblock-lines">1 2 3 4 5</pre> <pre class="codeblock-code"><code><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">extends</span></span> "layout.html" %}</span><span class="xml"> </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">block</span></span> content %}</span><span class="xml"> Content of the page... </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endblock</span></span> %}</span></code></pre> </div> </div></li> <li><strong>Easy to learn</strong>: The syntax is easy to learn and has been optimized to allow web designers to get their job done fast without getting in their way.</li> </ul> <p>Of course, PHP is also the language for which you can find the more template engine projects. But most of them do not embrace web development best practices yet:</p> <ul> <li><strong>Extensibility</strong>: Twig is flexible enough for all your needs, even the most complex ones. Thanks to an open architecture, you can implement your own language constructs (tags, filters, functions, and even operators) to create your very own DSL.</li> <li><strong>Unit tested</strong>: Twig is fully unit-tested. The library is stable and ready to be used in large projects.</li> <li><strong>Documented</strong>: Twig is fully documented, with a dedicated online book, and of course a full API documentation.</li> <li><p><strong>Secure</strong>: When it comes to security, Twig has some unique features:</p> <ul> <li><p><em>Automatic output escaping</em>: To be on the safe side, you can enable automatic output escaping globally or for a block of code:</p> <div translate="no" data-loc="5" class="notranslate codeblock codeblock-length-sm codeblock-twig"> <div class="codeblock-scroll"> <pre class="codeblock-lines">1 2 3 4 5</pre> <pre class="codeblock-code"><code><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">autoescape</span></span> "html" %}</span><span class="xml"> </span><span class="hljs-template-variable">{{ var }}</span><span class="xml"> </span><span class="hljs-template-variable">{{ var|<span class="hljs-keyword">raw</span> }}</span><span class="xml"> </span><span class="hljs-comment">{# var won't be escaped #}</span><span class="xml"> </span><span class="hljs-template-variable">{{ var|<span class="hljs-keyword">escape</span> }}</span><span class="xml"> </span><span class="hljs-comment">{# var won't be doubled-escaped #}</span><span class="xml"> </span><span class="hljs-template-tag">{% <span class="hljs-name"><span class="hljs-keyword">endautoescape</span></span> %}</span></code></pre> </div> </div></li> <li><p><em>Sandboxing</em>: Twig can evaluate any template in a sandbox environment where the user has access to a limited set of tags, filters, and object methods defined by the developer. Sandboxing can be enabled globally or locally for just some templates:</p> <div translate="no" data-loc="1" class="notranslate codeblock codeblock-length-sm codeblock-twig"> <div class="codeblock-scroll"> <pre class="codeblock-lines">1</pre> <pre class="codeblock-code"><code><span class="hljs-template-variable">{{ <span class="hljs-name">include</span><span class="hljs-params">('page.html', sandboxed = true)</span> }}</span></code></pre> </div> </div></li> </ul></li> <li><strong>Clean Error Messages</strong>: Whenever you have a syntax problem within a template, Twig outputs a helpful message with the filename and the line number where the problem occurred. It eases the debugging a lot.</li> <li><strong>Fast</strong>: One of the goals of Twig is to be as fast as possible. To achieve the best speed possible, Twig compiles templates down to plain optimized PHP code. The overhead compared to regular PHP code was reduced to the very minimum.</li> </ul> </div> </div> </div> </main> <footer class="ft"> <div class="content"> <div class="theme-switcher" id="theme-switcher"> <button data-tooltip="Light theme" data-theme="light"> <svg class="sun-icon" viewBox="0 0 24 24"> <path d="M12 6a1 1 0 0 0 1-1V3a1 1 0 0 0-2 0v2a1 1 0 0 0 1 1m9 5h-2a1 1 0 0 0 0 2h2a1 1 0 0 0 0-2M6 12a1 1 0 0 0-1-1H3a1 1 0 0 0 0 2h2a1 1 0 0 0 1-1m.2-7a1 1 0 0 0-1.4 1.5l1.5 1.4A1 1 0 0 0 7 8a1 1 0 0 0 .7-.3 1 1 0 0 0 0-1.4ZM17 8.1a1 1 0 0 0 .7-.2L19 6.5A1 1 0 0 0 17.8 5l-1.5 1.4a1 1 0 0 0 0 1.4 1 1 0 0 0 .7.3M12 18a1 1 0 0 0-1 1v2a1 1 0 0 0 2 0v-2a1 1 0 0 0-1-1m5.7-1.9a1 1 0 0 0-1.4 1.5l1.5 1.4a1 1 0 0 0 .7.3 1 1 0 0 0 .7-.3 1 1 0 0 0 0-1.4Zm-11.4 0-1.5 1.4a1 1 0 0 0 0 1.5 1 1 0 0 0 .8.3 1 1 0 0 0 .6-.3l1.5-1.4a1 1 0 0 0-1.4-1.4ZM12 8a4 4 0 1 0 4 4 4 4 0 0 0-4-4" /> </svg> </button> <button data-tooltip="OS System" data-theme="system"> <svg class="system-icon" viewBox="0 0 24 24"> <path d="M17 3.34A10 10 0 1 1 2 12l.005-.324A10 10 0 0 1 17 3.34M8 5.072A8 8 0 0 0 12.001 20L12 4a8 8 0 0 0-4 1.072" /> </svg> </button> <button data-tooltip="Dark theme" data-theme="dark"> <svg class="moon-icon" viewBox="0 0 512 512"> <path d="M283.2 512c79 0 151-36 198.9-94.8a12 12 0 0 0-11.6-19.3A200.6 200.6 0 0 1 333.7 26.5 12 12 0 0 0 330 4.3 258 258 0 0 0 283.2 0a256 256 0 1 0 0 512" /> </svg> </button> <span class="switch-handle"></span> </div> <p> Website powered by Symfony and Twig, deployed on <a href="https://symfony.com/cloud" title="Platform.sh"> <img class="sc" src="/images/platformsh.svg" alt="Platform.sh" height="180" width="772" loading="lazy" /> </a> </p> <p> The <a href="/images/twig-logo.png" title="Twig Logo">Twig logo</a> is &copy; 2010-2025 <a href="https://symfony.com/" title="Symfony">Symfony</a> </p> </div> </footer> <div id="sln"></div> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10