Disco uses twig by sensio labs as its templating engine.

The template service extends a \Twig_Environment class and provides a few helper functions on top of twigs native functions.

The template service depends on configuration settings set in app/config/config.php and app/config/twig.php.

Where do we store templates?

Templates are stored in app/template/ by default as defined by the configuration setting TEMPLATE_PATH and can use any naming convention you like.

Specifying a default template extension

It's redundant to have to declare the templates extension every time you render one, ie .html after every template name.

Use the configuration setting TEMPLATE_EXTENSION to specify your default template extension (default is `.html`). Its still safe to include the extension in the template path, as it wont be appended to the path if the path already ends in the set extension.

Basic Examples #

// Render a template
$html = Template::render('your-template.html', ['user_name' => 'Johnny!']);

// Add a template onto the Views html stack

// Check if a template exists
$exists = Template::isTemplate('dir/path/template');

Twig Extension #

Disco adds a Twig Extension by default to Twig to give you some added functionality within your twig templates.


{% if App.with('Session').hasFlash('error') %}
    {% set error = App.with('Session').getFlash('error') %}
{% endif %}

{% do View.title('Our page title!') %}

{% if Request.url == '/about-us' %}
{% endif %}


  • call - Call any native PHP function, can really come in handy so you don't have to provide your own bridge between twig and what PHP offers in its native library. The first parameter is the function name you want to call and every parameter after that is passed to the function as a parameter.
{{ call('strtolower', 'THIS WILL BECOME LOWER CASE') }}

{% set stringPieces = call('explode', ' ', 'Convert this string to an array of strings') %}

{{ call('round', 3.145798, 2) }}


  • style - Add a css style to the head of the view/page.
  • script - Add js to the view/page.
  • cache - Cache a block of content for a set period of time (default is 10 minutes). Cache parameters:
    • key - The key to cache the content with, changing the key will automatically force the cache to be cleared and reset on the next template load. If you don't provide a key the key will be determined by performing a hash on the content of the cache tag. This means that if you change the markup or logic inside the cache tag when no key is set, the cache will automatically be cleared and reset on the next template load.
    • for - How long the the content should be cached for. Specify a DateTime modified string like +10 minutes, +2 weeks, +3 hours.
    • until - (mutually exclusive with for) When the content should be cached until as a DateTime format like 2016-03-17.
    • if - A condition which must be true for the caching to be performed.
    • unless - (mutually exclusive with if) A condition which must be false for the caching to be performed.    
  • page - Paginate a Model or LookUp.
{% style %}
    body {
        background-color: {{ bgColor }};
{% endstyle %}

{% script %}
    console.warn('WHAT ARE YOU DOING!');
{% endscript %}

{% cache %}
    {% set recentTweets = App.with('Twitter').latestTweets(5) %}
    {% for tweet in recentTweets %}
        {{ App.with('Twitter').formatTweet(tweet) }}
    {% endfor %}
{% endcache %}

{% cache key 'tweets' for '+12 hours' %}
    {# cache the tweet logic for 12 hours #}
{% endcache %}

{% cache key 'tweets' for '+1 day' unless App.config('devMode') %}
    {# cache the tweet logic for 1 day unless were runnin in devmode #}
{% cache %}

{% page App.with('\App\model\User').select('name').order('name').limit(10) as users %}

    {% for user in users %}
        {# output user markup #}
    {% endfor %}

    {{ page.getEasyMarkup() }}

{% endpage %}