Paint the Web - a micro-Blog in .md about Dev, Web and more

View and Templates in Flood\Canal

Flood\Canal uses Twig as main template language. Content is defined as Twig enabled MarkDown, you could use Twig variables inside the .md content files.

How to install Canal:

composer create-project flood/canal-structure . -s DEV

Pre-installed in Canal, the component's template files could also be installed with:

composer require flood/canal-view

Turn on debug function for twig with setting $option['debug'] = truein config.php of Canal

Usage with Canal

This will explain and demonstrate how the view files are controlled with Canal and where you find what.

The project flood/canal-view just contains default template files. We will use those, but you could of cause build your own stack.

The logic is in flood/canal, the configuration is done in config.php of flood/canal-structure

Translating to folder structure:

All files of flood/canal-structure are located after installation in:


Where composer installs flood/canal-view in


See also the default asset file structure.

Default Folders

This controls where Twig will look after files, use absolute paths. Twig has a fallback logic, it will always look from the first folder down and executes the first existing file found. Only when namespaces are applied this don't work, don't apply namespaces on the default/first entry. The content namespace is for content files that have twig enabled MarkDown, this namespace should not be used within other templates.

See also the default content folder.

$frontend->path_view = [
    getcwd() . '/view/',
    getcwd() . '/vendor/flood/canal-view/src',
    $frontend->content->path => 'content',
  • the first one must be the default folder for your files
  • when no key is defined, value will be used as namespace for that folder {% extends '@namespace/default.twig' %} evaluates to /some-dir/folder
  • for usage of flood/canal-view logic, just copy the example above.

Entry Point

For the ease of this guide we will use the route/controller.response variant that is as example already in _route.php.

You could set the template file from:

  • all classes that extend \Flood\Canal\Controller\Base
    • through parameter of response($tpl), overwrites property, executes render($tpl)
    • through parameter of render($tpl), overwrites property
    • through property $this->path_template

In _route.php this is the part I refer to:

    'about' => [
        'path' => '/about',
        'controller' => function ($frontend) {
            $controller = new \Flood\Canal\Controller\Base($frontend);
            return $controller->response('_meta.twig');

The _meta file, is in /view/_meta.twig, this file only extends canal-view's default_content_plain.twig, which is /vendor/flood/canal-view/src/default_content_plain.twig.

In /vendor/flood/canal-view/src/ are multiple default_* files, these are used to provide a simple way of deciding which layout is needed.

  • default.twig: provides the main blocks and defines a few block basics, all other default_* files are extending this file
  • default_content.twig: full-width content layout, removes sidebars
  • default_content_plain.twig: full-width content layout, removes sidebars, header, footer and other default blocks that are not content related
  • default_sidebar_both.twig: layout with two sidebars and content
  • default_sidebar_left.twig: layout the left sidebar and content
  • default_sidebar_right.twig: layout the right sidebar and content

This is done by overriding the main base.twig blocks with empty blocks.

Until now, no main structure or anything exists. The structure is build in canal-view's general/base.twig. This has the main html markup, more is included through overwriting the blocks/creating block files.

In the default_ files the used blocks are including twig files. Only create those you use, e.g. for block content_begin add content-begin.twig as /view/block/content-begin.twig. It will now automatically be displayed in the block.

default_content.twig excerpt:

{% block content_begin %}
    {% include 'block/content-begin.twig' ignore missing %}
{% endblock %}

The Canal view files aren't using namespaces in extends/include, giving you the possibility to simply overwrite them, even the base.twig, just add a file with the same relative path in your view folder and this will be used.


Blocks are defined in a way that most changes only require to add one or two blocks in the page template or adding a block file at all. They are completely nested and provide default contents and logic for the basic needed things most pages need. Some blocks are just designed to get content, if the implementation needs them. So no extra block or complex changes are needed, those blocks listed below as empty, user.


The head provides different blocks for those parts which often need to be changed. They in complete are in the block head:

    {% block head %}
        {# more blocks here #}
    {% endblock %}

These blocks are available, in the order they are defined:

  • head_begin empty, user block
  • head_meta defines charset, provides setting of meta keywords and title
  • head_misc empty, user block
  • head_style outputs the link to the css file, uses url.asset and frontend.debug to generate the route to a file named style.css or style.min.css, makes usage of head.font variable
  • head_js empty at base, should contain needed JS file links, there is a foot_js also
  • head_end empty, user block

At the most use cases only head_js need to be used.


The body is surrounded by a block:

{% block body %}
    <body class="body"{% if meta.lang %} lang="{{ meta.lang }}"{% endif %}>
{% endblock %}

And contains a lot of blocks containing blocks, take a look at the reference sheet or look for yourself, below are the most important explained.

Block Reference Sheet:

Image #1

Decorator blocks:

  • body_start: includes block/body-start.twig when exists and is meant for information banner/cookie notice etc.
  • header_inside: includes block/header.twig when exists, is meant for the page header
  • footer_inside: includes block/footer.twig when exists and is used as the page footer
  • footer_copyright: includes block/footer-copyright.twig when exists and is used as the page copyright notice
  • body_end: includes block/body-end.twig when exists and is meant for information banner/cookie notice etc.
  • foot_js: here should be added JS files and scripts which need to be embedded before </body>

Content blocks, they consist of groups of three:

  • sidebar_left_begin: includes block/sidebar-left-begin.twig when exists
  • sidebar_left_inside: includes block/sidebar-left.twig when exists
  • sidebar_left_end: includes block/sidebar-left-end.twig when exists
  • content_begin: includes block/content-begin.twig when exists
  • content_inside: includes block/content.twig when exists
  • content_end: includes block/content-end.twig when exists
  • sidebar_right_begin: includes block/sidebar-right-begin.twig when exists
  • sidebar_right_inside: includes block/sidebar-right.twig when exists
  • sidebar_right_end: includes block/sidebar-right-end.twig when exists

Default values

Defaults that will be set

The base controller sets a few defaults, these are:

  • requestContext: instance of Symfony RequestContext, e.g. {{ requestContext.getHost() }}
  • content: instance of Flood\Canal\Content\Content, provides method for fetching the content and meta information about the current article
  • frontend: instance of Flood\Canal\Frontend, provides the active runtime
  • match: result of the uri matcher, contains the result like which placeholders where set, the callback is also within, with which the controller was build
  • url: array
    • asset: the path to the asset folder, only not blocked folder/file access
    • home: link to the home page, it MUST exist a route home!
    • generator: instance of the UrlGenerator, easily generate with {{ generator.generate('id', {'article': 'value'}) }}, the id is the key of the route in $frontend->route_list, the second paramters will not be needed most times, only when using placeholders/parameters


{{ url.asset }}

will print at default:


All available variables

see the components Canal\View documentation


Fragments are small code parts which are written for a dynamic use, the most need to get parameters.

They should be inserted with:

{% include 'fragment/some-fragment.twig' with {'key': 'val'} %}

See Canal\View: Fragments

PHP explanation

Setting Values

Getting a variable from your controller to the template is easy, just $this->assign('key',$value); and you could access it with {{ key }}.