Writing template helpers

A template helper consists of one or more custom classes that you write yourself, each with one or more methods that you also write yourself. Custom template helper classes do not need to implement any interfaces, but they do need to extend DMCustomTemplateHelper. (Module template helpers work a little differently; see the section called “Using custom template helpers”.)

A simple template helper

A simple template helper looks like this:

<?php
class MyTemplateHelper extends DMCustomTemplateHelper {

    /**
     * Here, we are reimplementing the method we want to
     * override: in this case, the DMObjectTemplateHelper class'
     * getHtmlMetadataAsDL() method. We cannot literally override this method;
     * we must name it differently due to the way custom template helpers work.
     * And then we return the result:
     */
    public function getCustomHtmlMetadataAsDL() {
        // Assemble some HTML...
        $result = '<dl>
           <dt>Author</dt>
           <dd>Anonymous</dd>
        </dl>';

        // And then return it
        return $result;
    }

}
?>

This method will now be accessible from our page templates like so:

<?php echo $view->getHelper()->getCustomHtmlMetadataAsDL() ?>

The template helper concept contrasts with other strategies for adding dynamic functionality to dmBridge templates. For example, it would be easy to add blocks of PHP code directly in the template. This is not recommended due to its negation of most of the advantages outlined in the introduction to template helpers. It would also be possible to modify dmBridge code in-place. This is a bad idea for obvious reasons.

Template helper files must be saved in the dm/extensions/helpers folder, inside a folder named the same as their class name. (The path of the example above would be dm/extensions/helpers/MyTemplateHelper/MyTemplateHelper.php.) The class name doesn't matter, but it should briefly describe the purpose of the helper and be unique.

[Note]Note

The PHP engine is not able to load two classes with the same name simultaneously. Whenever dmBridge looks for a class, its class loader will look in the custom helpers folder last. Therefore, a custom helper whose name is the same as that of another dmBridge class will never get loaded.

Using custom stylesheets and JavaScripts

Template helpers may need to use a custom JavaScript from a script tag. They may want to provide some default styles. script tags (for JavaScripts) are allowed in the HTML body, but link (for stylesheets) is not. And even though script tags are allowed in the body, it may be difficult to avoid including a script that has already been included; for example, one template helper might want to include the jQuery library, and another may want to include it as well, leading to a clash.

This problem is solved by the following methods in the DMGenericTemplateHelper class:

  • addMetaTag()

  • addScriptTag()

  • addStylesheetTag()

All template helpers that require any functionality provided by a meta, script, or link tag will call these methods to add it, instead of outputting it in their markup. Then, in the appropriate places in the templates, the following methods are called:

  • getHtmlMetaTags()

  • getHtmlScriptTags()

  • getHtmlStylesheetTags()

An example follows:

<?php

/**
 * The template helper
 */
class MyTemplateHelper extends DMCustomTemplateHelper {

    public function helperWillRender() {
        $base_uri = DMConfigIni::getInstance()->getString(
           "dmbridge.base_uri_path");
        $this->addMetaTag("Bill", "author");
        $this->addHeadScriptTag("http://somewhere/jquery.js");
        $this->addBodyScriptTag(
           $base_uri . "/extensions/helpers/MyTemplateHelper/awesome.js");
        $this->addStylesheetTag(
           $base_uri . "/extensions/helpers/MyTemplateHelper/awesome.css");
    }

    public function getSomeAwesomeHtml() {
        return "<p>This is some awesome HTML!</p>";
    }

} ?>

<!-- The template -->
<html>
    <head>
        <?php echo $view->getHelper()->getHtmlMetaTags() ?>
        <?php echo $view->getHelper()->getHtmlStylesheetTags() ?>
        <?php echo $view->getHelper()->getHtmlHeadScriptTags() ?>
    </head>
    <body>
        <?php echo $view->getHelper()->getSomeAwesomeHtml() ?>
        <?php echo $view->getHelper()->getHtmlBodyScriptTags() ?>
    </body>
    </html>

In the MyTemplateHelper class, notice the helperWillRender() method. This is a delegate method called by the DMInternalView instance before the template has been rendered, and thus before any template helper methods have been called. This is necessary because if a helper were to be executed in the body -- as most are -- it would have no other way of inserting content in the head.

In the HTML template, Note that there are two separate methods called to insert scripts onto the page -- one in the head section (getHtmlHeadScriptTags()), and one in the body section (getHtmlBodyScriptTags()). Placing scripts in the body is a good general web design practice, as it helps pages to load faster; but it is not always possible. It is common to include e.g. framework scripts (such as jQuery or YUI) in the head section, and as many of the rest as possible in the body section.

Even though, for example, getHtmlMetaTags() outputs a series of meta tags, it is possible to write the directly in the template. The advantage of using this accessor mechanism is that it avoids placing duplicate tags on the page, and it makes it possible for template helpers to place their required tags in the right place.