Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Jade Templating for PHP Developers

4.80/5 (3 votes)
15 Oct 2014CPOL8 min read 32K   242  
Jade templating for PHP developers

Sample Image - maximum width is 600 pixels

Introduction

Jade is a templating engine that is causing quite a stir in the node.js/express community. It makes for well structured and easily maintainable HTML view templates but is not widely used by PHP developers. The main reason is that incorporating PHP snippets in Jade syntax makes for ugly unmaintainable code and kind of defeats the object of using Jade in the first place. I am going to present a development workflow using a simple Jade extension that will allow PHP developers to gain all of the advantages of the Jade syntax with none of the syntactical disadvantages of embedding raw HTML to support PHP.

Background

  • What is Jade?

    Jade is a language that compiles to HTML and it's a great way of separating your application logic from presentation markup. Put simply, Jade is HTML without Tags.

    To whet your appetite, here is an example of a jade template and the equivalent HTML.

    HTML
    doctype html
    html(lang="en")
      head
        meta(charset="utf-8")
        title Jade Example
        meta(name="description" content="")
        meta(name="author" content="")
        //- Mobile Specific Metas
        meta(name="viewport" 
        content="width=device-width, 
        initial-scale=1, maximum-scale=1")
      body
        div
          h1 Jade is Wonderful....
        div
          p.
            Nullam a dolor id arcu semper 
            finibus ut pulvinar orci. Proin
            sodales nisi et dictum pulvinar. 
            Duis orci velit, suscipit et
            porttitor gravida, molestie ac purus. 
            Cum sociis natoque penatibus
            et magnis dis parturient montes, 
            nascetur ridiculus mus. Cras felis
            neque, gravida a blandit ac, 
            rutrum ut sapien. Vivamus tincidunt
            volutpat libero eget tempor. 
            Nam dolor mauris, mollis in euismod
            vitae, viverra ac libero
        div
          p Copyright 2014 www.jade4php.com. 
          All rights reserved.
        //- Scripts
        script(type="text/javascript" 
        src="js/jquery-1.8.0.min.js")
    HTML
    <!DOCTYPE html>
    <html lang="en">
      <head>
          <meta charset="utf-8">
          <title>Jade Example</title>
          <meta name="description" content="">
          <meta name="author" content="">
          <meta name="viewport" 
          content="width=device-width, 
          initial-scale=1, maximum-scale=1">
      </head>
      <body>
          <div>
              <h1>Jade is Wonderful....</h1>
          </div>
          <div>
              <p>
                  Nullam a dolor id arcu semper 
                  finibus ut pulvinar orci. Proin
                  sodales nisi et dictum pulvinar. 
                  Duis orci velit, suscipit et
                  porttitor gravida, molestie ac purus. 
                  Cum sociis natoque penatibus
                  et magnis dis parturient montes, 
                  nascetur ridiculus mus. Cras felis
                  neque, gravida a blandit ac, 
                  rutrum ut sapien. Vivamus tincidunt
                  volutpat libero eget tempor. 
                  Nam dolor mauris, mollis in euismod
                  vitae, viverra ac libero
              </p>
          </div>
          <div>
              <p>Copyright 2014 www.jade4php.com. 
              All rights reserved.</p>
          </div>
          <script type="text/javascript" 
          src="js/jquery-1.8.0.min.js"></script>
      </body>
    </html>

    To find out more about the Jade programming language and how it can change your relationship with HTML, take a look at the Jade Language website or a there is a great tutorial by Dave Auld here on CodeProject Feeling Jaded with Jade? Don't Be!.

  • Reasons to Love Jade

    1. There are no tags

      No more spaghetti HTML code that grows more unmanageable with every resisted change. Jade is elegantly simple. Elements are indented so there is no need for closing tags and because formatting is important for syntax, your code remains easy to read and a joy to maintain no matter how often your boss makes you change it.

    2. Master Templates

      You can create master layouts to organise your website and include different "blocks" of content for individual pages or sections in your site map.

    3. Markdown

      You can easily include markdown syntax in your template file with the built in markdown filter.

    4. Complements Client Side frameworks

      If you use a client side framework such as Angular.js, you will enjoy all the benefits of well structured, maintainable code on both the server and on the client. To quote Dr Pangloss without a hint of satire "Avec Jade tout est pour le mieux dans le meilleur des mondes" which loosely translates as "with Jade all is for the best in this the best of all worlds".

    5. You can learn Jade interactively

      Jade By Example is a great place to explore Jade interactively and try things out.

    6. You can refactor the code

      No more reluctance to touch fragile code for fear it will break. Jade positively invites you to refactor it as you make those pressing last minute changes.

    7. Simplify common code with mixins

      Generate menus, panels and navigation widgets simply and easily with Jade parameterised mixins.

    8. Easily convert existing HTML to Jade

      Got an existing website you are ashamed of? No problem. [Convert HTML to Jade](http://html2jade.aaron-powell.com/) is an online resource you can use to give that tired old website the makeover it deserves.

    9. You can use Jade with PHP

      node/express is a great environment for developing websites but we live in a world of shared hosting and PHP/Mysql. I can't be parted from Jade but I want to be able to use it in my normal workflow. And if I'm honest, I really have an quiet affection for PHP as well as Jade.

    10. Jade is cool

      Quite simply, Jade takes less time to code, takes less lines of code, is much prettier than HTML, is more maintainable and works well with all the other web development tools I use. What's not to love.

Using the Code

  • How can PHP developers use Jade ?

    So far, I have described a code Eutopia and I can tell that you can't wait to integrate it into your PHP developers toolkit. But there is a snag. Using Jade with PHP means introducing some raw HTML to inject PHP logic and variables. For example:

    PHP
    <?php echo htmlspecialchars($foo, ENT_QUOTES, 'UTF-8'); >?

    How ugly is that? But before you throw up your hands and go back to the basement to churn out more evil HTML markup, there is a simple way around the problem.

    Using a jade extension called jade4php you can instead write:

    PHP
    p!= php('$foo')

    Now doesn't that cheer you up? This concise statement will result in the following compiled HTML markup but without the pain. The != simply tells Jade not to escape the paragraph content as it is already escaped with the PHP htmlspecialcharacters function.

    PHP
    <p>
        <?php echo htmlspecialchars($foo, ENT_QUOTES, 'UTF-8'); >
    </p>

    Unlike those other guys sweating for hours in the misery of the HTML gym, the blue jade way is all gain and no pain (I think I'm going to put that slogan on a T-Shirt).

  • Example Project

    1. Download the jade4php example website and unzip it to your project folder. It doesn't really matter where this folder is or what you call it, but I would recommend somewhere in your home folder.

      A live demo of the example project is available at www.jade4php.com including an online source code explorer.

    2. Download and install node.js from nodejs.org. This will also install the Node Package Manager (npm) that you will use to install the jade dependencies for your projects.

    3. Open a terminal window and navigate to the folder where you installed the example website in step (1) and type:

      PHP
      npm install

      This will install the node.js dependencies defined in package.json for your project so that you can run jade using grunt.

      The package.json file:

      PHP
      {
        "name": "jade4php-example",
        "version": "0.0.0",
        "description": "An example jade4php project",
        "homepage": "http://www.jade4php.com",
        "main": "Gruntfile.js",
        "scripts": {
          "test": "echo \"Error: no test specified\" && exit 1"
        },
        "author": {
          "name": "Brian Etherington",
          "email": "brian.etherington@outlook.com",
          "url": "http://www.jade4php.com"
        },
        "repository": {
          "type": "git",
          "url": "git://github.com/BookArt/jade4php-example.git"
        },
        "bugs": {
          "url": "https://github.com/BookArt/jade4php-example/issues"
        },
        "licenses": [
          {
            "type": "MIT",
            "url": "https://github.com/BookArt/jade4php-example/blob/master/LICENSE-MIT"
          }
        ],
        "devDependencies": {
          "grunt": "^0.4.5",
          "grunt-contrib-clean": "^0.6.0",
          "grunt-jade4php": "^1.0.0"
        },
        "private": true
      } 
    4. Install grunt-cli using the node package manager npm (already installed with node in step 2 above):

      PHP
      npm install -g grunt-cli

      You will use grunt to run jade to compile your templates presently. For further information about grunt and what it can do, see gruntjs.com.

      The grunt tasks are defined in Gruntfile.js:

      PHP
      module.exports = function(grunt) {
      
        grunt.initConfig({
          pkg: grunt.file.readJSON('package.json'),
          clean: {
            compile: ['htdocs/templates/**/*.phtml'],
          },
          jade4php: {
            compile: {
              options: {
                pretty: true
              },
              expand: true,
              cwd: 'jade',
              src: ['**/*.jade', '!_**/*.jade', '!layout/*.jade', '!mixins/*.jade', '!includes/*.jade'],
              dest: 'htdocs/templates/',
              ext: '.phtml'
            }
          }
        });
      
        grunt.loadNpmTasks('grunt-contrib-clean');
        grunt.loadNpmTasks('grunt-jade4php');
      
        grunt.registerTask('default', ['clean','jade4php']);
      
      };  
    5. In the terminal window, type grunt to run the default task:

      PHP
      grunt
      Running "clean:compile" (clean) task
      >> 8 paths cleaned.
      
      Running "jade4php:compile" (jade4php) task
      File htdocs/templates/amazium.phtml created.
      File htdocs/templates/conditional.phtml created.
      File htdocs/templates/forms.phtml created.
      File htdocs/templates/intro.phtml created.
      File htdocs/templates/menu.phtml created.
      File htdocs/templates/paras.phtml created.
      File htdocs/templates/setup.phtml created.
      File htdocs/templates/tables.phtml created.
      
      Done, without errors.

      What just happened ?

      The templates in jade4php_example/jade folder were compiled as .phtml files to the jade4php_example/htdocs/templates folder.

      Have a look at the jade templates and the equivalent .phtml files to see what has been generated.

    6. If you do not already have one, you will need a Web Server with support for PHP.

      If you want to get up and running quickly, you can use the development web server built into PHP. Download and install PHP from php.net/downloads.php.

      Full instructions for configuration and installation can be found at php.net/manual/en/install.php.

      You will be using the Command Line PHP so make sure the path to the PHP executable is in your PATH environment if you are using Microsoft Windows.

      Open a second terminal window, navigate to the jade4php projects folder and type...

      PHP
      cd htdocs
      php -S localhost:8000

      This will start a web server on port 8000 with the document root set to your project's htdocs folder. In a browser, type:

      PHP
      localhost:8000/phpinfo.php

      This should display information about the installed version of PHP. If you receive an error, go back and check your installation and configuration of PHP.

      If you have successfully installed PHP, then in your browser you can now type:

      PHP
      localhost:8000/index.php

      This will display the home page of the example website..

      Alternatively, PHP support can be added to a number of web servers (IIS, Xitami, and so on), but most commonly Apache HTTP Server is used. Go to httpd.apache.org/docs/current/install.html for information on how to install and configure Apache.

    7. Find the jade folder in your jade4php project folder and edit intro.jade to change some text and save the edited file. In the first terminal window, type grunt to update the changed templates.

      PHP
      grunt
      Running "clean:compile" (clean) task
      >> 8 paths cleaned.
      
      Running "jade4php:compile" (jade4php) task
      File htdocs/templates/amazium.phtml created.
      File htdocs/templates/conditional.phtml created.
      File htdocs/templates/forms.phtml created.
      File htdocs/templates/intro.phtml created.
      File htdocs/templates/menu.phtml created.
      File htdocs/templates/paras.phtml created.
      File htdocs/templates/setup.phtml created.
      File htdocs/templates/tables.phtml created.
      
      Done, without errors.

      As before, the jade templates have been compiled to your htdocs/templates folder.

    8. Refresh your browser to see the changes.

    9. The Template Class

      The job of managing template variables and displaying the HTML code is delegated to Template.class.php.

      This code is based upon original code by Brian Lozier and has been greatly simplified by me for the purpose of managing the .phtml templates generated by Jade.

      I am grateful to Brian for his article Beyond The Template Engine. At the time I first read the article, I leaned more towards a more feature rich template engine (Smarty) than the vanilla PHP he proposed. But with the advent of Jade, I think that Brian's ideas about PHP templating fit the bill perfectly.

      PHP
      <?php
      
      /**
       * A simple template class
       *
       * Based upon original code by:
       *
       * Copyright (c) 2003 Brian E. Lozier (brian@massassi.net)
       *
       * Permission is hereby granted, free of charge, to any person obtaining a copy
       * of this software and associated documentation files (the "Software"), to
       * deal in the Software without restriction, including without limitation the
       * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
       * sell copies of the Software, and to permit persons to whom the Software is
       * furnished to do so, subject to the following conditions:
       *
       * The above copyright notice and this permission notice shall be included in
       * all copies or substantial portions of the Software.
       *
       * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
       * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
       * IN THE SOFTWARE.
       */
      
      class Template {
      
          private $vars = []; // Holds all the template variables
      
          /**
           * Set a template variable.
           */
          public function assign($name, $value) {
              $this->vars[$name] = $value;
          }
      
          /**
           * Open, parse, and return the template file.
           *
           * @param $file string the template file name
           */
          public function fetch($file) {
              extract($this->vars);          // Extract the vars to local namespace
              ob_start();                    // Start output buffering
              include($file);                // Include the file
              $contents = ob_get_contents(); // Get the contents of the buffer
              ob_end_clean();                // End buffering and discard
              return $contents;              // Return the contents
          }
      
          public function display($file) {
              echo $this->fetch($file);
          }
      } 
    10. Using the template class with /tables.php:

      PHP
      <?php
      include "lib/Template.class.php";
      $template = new Template();
      
      $table = [
        ['id' => 1, 'first_name' => 'Bruce', 'last_name' => 'Wayne', 'location' => 'Gotham City'],
        ['id' => 2, 'first_name' => 'Clarke', 'last_name' => 'Kent', 'location' => 'Metropilis'],
        ['id' => 3, 'first_name' => 'Oliver', 'last_name' => 'Queen', 'location' => 'Star City'],
        ['id' => 4, 'first_name' => 'Diana', 'last_name' => 'Prince', 'location' => 'Themyscira']
      ];
      
      $template->assign('table', $table);
      $template->display('templates/tables.phtml');
    11. The corresponding jade code in jade/tables.jade...

      PHP
      This is an example of a table generated in PHP on the server. 
      table
        thead
          tr
            th(scope='col') #ID:
            th(scope='col') First Name:
            th(scope='col') Last Name:
            th(scope='col') Location:
        tbody.striped
          //----------------------------------------------
          //- Assign php row expressions to jade variables
          - id         = '#'+php("$row['id']")
          - first_name = php("$row['first_name']")
          - last_name  = php("$row['last_name']")
          - location   = php("$row['location']")
          //----------------------------------------------
          :php foreach($table as $row):
          tr
            td!= id
            td!= first_name
            td!= last_name
            td!= location
          :php endforeach;
  • Workflow

    Including jade in your web workflow is easy. First separate out the application logic from the view by incorporating a template class, like the one you will find in the example project lib folder, and assign data variables to template variables. Then when everything is set up, make a call on the template class to output the compiled template to the browser.

    Keep a separate folder for your jade templates and use grunt to run the jade compiler to generate the .phtml files you need for the PHP template class.

    You probably have your own ideas about how projects should be organised and jade4php is flexible enough to allow you to use your preferred folder structure. If you want to do a lot of database work, it would be a good idea to consider moving also to a model-view-controller pattern to gain even further benefits from function separation. But that I think is for another article and another day....

History

  • 13th October, 2014: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)