Developer Blog

  • Blog
  • /
  • The new PHPixie templating library
By Dracony on 25 March 2015

The new Templating library is out now, introducing a lot of new features. If you just want to try it out and get your hands dirty just do this:

1
2
3
4
5
6
7
8
git clone https://github.com/phpixie/template
cd template/examples

#install composer if you don't have it yet
curl -sS https://getcomposer.org/installer | php

php composer.phar install
php quickstart.php

PHPixie Template still uses PHP as templating language, but now it can also handle template inheritance and custom formats. It’s super easy to use it to parse HAML, Markdown or whatever else you like. All you need to do is provide a compiler that will translate your format into a plain PHP template, the library will take care of caching the result, updating it when the files are modiefied etc. by itself.

So let’s try integrating it with Markdown, we’ll use mthaml/mthaml for that:

1
2
3
4
5
6
7
8
//composer.json
{
    "require": {
        "phpixie/template": "3.*@dev",
        "phpixie/slice": "3.*@dev",
        "mthaml/mthaml": "1.7.0"
    }
}

And here is our compiler:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class HamlFormat implements \PHPixie\Template\Formats\Format
{
    protected $mtHaml;

    public function __construct()
    {
        $this->mtHaml = new \MtHaml\Environment('php');
    }

    public function handledExtensions()
    {
        return array('haml'); // register which file extension we handle
    }

    public function compile($file)
    {
        $contents = file_get_contents($file);
        return $this->mtHaml->compileString($contents, $file);
    }
}

And now let’s inject it into Template:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$slice = new \PHPixie\Slice();

$config = $slice->arrayData(array(
    'resolver' => array(
        'locator' => array(
            //template directory
            'directory' => __DIR__.'/templates/',
            'defaultExtension' => 'haml',
        )
    ),
    'compiler' => array(
        'cacheDirectory' => > __DIR__.'/cache/',
    )
));

$template = new \PHPixie\Template($slice, $config, array(), array(
    new HamlCompiler()
));

That’s it, we can now use HAML for our templates while retaining all the original features like Extensions and inheritance.

Inheritance
It’s pretty inuitive to understand template inheritance, especially if you used Twig or even Smarty. Here is a quick example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--layout.php-->
<html>
    <title>
        <?php $this->block('title'); ?>
    </title>
    <body>
        <?php $this->childContent(); ?>

    </body>
</html>
``````php?start_inline=1
<!--fairy.php-->
<?php $this->layout('layout'); ?>
<?php $this->startBlock('title'); ?>
Fairy page
<?php $this->endBlock(); ?>

<h2>Hello <?php $_($name); ?></h2>

This will result in:

1
2
3
4
5
6
<?php $this->layout('layout'); ?>
<?php $this->startBlock('title'); ?>
Fairy page
<?php $this->endBlock(); ?>

<h2>Hello <?php $_($name); ?></h2>

Of course it’s always possible to continue using include like in the previous version of PHPixie:

1
include $this->resolve('fairy');

Template name resolution
Usually templating libraries have some way of providing fallback tempates, that are used if the template you wan’t to use does not exist. And usually they handle it via some naming convention. PHPixie alows you to fine tune name resolutiion using 3 locator types:

  • Directory – Maps template name to a folder location, simplest one
  • Group – allows you to specify an array of locators. The template will be searched in those locators one by one until it’s found. This is used for providing fallbacks
  • Prefix – allows you to route the resolution based on a prefix

This sounds more complex then it actually is, so let’s look at an example, assume the following config:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$config = $slice->arrayData([
    'resolver' => [
        'locator' => [
            'type' => 'prefix',
            'locators' => [

                'Site' => [
                    'directory' => __DIR__.'/site/',
                ],

                'Theme' => [
                    'type' => 'group',
                    'locators' => [
                        [
                            'directory' => __DIR__.'/templates/',
                        ],

                        [
                            'directory' => __DIR__.'/fallback/',
                        ],
                    ] 
                ]
            ]
        ]
    ]
]);

It means that Site::layout template will be searched for in the site/ folder, while the Theme::home one will be searched for in templates/ and fallback/.

Extensions

Extensions provide additional methods that you may use inside your views, they are helpful for things like formatting and escaping. As an example let’s look at the HTML extension:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class HTML implements \PHPixie\Template\Extensions\Extension
{
    public function name()
    {
        return 'html';
    }

    //Methods we would like to expose
    public function methods()
    {
        return array('escape', 'output');
    }

    //Also we can assign aliases to some methods, meaning that they will also
    //be assigned to a specified local variable
    //In this case it allows us to use $_($name) instead of $this->output($name)
    public function aliases()
    {
        return array(
            '_' => 'output'
        );
    }

    public function escape($string)
    {
        return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
    }

    public function output($string)
    {
        echo $this->escape($string);
    }
}

Your Extensions then have to be injected in the library constructor just like Formats.

I don’t know any other templating library that allows you so much flexibility in regards to formats and name resolution, so I hope you like what you see here =)

comments powered by Disqus