The Dev Drawer
Posted on March 24, 2023
Ever wanted to master Mustache single-page application development? Did you know you can use PHP with it? In this tutorial, we go over how you can create a single-page application using Mustache and PHP.
In today's fast-paced world, users expect websites and applications to load quickly and provide a seamless experience. Single-page applications (SPAs) have emerged as a popular solution to meet these expectations. With Mustache and PHP, developers can build dynamic, responsive, and scalable SPAs that deliver content and functionality without requiring page reloads. However, mastering these technologies can be challenging, especially for those new to web development.
In this tutorial, we will dive deep into the world of Mustache and PHP to help you master single-page application development. We will cover the basics of SPAs, discuss the benefits of using Mustache and PHP, and provide step-by-step guidance on how to build a SPA from scratch. Whether you're a beginner looking to learn more about web development or an experienced developer seeking to expand your skills, this tutorial will provide you with valuable insights and practical tips to take your SPA development to the next level.
View This On YouTube
File Structure
index.php
autoload.php
.htaccess
/controllers
Nav.php
Templates.php
/sass
style.scss
/css (generated by Sass)
style.css
style.min.css
/views
404.html
about.html
contact.html
home.html
partials/
/contact
forms.mustache
footer.mustache
header.mustache
styles.mustache
htaccess File
We are using the .htaccess
file to redirect all page calls to the index.php
file. So if you go to / it will show the index.php and if you go to /about it will show the same index.php. We will use this as the basis of our routing.
<IfModule mod_rewrite.c>
Options +FloowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php [L]
</IfModule>
Install Mustache
You can either download Mustache from their website or use Composer to install it. For this tutorial, we will be using Composer.
composer require mustache/mustache
This will give us access to the vendor and autoloader via Composer.
Setup our index.php
Since this file will be used for all requests on this website, we need to configure it in a way it acts as a router.
<?php
require_once 'vendor/autoload.php';
require_once 'autoload.php';
Mustache_Autoloader::register();
Create Our Autoloader (for our application classes)
In a previous video I created, I went over how to create your own Autoloader for your custom classes. You can see that video here:
This code comes in handy when you are creating your own custom classes and don't want to have to require or include them. In this case, we will use it to pull our custom classes from the controllers
folder.
<?php
function autoload($class) {
include 'controllers/'.$class.'.php';
}
spl_autoload_register('autoload');
Create Our Templates Class
The template class will have some key methods in it that use Mustache and render the content/data.
In our __contruct
method, we will initialize the Mustache Engine
and add our partials to the object. This will help when we go to use our partials below.
Next, we create the render
method. This method will get the content from the view HTML and parse it using Mustache. For the purposes of the next block of code, we have coded a $data
array that will be used for the home page. In a few steps below, we will create a method data
that uses a switch statement to get the content for multiple pages.
Finally, we have getPageURL
. This method grabs the current page from the URL and allows us to use the render
function to pull the appropriate template from the views folder.
<?php
class Templates {
private $m;
public function __construct(){
$this->m = (new \Mustache_Engine(
[
'partials_loader' => new \Mustache_Loader_FilesystemLoader('views/partials'),
]
));
}
public function render($template) {
$data['content'] = [
'title' => 'Home',
'heading' => 'Welcome to the home page!',
'content' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
];
$template = @file_get_contents('views'. $template.'.html');
if($template === false) {
$template = file_get_contents('views/404.html');
}
return $this->m->render($template, $data);
}
public function getPageURL() {
$url = explode('?', $_SERVER['REQUEST_URI']);
return ($url[0] == '/' ? '/home' : $url[0]);
}
}
Notice the @
symbol on the file_get_contents
method. This will prevent warnings from showing if the file is not found. We will handle that with our 404 template call.
Setup Our First Template
We are now going to use the {{}}
Mustache variables in our simple HTML.
When you see the {{ variable }}
, this will print out a variable that matches the data being sent over. In our code, we use {{ content.title }}
for the title. This tells the template to look for an array content
and add the value from the title
object. If you need the template to produce a rendered object, you would need to use {{{ variable }}}
, otherwise, it just displays as text.
You will also notice {{> styles }}
in the below code. This adds partials that match that name. We will get into that a bit more below.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ content.title }}</title>
{{> styles }}
</head>
<body>
{{> header }}
<main>
<h1>{{ content.heading }}</h1>
<p>{{ content.content }}</p>
</main>
{{> footer }}
</body>
</html>
For the most part, you can duplicate this for each additional page unless you are adding different content or data to the template.
There are certain tags you use in Mustache. I will list the most common ones out here:
{{ variable }}
this allows you to add text from a variable.
{{{ variable }}}
this allows you to add rendered text (it is different from the {{}}
).
{{# variable }}
whatever you want here {{/ variable }}
if a variable is true
{{^ variable }}
whatever you want here {{/ variable }}
if a variable is false
{{# array }}
{{ item }}
{{/ array}}
get items from an array as a loop or use {{ array.item }}
to get a single item
{{> folder/template }}
get a mustache partial from a folder, remember the templates in this folder must have the extension .mustache since it is rendered via the Mustache code.
Setup Partials
In this part of the tutorial, we are going to create a header
, footer
, and style
partial. Think of a partial as a include
or require
file you would normally use in PHP.
In the views/partials
folder, create the following files:
header.mustache
<header>
{{# nav.header }}
<div class="logo">[logo]</div>
<ul>
{{# links }}
<li><a href="{{ url }}">{{ name }}</a></li>
{{/ links }}
</ul>
{{/ nav.header }}
</header>
footer.mustache
<footer>
{{# nav.footer }}
<ul>
{{# links }}
<li><a href="{{ url }}">{{ name }}</a></li>
{{/ links }}
</ul>
{{/ nav.footer }}
</footer>
styles.mustache
<link href="/css/style.min.css" rel="stylesheet">
You can create as many partials as you need, but for this tutorial, we will only be using these 3.
Create Your Nav Class
In your controllers folder, create your Nav.php file. We will use this to dynamically generate the header and footer links.
<?php
class Nav {
public function header() {
$header = [
'links' => [
['url'=>'/', 'name'=>'Home'],
['url'=>'/about', 'name'=>'About'],
['url'=>'/contact', 'name'=>'Contact'],
]
];
return $header;
}
public function footer() {
$footer = [
'links' => [
['url'=>'/about', 'name'=>'About'],
['url'=>'/contact', 'name'=>'Contact'],
]
];
return $footer;
}
}
Now that we have created the nav class, we can add it to our template class.
In your Templates.php
file, add a new variable below private $m;
, so it now says
private $m;
private $nav;
This will declare our class variable. So, now, in your constructor
add $this->nav = new Nav();
under the Mustache_Engine
variable. This will give us access to the nav class.
We will use this in a moment.
Create Dynamic Data
In the first part of the code, we added only data for the home page.
$data['content'] = [
'title' => 'Home',
'heading' => 'Welcome to the home page!',
'content' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
];
We want to take this and make it more dynamic. Create a new function in the Templates.php
file called data()
. We are going to add our header, footer, and switch statement for the data. Your final code should look something like this:
public function data($page) {
$data['nav']['header'] = $this->nav->header();
$data['nav']['footer'] = $this->nav->footer();
switch ($page) {
case '/home':
$data['content'] = [
'title' => 'Home',
'heading' => 'Welcome to the home page!',
'content' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
];
break;
case '/about':
$data['content'] = [
'title' => 'About',
'heading' => 'Welcome to the about page!',
'content' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
'additional' => ['item 1', 'item 2', 'item 3']
];
break;
case '/contact':
$data['content'] = [
'title' => 'Contact',
'heading' => 'Welcome to the contact page!',
'content' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
];
break;
default:
$data['content'] = [
'title' => '404',
'heading' => 'Oops! Page Not Found',
'content' => 'This page cannot be found, please try again.'
];
break;
}
return $data;
}
This should allow us to create other HTML templates in our view (about.html
,contact.html
,404.html
) as well as link to our header and footer partials.
Go ahead and create those pages if you have not already done so.
They should look like the home.html we have already created.
Update index.php For Template Changes
We initially created the index.php with a reference to the Mustache_Autoloader
. We can now finish this page.
Add the following code to the end of the index.php
:
$templates = new Templates();
$page = $templates->getPageURL();
$data = $templates->data($page);
echo $templates->render($page, $data);
That code should now pull in the Templates
class and call the functions we created to display the data and get the templates.
Conclusion
You should be able to run your code now and see the different pages and content from your methods.
This is a simple way to create a dynamic website, and the cool thing is Mustache does not care where the data comes from. In this tutorial, we are hard-coding it in the method, but you can pull it from a database, an API, a JSON file, or even a CSV. As long as you are sending the data to the template, Mustache will display it where the {{ variable }}
is.
The only thing you have to remember is, Mustache is a "logic-less" template engine. So you cannot do logic statements. The data has to be prepared prior to entering the template. So if you need to do a if
statement, you will need to do it in the PHP code before rendering the template. Outside of that, it is a very useful tool for creating dynamic, data-driven websites.
Watch the video above or download the full codebase using my GitHub profile here: https://github.com/thedevdrawer/mustache-php.
Good luck coding with Mustache.
Read more articles on DevDrawer
Posted on March 24, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.