Template API

Using a templating language/engine is very helpful when building web apps. There are many out there such as Pug, Mustache, Twig and Blade to name a few.

Perch Templates are really nice. Like many template engines, Perch Templates can do a lot more than just output content. You can URL encode, JSON encode, escape, format content and more. You also can output content and/or markup conditionally. Plus you extend their functionality with Template Filters and Template Handlers.

And the use of Perch Templates is not restricted to content you retrieve from the database. You can, for example, build a web app that consumes JSON APIs and output the data using Perch Templates thanks to the Perch API.

Basic Usage

The Template API is really easy to use. We’ll go through how to set the template file, namespace and all of that stuff in the full example, but I want to demonstrate how easy it is to render a template. All it you need is an array of data:

$data = array();
$data['title'] = "My Title";
$data['desc'] = "My Description";
echo $Template->render($data);

And you can render multiple items (e.g. for listing) by passing an array of data arrays and use render_group() instead of render():

$data = array();

$data[] = [
  'title' => 'My Title',
  'desc' => 'My Description',
];

$data[] = [
  'title' => 'My Second Title',
  'desc' => 'My Description',
];

echo $Template->render_group($data);

Movie App

Let’s build a movie app that consumes a JSON API and make use of the Template API to render some templates using the data we get from the JSON API.

Before we start

If you never built a Perch app before, check out the post Build Your First Perch App and you will be able to build a simple one in minutes.

We will use the OMDb API. Visit their website and generate a free API Key.

Set up the app

Register your app. I’m calling mine pipit_movies. Check out the naming conventions if you are unsure what to name yours.

pipit_movies/admin.php:

<?php
    $this->register_app('pipit_movies', 'Movies', 5, 'Movie App', '1.0', true);
    $this->require_version('pipit_movies', '3.0');

Add your app ID to perch/config/apps.php:

<?php
    $apps_list = [ 
        'pipit_movies',
    ];

Add your OMDb API key to your perch/config/config.php:

define('PIPIT_MOVIES_OMDB_API_KEY', 'your_api_key');

Let’s get to work

Create your app’s runtime file pipit_movies/runtime.php. This is where we’ll be creating our functions.

What we want to do:

function pipit_movies_get() {
    // get JSON from OMDb API

    // render a template using the data we get from the API
}

OMDb API

Let’s have a look at the OMDb API.

You can use https://www.omdbapi.com/?apikey=your_key and then append some parameters like &t=moon.

The parameter t takes a movie or TV series title. Later we will also use the s parameter to search movies. Check their documentation for the full options.

So if we want to get the movie “The Terminal”, we can use https://www.omdbapi.com/?apikey=your_key&t=the%20terminal.

So now we know how to generate the URL based on the title we want to look up:

function pipit_movies_get($title) {
    $url = 'https://www.omdbapi.com/?apikey=' . PIPIT_MOVIES_OMDB_API_KEY;
    $url .= '&t=' . urlencode($title);
}

And let’s get the JSON and convert it into an array called $data:

function pipit_movies_get($title) {
    $url = 'https://www.omdbapi.com/?apikey=' . PIPIT_MOVIES_OMDB_API_KEY;
    $url .= '&t=' . urlencode($title);

    $json = file_get_contents($url);
    $data = json_decode($json, true);
}

Here’s an example of the data we get:

Array
(
    [Title] => The Terminal
    [Year] => 2004
    [Rated] => PG-13
    [Released] => 18 Jun 2004
    [Runtime] => 128 min
    [Genre] => Comedy, Drama, Romance
    [Director] => Steven Spielberg
    [Writer] => Andrew Niccol (story), Sacha Gervasi (story), Sacha Gervasi (screenplay), Jeff Nathanson (screenplay)
    [Actors] => Tom Hanks, Catherine Zeta-Jones, Stanley Tucci, Chi McBride
    [Plot] => An eastern immigrant finds himself stranded in JFK airport, and must take up temporary residence there.
    [Language] => English, French, Russian, Bulgarian, Spanish
    [Country] => USA
    [Awards] => 5 wins & 4 nominations.
    [Poster] => https://ia.media-imdb.com/images/M/MV5BMTM1MTIwNTMxOF5BMl5BanBnXkFtZTcwNjIxMjQyMw@@._V1_SX300.jpg
    [Ratings] => Array
        (
            [0] => Array
                (
                    [Source] => Internet Movie Database
                    [Value] => 7.3/10
                )

            [1] => Array
                (
                    [Source] => Rotten Tomatoes
                    [Value] => 61%
                )

            [2] => Array
                (
                    [Source] => Metacritic
                    [Value] => 55/100
                )

        )

    [Metascore] => 55
    [imdbRating] => 7.3
    [imdbVotes] => 344,236
    [imdbID] => tt0362227
    [Type] => movie
    [DVD] => 23 Nov 2004
    [BoxOffice] => $77,032,279
    [Production] => DreamWorks SKG
    [Website] => http://www.theterminal-themovie.com/
    [Response] => True
)

