Custom blocks in smarty

Creating Custom Blocks in Smarty

Quentin Zervaas

Introduction

Smarty is a very powerful template engine for PHP that allows developers to extend its capabilities using custom plug-ins. There are several different types of plug-ins, each of which serves a different purpose. In this article we will look at how the block plug-in type works.

We will first learn how block plug-ins can be used in your templates, and then learn how to create our own. Once we know how to create a block plug-in, we will cover a practical example that will show you how block plug-ins can effectively be used in your own web sites.

The Block Plug-in Type

There are several different kinds of plug-ins that can be implemented in Smarty, allowing developers to easily extend the capabilities of their templates (or to manipulate how the engine works). We will be looking at the block plug-in type, which allows you to process an entire area of generated content. For example, blocks allow you to use template code similar to that in Listing 1.

{my_custom_block}

Here is the content inside the block

{/my_custom_block}

If we were to use this template code, we would then need to implement the my_custom_block plug-in. The plug-in code would be executed twice: once when the block is opened and again when it is closed. We can determine within the code which of those two events are being handled. When we handle the closing of the block, we have access to the content inside the block (which may contain output from other Smarty tags).

You may already be familiar with one of the built-in blocks Smarty has: {capture}. This plug-in allows you to save the contents of the block to a template variable for later use. I commonly use this in URL generation. Listing 2 shows an example of generating a URL and saving it to the $url variable so it can used multiple times in the template.

{capture assign=url}/path/to/page?var1={$var1}&var2={$var2}{/capture}

<a href=”{$url|escape}”>{$url|escape}</a>

Note: Remember to use the escape modifier when outputting template variables in HTML. This is to prevent script injection, as well as to generate valid XHTML (in this case, the & would be output as & rather than &amp; if we didn’t use escape).

One of the most useful applications of blocks is to generate a series of HTML tags in a single line of code. For example, if you wanted to publish articles on a web site, you might want to display a summary of each article (known as a teaser) in several locations on the site – perhaps in different templates.

Listing 3 shows the HTML code you may use to display an article teaser.

<div class=”teaser”>

<h3>{$title|escape}</h3>

<div class=”byline”>By {$author|escape}</div>

<p>

{$teaser|escape}

</p>

</div>

While there is nothing wrong with this, if you end up repeating this code in several templates in your site, it becomes difficult to update if you ever want to change the mark-up. A simpler and cleaner solution is to create a custom block (let’s call it teaser) and let the block deal with the specific HTML tags.

Doing so would allow you use the following code in your template instead:

{teaser title=$title author=$author}

{$teaser}

{/teaser}

When you implement the teaser block, you can either hard-code the HTML tags in the plug-in’s PHP code (not recommended) or you can write the HTML tags to another template and have the block plug-in use that template (this is what the example in this article will use).

Note: Technically speaking, you could implement the same solution using normal Smarty includes (such as {include file=’teaser.tpl’ title=$title author=$author teaser=$teaser}), however using blocks allows you to perform any other custom logic that is required and also lends itself to much cleaner code, even if it is slightly more work. Additionally, when using blocks, you don’t care about the implementation details at all (that is, in your template you don’t need to care where the template is stored).

Implementing a Block Plug-In

We will now look at how to create a block plug-in. Smarty looks for plug-ins in the plugins directory that resides in the same location as the Smarty.class.php file. You can write your custom blocks to this directory, or you can create your own custom plug-in directory.

I highly recommend using a separate directory for your own plug-ins, as it makes upgrading Smarty much easier in the future (you don’t need to keep track of which plug-ins are your own – especially if you have a large number of custom plug-ins in your site).

In the rest of this article I will assume you have created a directory called customplugins which resides in the same location as Smarty.class.php and the plugins directory.

In addition to defining the template_dir and compile_dir variables when instantiating the Smarty class, you must now also update the plugins_dir variable to include customplugins. As an example, you might use the code in Listing 5 to instantiate Smarty:

<?php

require_once(‘Smarty/Smarty.class.php’);

 

$smarty = new Smarty();

$smarty->template_dir = ‘/path/to/templates’;

$smarty->compile_dir = ‘/path/to/templates_c’;

$smarty->plugins_dir[] = ‘customplugins’;

