Sharing Templates Between PHP and JavaScript

Share this article

Templating in web applications is crucial for separating your business logic from your presentation. There are two types of templates: server-side templates, which are used through a server-side templating engine during the initial page load, and client-side templates, which are used for working with JavaScript-based applications or Ajax requests. In scenarios where your web application depends heavily on Ajax, it can be difficult to maintain both server-side and client-side templates without duplication. Hence it can be useful to choose a templating engine which provides both client- and server-side support which allows maximum reusability. Mustache is quickly becoming one of the more popular templating engines among those available, and provides implementations for different programming languages and platforms to cater to our needs. In my article Creating HTML Templates with Mustache.js
on JSPro, I showed you how to work with Mustache templates in client-side code. If you don’t have any previous experience working with Mustache, I recommend reading it. In this article I’ll focus on creating server-side Mustache templates and sharing the same set of templates with client-side JavaScript.

Introduction to Mustache.php

The Mustache implementation in PHP is named Mustache.php, and you can grab a copy of the library using from the official GitHub project page. However, if you are familiar with using Composer, I recommend you to install Mustache using that for better dependency management (and if you’re not familiar with Composer, I recommend you read PHP Dependency Management with Composer). Add the following to your composer.json file and run either composer install or composer update (whichever is appropriate):
{
    "require": {
        "mustache/mustache": "2.0.*"
    }
}
Let’s start by looking at a simple example for doing templating with Mustache.php.
<?php
require 'vendor/autoload.php';

$tpl = new Mustache_Engine();
echo $tpl->render('Hello, {{planet}}!', array('planet' => 'World'));
First the Composer autoloader is included (alternatively you can use Mustache’s autoloader if you are working with a cloned or downloaded copy of the library). Then the render() method of the Mustache_Engine
class is called to generate the view by passing it the template data and some replacement values. Ideally you wouldn’t provide the template contents inline like the example does. Templates should be kept in their own files in a dedicated directory. You can configure the path to the template files when creating an instance of the Mustache_Engine class.
<?php
$mustache = new Mustache_Engine(array(
   'loader' => new Mustache_Loader_FilesystemLoader('../templates')
));

$tpl = $mustache->loadTemplate('greeting');

echo $tpl->render(array('planet' => 'World'));
loader in the configuration array defines the path to the template files (more details on the configuration parameters can be found in the Mustache.php Wiki). In this scenario, template files are located inside the templates directory. The loadTemplate() method loads the file templates/greeting.mustache. Having briefly covered the necessary theory for working with Mustache, we can now look at how to share the templates.

Sharing Templates between PHP and JavaScript

Our main goal is to share the templates between PHP (server-side) and JavaScript (client-side). For the basis of our example, let’s assume we have an e-commerce site with two product categories: Books and Movies. When the user first visits, all of the products will be displayed in a single list as shown below.

