Creating view classes

Of course, the "Hello World!" example contains way too less information to start creating complex systems using x:template. In this chapter I'm going to show you how to create view classes for different purposes.

Every view class you create must extend XTemplate\View or XTemplate\SubView. These abstract classes contain everything you need to modify a template and render the result. The only thing you of course need to do is adding your logic into your class file. This logic is typically located in the _render()-method of your class. The _render() method is called automatically when the template is rendered.

The two classes have different purposes which are very easy to remember:

Choose XTemplate\View if you're working with a full HTML template including a doctype.

Choose XTemplate\SubView if you're working with a partial HTML template like a module template in a CMS.

There are two different kinds of every general view class which help you to express a certain purpose of a class.

Views with dedicated template files

If your view class has one dedicated template file which will never change, you should use XTemplate\ComfortView or XTemplate\ComfortSubView as base class. These classes expect you to implement a constant named TEMPLATE which contains the path to the template file relative to your class file.

This is an example for a simple view class using one of these base classes:

scripts/2_creating_view_classes/example1.php
<?php
    /**
     * x:template - PHP based template engine
     * Copyright (c) 2011 - 2012 by Tobias Pohlen <tobias.pohlen@xtemplate.net>
     * 
     * Released under the GPL License.
     * 
     * @author Tobias Pohlen
     * @ignore
     */
 
    // Load the x:template engine
    require_once "../../../Engine.php";
 
    /**
     * A simple view class using XTemplate\ComfortView as base class.
     * 
     * @author      Tobias Pohlen
     * @version     $Id$ 
     * @package     xtemplate
     * @ignore
     */
    class Example1 extends XTemplate\ComfortView
    {
        /**
         * Path to the template file relative to this class file.
         */
        const TEMPLATE = "template.html";
 
        protected function _render()
        {}
    }
?>

Views different template files

If you don't want to bind your class to a certain template file, you should use XTemplate\View or XTemplate\SubView as base class. These classes expect the path to the view file to be passed as constructor argument. This path is not relative to the class. It's - as every usual path in PHP - relative to the file which is called. Of course you can pass absolute paths, too.

This is a typically scenario when you need to select the template dynamically: Assume you're programming a plugin for a content management system. Since the plugin shall have different outputs on different websites, you have a way to configure which template shall be used.

This is an example class which uses XTemplate\SubView as base class:

scripts/2_creating_view_classes/example2.php
<?php
    /**
     * x:template - PHP based template engine
     * Copyright (c) 2011 - 2012 by Tobias Pohlen <tobias.pohlen@xtemplate.net>
     * 
     * Released under the GPL License.
     * 
     * @author Tobias Pohlen
     * @ignore
     */
 
    // Load the x:template engine
    require_once "../../../Engine.php";
 
    /**
     * A simple view class using XTemplate\View as base class.
     * 
     * @author      Tobias Pohlen
     * @version     $Id$ 
     * @package     xtemplate
     * @ignore
     */
    class Example2 extends XTemplate\SubView
    {
        protected function _render()
        {}
    }
?>

Render the templates

To render your views you first have to create instances of your view classes. In the following example I'm using the two example classes which are shown above.

After you've create the instance, you have two options to render the template: Explicitly and implicitly.

Explicit rendering

To render the template explicitly, you have to call the render()-method of the instance you want to render. If the rendering process fails, a XTemplate\Exceptions\RenderException will be thrown. According to this fact the explicit rendering gives you the possibility to react on errors in your custom way.

scripts/2_creating_view_classes/controller1.php
<?php
    /**
     * x:template - PHP based template engine
     * Copyright (c) 2011 - 2012 by Tobias Pohlen <tobias.pohlen@xtemplate.net>
     * 
     * Released under the GPL License.
     * 
     * @author Tobias Pohlen
     * @ignore
     */
 
    // Load the view class
    require_once "example2.php";
 
    // Create new view instances
    $objView1 = new Example2("template.html");
    $objView2 = new Example2("template2.html");
 
    // Render the template explicitly
    try
    {
        // Render the view
        $objView1->render();
        // Print the result of the rendered template
        echo $objView1;
    }
    catch (XTemplate\Exceptions\RenderException $objException)
    {
        echo "View1 could not be rendered<br />";
    }
 
    try
    {
        // Render the view
        $objView2->render();
        // Print the result of the rendered template
        echo $objView2;
    }
    catch (XTemplate\Exceptions\RenderException $objException)
    {
        echo "View2 could not be rendered<br />";
    }
?>

Implicit rendering

Sometimes you don't have anything special to do when the rendering fails. In this case you can use the implicit rendering. The implicit rendering doesn't throw any exception. If the rendering fails, the result of the rendered template will be the error message.

scripts/2_creating_view_classes/controller2.php
<?php
    /**
     * x:template - PHP based template engine
     * Copyright (c) 2011 - 2012 by Tobias Pohlen <tobias.pohlen@xtemplate.net>
     * 
     * Released under the GPL License.
     * 
     * @author Tobias Pohlen
     * @ignore
     */
 
    // Load the view class
    require_once "example2.php";
 
    // Create new view instances
    $objView1 = new Example2("template2.html");
    $objView2 = new Example1();
 
    // Render the templates implicitly
    echo $objView1;
    echo $objView2;
?>