?>

Note: By default the plugins_dir variable is an array with plugins as its only element. We are simply adding the customplugins value to this array.

The next step is to create a new file in the customplugins directory to hold the plug-in PHP code. All plug-ins in Smarty use a standard file-naming scheme, in the format of type.name.php. Since the type of plug-in we are creating is a block plug-in, we use the filename block.blockname.php. As an example, if we were to create a plug-in called teaser the filename would be block.teaser.php.

Within this file we create a PHP function, which is named in the format smarty_type_name. So in the case of creating a block called teaser the function we create would be called smarty_block_teaser().

When implementing a block plug-in, the PHP function takes four arguments:

  1. $params – This is an array of the attributes passed to the block’s opening tag. This array is available both when the block is opened and when it is closed.
  2. $content – This is a string of the content inside the block. This value is only available when the block function is called for the block being closed. If the block contains template code (such as loops or variable output) then $content contains the evaluated output (not the original template source).
  3. $smarty – The Smarty object, allowing you to assign variables or to evaluate another template.
  4. $open – This variable is used to determine whether the function is being called for the tag opening or closing. When being called for close, the value of $open is false.

To actually output content to the template, it is simply a matter of returning the output value from the plug-in.

Putting all of this together, if we wanted to create a block plug-in called teaser, we would create a file called block.teaser.php in the customplugins directory with the code as shown in Listing 6.

<?php

function smarty_block_teaser($params, $content, $smarty, $open)

{

if ($open) {

// Called when {teaser} appears in template

}

else {

// Called when {/teaser} appears in template.

// Additionally, $content contains the evaluated template

// that lies within the {teaser} {/teaser} tags.

}

}

?>

Next we will complete this code by creating a fully-functioning block plug-in.

Implementing the Complete Teaser Block Plug-In

Now that we have a solid understanding of how the block plug-in type works, we can implement a complete plug-in. We will build on the teaser example from earlier in this article.

Our goal is to use the code shown in Listing 7 to generate the output shown in Listing 8.

{teaser title=’My Article’ author=’Quentin Zervaas’}

In this article you will learn about such and such.

{/teaser}

<div class=”teaser”>

<h3>My Article</h3>

<div class=”byline”>By Quentin Zervaas</div>

<p>

In this article you will learn about such and such.

</p>

</div>

The first thing we will do is to create a Smarty template in which to output the block. We do this to avoid embedding HTML tags within our PHP code, as well as allowing us to easily use other Smarty functionality in our display template as required.

Listing 9 shows the code we write to the teaser.tpl template, which should be saved within the template directory as specified in the template_dir variable. I have just assumed it’s in the top-level directory, but you may wish to organise your own templates differently.

<div class=”teaser”>

<h3>{$block.title|escape}</h3>

<div class=”byline”>By {$block.author|escape}</div>

<p>

{$block.content|escape}

</p>

</div>

Next we implement the teaser plug-in. As you can see in Listing 10, we output values from the $block template variable. This is done to group all block values together without cluttering the Smarty variable namespace.

Listing 10 shows the code for the block.teaser.php file, which we store in the customplugins directory created earlier in this article.

<?php

function smarty_block_teaser($params, $content, $smarty, $open)

{

if ($open) {

// nothing to do

}

else {

// build the array of template values based

// on the attributes and block content

$block = array(

‘title’   => $params[‘title’],

‘author’ => $params[‘author’],

‘content’ => $content

);

 

// assign block values to template

$smarty->assign(‘block’, $block);

 

// return template output

return $smarty->fetch(‘teaser.tpl’);

}

}

?>

That is all that’s required to implement a block plug-in. You can then call {teaser} {/teaser} in your templates as required (as in Listing 8).

Conclusion

In this article we have learned how to simplify your Smarty template code and to avoid repeating complex templates by using block plug-ins. Doing so allows us to easily to maintain and update templates as required without worrying about the implementation details of web page components.

To demonstrate the block functionality we implemented a plug-in called teaser, which could be used to output the summary of an article or document.

You can find the full block plug-in documentation on the Smarty web site at http://www.smarty.net/manual/en/plugins.block.functions.php.

Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedIn

Leave a Reply

Your email address will not be published. Required fields are marked *