PHP
Article
By Lukas White

Introduction to JadePHP

By Lukas White
Help us help you! You'll get a... FREE 6-Month Subscription to SitePoint Premium Plus you'll go in the draw to WIN a new Macbook SitePoint 2017 Survey Yes, let's Do this It only takes 5 min

There are dozens of templating engines out there, with options such as Smarty, Twig (used in the upcoming version of Drupal) and Blade (the default for Laravel) among the best known – as well as vanilla PHP, of course. Stepping away from PHP specifically, eRuby / ERB and Haml for Ruby / Ruby on Rails, and Javascript has scores of popular choices including Mustache, Handlebars, Hogan and EJS. Some have subtly different syntax, some more markedly so.

One which differs quite significantly from most is Jade, an engine usually associated with Javascript applications – it’s supported out-of-the-box by Express for Node.js, for example. It’s Jade I’m going to look at in this article; or more specifically the PHP port JadePHP.

Haml and Jade

It would be remiss to talk about Jade without mentioning Haml, from which Jade takes its inspiration – and indeed there are several libraries for using Haml with PHP. Jade shares its overall philosophy, which is to make templating “beautiful” and use what the authors describe as templating “haiku”. Whatever that actually means, there’s no denying Haml and Jade do share some characteristics which make them fundamentally different to most templating languages.

What’s the Difference?

Most templating engines involve writing the target markup and “injecting” it with placeholders and / or basic logic – a superset, in a sense. Jade still has placeholders and logic, but also provides a shorthand for writing XML-like elements. Generally that means HTML, although you can also use it for things like RSS as well as XML itself.

In fact if you wanted to, you could just use Jade as a shorthand for HTML without taking advantage of its more “traditional” templating features.

How to use the Repository

Rather frustratingly, the code is not currently available via Composer – although it should be a simple enough task to package it up, if anyone has an hour or two. You can get it to to work, however, by cloning the repository and include‘ing or require‘ing the included autoload.php.dist (the Github repository includes Symfony’s UniversalClassLoader).

Here’s an example, adapted from the one in the project’s README, which assumes that the repository has been downloaded into a directory called jade:

require('./jade/autoload.php.dist');

use Everzet\Jade\Dumper\PHPDumper,
        Everzet\Jade\Visitor\AutotagsVisitor,
        Everzet\Jade\Filter\JavaScriptFilter,
        Everzet\Jade\Filter\CDATAFilter,
        Everzet\Jade\Filter\PHPFilter,
        Everzet\Jade\Filter\CSSFilter,
        Everzet\Jade\Parser,
        Everzet\Jade\Lexer\Lexer,
        Everzet\Jade\Jade;

$dumper = new PHPDumper();
$dumper->registerVisitor('tag', new AutotagsVisitor());
$dumper->registerFilter('javascript', new JavaScriptFilter());
$dumper->registerFilter('cdata', new CDATAFilter());
$dumper->registerFilter('php', new PHPFilter());
$dumper->registerFilter('style', new CSSFilter());

// Initialize parser & Jade
$parser = new Parser(new Lexer());
$jade   = new Jade($parser, $dumper);

$template = __DIR__ . '/template.jade';

// Parse a template (both string & file containers)
echo $jade->render($template);

This will compile the file template.jade and echo its contents.

Where you actually use this depends on your workflow, whether you’re using a framework, and so on. You could, perhaps, use a service such as Watchman, Guard or Resource Watcher to watch the filesystem for changes to your Jade templates, and compile them at the appropriate time during the development process.

A simple example

Let’s look at a simple example, which shows a complete – if basic – HTML page, with only two variables and no logic (yet!)

!!! 5
html(lang="en-us")

    meta(charset="utf-8")
    meta(http-equiv="X-UA-Compatible", content="IE=Edge;chrome=1")

    title(dir="ltr")= pageTitle

    meta(name="viewport", content="width=device-width, initial-scale=1.0")

    link(rel="stylesheet", media="screen", href="/css/styles.css")

    body
    header
    h1 My Jade Application
    div#content
    div.inner
        =$bodyContent

    script(data-main="js/main.js", src="js/libs/require.js")

Important: you’ll need to use two spaces to indent. This is the only method currently understood by Jade PHP, and using something different will cause errors or invalid markup.

Straight away, it will be apparent that Jade looks rather different to the HTML you’re accustomed to. No angled brackets and no closing tags, for starters. Nor are there curly brackets, double curly brackets, or any of the common approaches to marking up variables to be injected into the template. (That said, you can use the double curly bracket syntax, but it’s not a part of Jade, per se.)

What it does show is a very concise method of generating markup. Let’s look at the resulting HTML:

<!DOCTYPE html>
<html lang="en-us">
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=Edge;chrome=1" />
    <title dir="ltr"><?php echo pageTitle ?></title>
    <meta name="viewport" content="width=device-width" initial-scale="1.0" />
    <link rel="stylesheet" media="screen" href="/css/styles.css" />
    <body>
        <header>
            <h1>My Jade Application</h1>
        </header>
        <div id="content">
            <div class="inner">
                <?php echo $bodyContent ?>
            </div>
        </div>
        <script data-main="js/main.js" src="js/libs/require.js"></script>
    </body>