Rendering the template

Now we need to instantiate the Perch API and get the Template class:

// pass your app ID
$API  = new PerchAPI(1.0, 'pipit_movies');

// pass the class name, we want Template
$Template = $API->get('Template');

Then we need to set the template file we want to use and the namespace:

$Template = $API->get('Template');
$Template->set('movies/detail.html', 'movies');

Now in our template we can use <perch:movies> tags because we set the namespace to be movies. And finally we render the template with our $data array:

function pipit_movies_get($title) {
    $url = 'https://www.omdbapi.com/?apikey=' . PIPIT_MOVIES_OMDB_API_KEY;
    $url .= '&t=' . urlencode($title);

    $json = file_get_contents($url);
    $data = json_decode($json, true);

    $API  = new PerchAPI(1.0, 'pipit_movies');
    $Template = $API->get('Template');
    $Template->set('movies/detail.html', 'movies');
    echo $Template->render($data);
}

Let’s create our template in pipit_movies/templates/movies and name it detail.html. Refer to the sample array above to check what IDs we can use.

Here’s a basic one to get you started:

<div class="movie">
    <h1><perch:movies id="Title"></h1>

    <div class="movie__meta">
        <perch:movies id="Rated"> - <perch:movies id="Runtime"> - <perch:movies id="Genre">
    </div>

    <div class="movie__poster">
        <img src="<perch:movies id="Poster" >" alt="<perch:movies id="Title" >" />
    </div>

    <p><perch:movies id="Plot"></p>

    <div><strong>Director:</strong> <perch:movies id="Director"></div>
    <div><strong>Staring:</strong> <perch:movies id="Actors"></div>

    <perch:repeater id="Ratings">
        <perch:before><ul></perch:before>
            <li><perch:movies id="Source">: <perch:movies id="Value"></li>
        <perch:after></ul></perch:after>
    </perch:repeater>
</div>

Note how we can use repeaters for $data['Ratings'] since it is an array of arrays.

Now you can to any of your Perch pages and output a movie’s details like so:

pipit_movies_get('The Bourne Identity');

Render multiple items

Now let’s create another function to make use of OMDb’s search feature:

function pipit_movies_search($term) {
    $url = 'https://www.omdbapi.com/?apikey=' . PIPIT_MOVIES_OMDB_API_KEY;
    $url .= '&s=' . urlencode($term);

    $json = file_get_contents($url);
    $data = json_decode($json, true);

    $API  = new PerchAPI(1.0, 'pipit_movies');
    $Template = $API->get('Template');
    $Template->set('movies/list.html', 'movies');
    echo $Template->render_group($data['Search']);
}

And here’s a basic list.html template:

<perch:before>
<ul>
</perch:before>
    <li class="movie">
        <div class="movie__poster">
            <img src="<perch:movies id="Poster" >" alt="<perch:movies id="Title" >" />
        </div>
        <h1>
            <a href="/movie/<perch:movies id="Title" urlify>">
                <perch:movies id="Title">
            </a>
        </h1>
    </li>
<perch:after>
</ul>
</perch:after>

Note how I’m here using the urlify attribute to generate a URL:

<a href="/movie/<perch:movies id="Title" urlify>">
    <perch:movies id="Title">
</a>

So you can have pages like /movie/batman-begins and then on that page you may have something like the following to display the movie’s details:

$movie_title = str_replace('-', ' ', perch_get('slug'));
pipit_movies_get($movie_title);

What did we learn?

The Perch Template API allows us to render templates and it doesn’t exactly care about the source of the data.

You can build an app similar to the Blog app and render your templates with the content you retrieve from the database. Or you can build an app that fetches data from an API and render the data like demonstrated in this post. Or you can render templates with computed data.

You are not limited to any data source and still can take full advantage of Perch Templates.

Note the app we built is just an example of how you might use the Perch API to render templates. You can build custom PHP applications on top of Perch and make use of its powerful template engine and still get all the perks of using a CMS.

link