You can see that the details of each product type are different; hence we need separate templates for the two categories. Create two templates, one called books.mustache and another movies.mustache. This is how the books.mustache
file will look like:
{{#products}}
{{#book}}
<div>
<p>Book Title: {{title}}</p>
<p>Book Author: {{author}}</p>
<p>Book Price: {{price}}</p>
</div>
{{/book}}
{{/products}}
The above is a simple template with a section for looping purposes and some template-specific variables. {{#products}} is used to loop through all of the elements inside the products section of the array we will provide. {{#book}} is used to check if the item is actually a book. If the book key doesn’t exist, then nothing will be displayed to the user. On the initial page load, all of the products need to be retrieved and displayed to the user, so we use PHP to generate the initial display using both the template and the data set.
<?php
$books = array();
$result = $db->query('SELECT title, author, price FROM books');
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
    $row['book'] = true;
    $books[] = $row;    
}
$result->closeCursor();

$movies = array();
$result = $db->query('SELECT name, price, cast FROM movies');
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
   $row['movie'] = true;
   $movies[] = $row;    
}

$booksTmpl = $this->mustache->loadTemplate('books');
$moviesTmpl = $this->mustache->loadTemplate('movies');

$data = array(
    'products' => array_merge($books, $movies)
);
$html = $booksTmpl->render($data);
$html .= $moviesTmpl->render($data);

echo $html;
We use two database queries to pull the book and movie data from the database and save it into an associative array for passing into the templates . I’ve used basic PDO methods for pulling the data; you can use your own database abstraction layer or ORM if you like. The templates for books and movies are loaded separately into two variables using the loadTemplate() method, and I pass the products array to each template’s render() method. It applies the template to the product data and returns the HTML output. To filter the results based on product type, we could get all the filtered books (or movies) as rendered HTML from the server, but all of the markup would incur additional overhead for each request. We really don’t want to have to send the same markup over and over again. This is where the client-side templates come into play – we can keep the necessary templates loaded into memory on the client and only load the data from the server using Ajax. To make the templates available to the client, they can be injected in the initial page request in <script> tags for future use by JavaScript. The code inside these tags will not be displayed, nor will they be executed by JavaScript if we set the type to text/mustache.
<script id="booksTmpl" type="text/mustache">
<?php
echo file_get_contents(dirname(__FILE__) . '/templates/books.mustache');
?>
</script>
<script id="moviesTmpl" type="text/mustache">
<?php
echo file_get_contents(dirname(__FILE__) . '/templates/movies.mustache');?>
</script>
In order to use these templates in JavaScript, we just need to include the Mustache.js library in the document. You can grab a copy of mustache.js file from its GitHub page
and include it in your HTML as following:
<script type="text/javascript" src="mustache.js"></script>
Once the user selects the filter option, we can get the data using an Ajax request. But unlike the initial page load, we won’t apply the templates to the data before sending them to the client since we have the templates available client-side already.
<script>
$("#booksFilter").click(function () {
   $.ajax({
       type: "GET",
       url: "ajax.php?type=books"
   }).done(function (msg) {
       var template = $("#booksTmpl").html();
       var output = Mustache.render(template, msg);
       $("#products").html(output);
   });
});
</script>
The book list is retrieved from the database and returned in JSON format to the client, and then we fetch the book template from within its script tag using $("#booksTmpl").html() and pass both the template and data to the client-side Mustache rendering function. The generated output is then applied back to a products section on the page.

Summary

Working with separate template engines both client-side and server-side can be a difficult task and can lead to template duplication. Luckily, various implementations of Mustache allow us to share the same templates between both sides. This increases the maintainability of your code. If you’d like to play around with some example code for this article, you can find it on the PHPMaster GitHub account. Feel free to share your suggestions and previous experiences with Mustache templates in the comments below. Image via Fotolia

Frequently Asked Questions on Sharing Templates between PHP and JavaScript

How can I share templates between PHP and JavaScript?

Sharing templates between PHP and JavaScript can be achieved by using a common templating language that both PHP and JavaScript understand. One such language is Mustache. Mustache is a logic-less template syntax that can be used in all languages including PHP and JavaScript. You can define a template and use it on both the server side (PHP) and the client side (JavaScript). This way, you can render the same template on the server or the client, depending on the situation.

What is Mustache and how does it work?

Mustache is a logic-less templating system that works by expanding tags in a template using values provided in a hash or object. It is often referred to as “logic-less” because there are no if statements, else clauses, or for loops. Instead, there are only tags. Some tags are replaced with a value, some nothing, and others a series of values. This allows you to use the same templating language server-side and client-side.

How can I install Mustache for PHP?

You can install Mustache for PHP using Composer, a dependency manager for PHP. You just need to run the command composer require mustache/mustache in your terminal. This will install Mustache and its dependencies in your project.

How can I use Mustache with JavaScript?

To use Mustache with JavaScript, you need to include the Mustache.js script in your HTML file. You can download it from the official website or include it directly from a CDN. Once included, you can use the Mustache.render method to render your templates.

Can I use other templating systems to share templates between PHP and JavaScript?

Yes, besides Mustache, there are other templating systems that you can use to share templates between PHP and JavaScript. Some of them include Handlebars, Twig, and Smarty. However, the process might be different and you might need to adjust your code accordingly.

How can I handle complex logic with Mustache since it is a logic-less templating system?

While Mustache is a logic-less templating system, it does provide some basic logic through tags. For example, you can use the {{#tag}} and {{/tag}} syntax to create sections that only render if the tag is not empty or false. You can also use the {{^tag}} and {{/tag}} syntax to create sections that only render if the tag is empty or false.

How can I pass data from PHP to JavaScript?

You can pass data from PHP to JavaScript by echoing the data in a script tag in your HTML file. You can either echo the data directly or encode it as JSON using the json_encode function in PHP.

How can I debug my Mustache templates?

Debugging Mustache templates can be a bit tricky since it is a logic-less templating system. However, you can use the {{#tag}} and {{/tag}} syntax to create sections that only render if the tag is not empty or false. This can help you identify where the problem is.

Can I use Mustache with other programming languages?

Yes, Mustache is a cross-language templating system. It can be used with a wide range of programming languages including but not limited to JavaScript, Python, Ruby, PHP, Perl, Objective-C, Java, C#, Android, Go, Lua, ooc, ActionScript, ColdFusion, Scala, Clojure, and Swift.

Are there any limitations to using Mustache?

While Mustache is a powerful templating system, it does have some limitations. Since it is a logic-less templating system, it can be difficult to handle complex logic. Also, since it uses tags, it can be difficult to debug if you have a lot of nested tags. However, these limitations can be overcome with careful planning and coding.

Rakhitha NimeshRakhitha Nimesh
View Author

Rakhitha Nimesh is a software engineer and writer from Sri Lanka. He likes to develop applications and write on latest technologies. He is available for freelance writing and WordPress development. You can read his latest book on Building Impressive Presentations with Impress.js. He is a regular contributor to 1stWebDesigner, Tuts+ network and SitePoint network. Make sure to follow him on Google+.

Advanced
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week
Loading form