</html>

Let’s go through the key lines in the Jade template, to get an idea of how the shorthand for HTML works.

!!! 5 is shorthand for the HTML5 doctype. It’s the only place you’ll see that triple exclamation mark syntax. You can also use !!! xml to get <?xml version="1.0" encoding="utf-8" ?>, for transitional you can use !!! transitional to get <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> or the default !!! default gives you <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">.

NOTE; in the latest Javascript-flavoured version of Jade, the !!! 5 declaration has been replaced with doctype html; it’s possible – though perhaps unlikely, looking at the Github repo’s lack of activity – that JadePHP will follow suit.

An HTML tag is specified by its name alone, with no need to close it; for example:

body
  header

…would, if you stopped there, result in:

<body>
    <header></header>
</body>

Note how the structure of the document is represented using indentation.

You can put a tag’s content after its name, with a space between them:

h1 My Jade Application

…becomes:

<h1>My Jade Application</h1>

If you want to split large blocks of content into multiple lines, use the pipe “|” character:

p 
  | Curabitur blandit tempus porttitor. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. 
  | Aenean eu leo quam. 
  | Pellentesque ornare sem lacinia quam venenatis vestibulum.

This compiles to:

<p>Curabitur blandit tempus porttitor. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>

You can use a format similar to CSS selectors to add IDs and classes to HTML elements:

div#content
  div.inner

…results in:

<div id="content">
    <div class="inner">

Other attributes such as src, href, lang, media etc can be specified using parenthesis:

html(lang="en-us") === <html lang="en-us">

link(rel="stylesheet", media="screen", href="/css/styles.css") === <link rel="stylesheet" media="screen" href="/css/styles.css" />

An equals sign is used for variable substitution. As you can see above, when you compile a Jade template it converts something like this:

= $pageTitle

…into the following:

<?php echo $pageTitle ?>
--ADVERTISEMENT--

Adding some Logic

You can use a dash to inject basic conditional logic. Here’s a concrete example:

header
    h1= $pageTitle
    - if ($loggedIn):
    p.greeting Welcome back!
    - else:
    a(href="/login") Please login
    - endif;

When you compile the template, this will result in the following:

<header>
    <h1><?php echo $pageTitle ?></h1>
    <?php if ($loggedIn) ?>
    <p class="greeting">Welcome back!</p>
    <?php else ?>
    <a href="/login">Please login</a>
    <?php endif ?>
</header>

Iteration follows very similar lines:

ul
  - foreach ($items as $item):
  li= $item

Filters

You can use filters to take a block of text and process it in some way, for example:

:php
    | $value = 10;
    | $computed_value += 100;
    | print $computed_value;

…will evaluate to:

<?php
    $value = 10;
    $computed_value += 100;
    print $computed_value;
?>

Perhaps more useful are the javascript and CSS filters, for example:

:style
| body {
|   background: yellow;
| }

…will evaluate to:

<style type="text/css">
body {
  background: yellow;
}

You set up these filters as follows (see the example code above for the context of these declarations):

$dumper->registerFilter('javascript', new JavaScriptFilter()); 
$dumper->registerFilter('php', new PHPFilter());
$dumper->registerFilter('style', new CSSFilter());

The first argument corresponds to the text you use to “mark up” the text in your templates, which is prefixed with a colon; so in the example above you could use :javascript, :php and :style respectively.

By implementing Everzet\Jade\Filter\FilterInterface, you can even define your own filters.

Why use Jade?

Arguments about which templating language to use are ultimately pretty futile. Whilst you can come up with certain benchmarks about which perform better than others in certain circumstances, which ones are specifically designed for certain environments – like client vs server-side, at the end of the day the choice is often a very personal one which comes down to what you feel comfortable scripting in. I have no intention of trying to fan those flames, any more than I wish to get involved in arguments over which is “the best” programming language.

Jade’s shorthand approach won’t be for everyone. There are some who will argue that it’s easier to read, and some who will vehemently disagree. If, however, it’s an approach that you see the merit in then that’s a compelling reason to choose it.

Another reason you might decide to use Jade – apropos of a number of templating options – is if you alternate between technologies. If you often switch between, say, Node.js and PHP development then there’s some logic in keeping things consistent. Why master one engine then use something else entirely, if it’s available for multiple languages?

Summary

In this article I’ve looked at JadePHP, a port of the primarily Javascript-focussed templating engine, Jade. I’ve given you a few pointers on how to use it and some ideas about why you might want to use it. Are you going to give it a try, or does it seem unnecessarily terse to you? Do let me know what you think of it in the comments.

Login or Create Account to Comment
Login Create Account
Recommended
Sponsors
Get the most important and interesting stories in tech. Straight to your inbox, daily.Is it good?