Since I decided to reinvert the wheel and write a growing MVC, I though having a template class will be cool. Now I have never done any complex templating apart from simple include kind of templating. Now I wrote this base class and here is my concept is explained below. Is this right way/concept of writing web page templates?

Concept
"Any Template class will extend this class. The Controller will modify single part or all. If controller will modify the content only using set action, then the page will change only one component and other parts will remain the same just like including header/footer would do"

Another question is,how do I pass same page object so that non changed parts are cached in the object (since http is stateless protocol)? Should I start session and store it object in session? Should parent be a singleton?
Thanks!

<?php

class TemplateBase{
    //variables corresponding to part of web page
    private $header;
    private $footer;
    private $body;
    private $menu;
    private $left_side;
    private $right_side;
    private $menu_header;//between menu and header
    private $menu_content;//between menu and content
    
    public function __construct(){
        //no inits for now
    }
    
    //header
    public function header_func($action, $value=null){
        if($action=="get"){
            return $this->header;
        }
        
        if($action=="set"){
            $this->header = $value;
        }
    }
    
    //footer
     public function footer_func($action, $value=null){
         if($action=="get"){
            return $this->footer;
        }
        
        if($action=="set"){
            $this->footer = $value;
        }
    }
    
    //body
     public function contents_func($action, $value=null){
         if($action=="get"){
            return $this->body;
        }
        
        if($action=="set"){
            $this->body = $value;
        }
    }
    
    //left side
     public function left_bar_func($action, $value=null){
         if($action=="get"){
            return $this->left_side;
        }
        
        if($action=="set"){
            $this->left_side = $value;
        }
    }
    
    //right side
     public function right_bar_func($action, $value=null){
         if($action=="get"){
            return $this->right_side;
        }
        
        if($action=="set"){
            $this->right_side = $value;
        }
    }
    
    //menu
     public function menu_func($action, $value=null){
         if($action=="get"){
            return $this->menu;
        }
        
        if($action=="set"){
            $this->menu = $value;
        }
    }
    
    //between menu and content
     public function menu_content_func($action, $value=null){
         if($action=="get"){
            return $this->menu_content;
        }
        
        if($action=="set"){
            $this->menu_content = $value;
        }
    }
    
    //between menu and header
     public function menu_header_func($action, $value=null){
         if($action=="get"){
            return $this->menu_header;
        }
        
        if($action=="set"){
            $this->menu_header = $value;
        }
    }

}

/*End of file*/

Recommended Answers

All 5 Replies

Generally the templating functionality would be rolled into the "view" component of your MVC architecture, at least in some fashion. The code you have provided looks a lot more like a registry to me.

However to better understand your design, I'd really like to see how you envision other classes extending this base class and what their unique functionality would be.

From what you provided I see some changes that would make like easier.
First, if this class will always be extended and should not be used by itself, making it an abstract class would make sense. Also I think given what I have seen so far, by extending the SPL ArrayObject you'll gain a lot of useful functionality in sense of being able to work with your template as if it was an array.

Also I think you can drastically refactor your class and make it more flexible.

<?php
	
	abstract class TemplateBase extends ArrayObject
	{
		/**
		 *	Constructs a new TemplateBase object
		 * 	If an array is provided it is passed to the ArrayObject constructor
		 *
		 *	@param $options array
		 */
		public function __construct( $options = array() )
		{
			if( is_array( $options ) ){
				parent::__construct( $array() );
			}
		}
		
		/**
		 *	Adds an area to the template class
		 *	
		 *	@param $area string
		 *	@param $content mixed
		 *	@return self
		 */
		public function setArea( $area, $content = null )
		{
			$this[$area] = $content;
			return $this;
		}
		
		/**
		 *	Returns and area if it has previously been set.
		 *	If a default is provided that is returned when the area has not
		 *	previously been defined.
		 *	
		 *	@param $area string
		 *	@param $default mixed
		 *	@return mixed
		 */
		public function getArea( $area, $default = null )
		{
			if( isset( $this[$area] ) ){
				return $this[$area];
			}
			return $default;
		}
		
		/**
		 *	Checks if the area has been set or not
		 *	@param $area string
		 *	@return boolean
		 */
		public function has( $area )
		{
			return isset( $this[$area] );
		}
	}
	
	class Template extends TemplateBase
	{
		
	}

Generally the templating functionality would be rolled into the "view" component of your MVC architecture, at least in some fashion. The code you have provided looks a lot more like a registry to me.

However to better understand your design, I'd really like to see how you envision other classes extending this base class and what their unique functionality would be.

From what you provided I see some changes that would make like easier.
First, if this class will always be extended and should not be used by itself, making it an abstract class would make sense. Also I think given what I have seen so far, by extending the SPL ArrayObject you'll gain a lot of useful functionality in sense of being able to work with your template as if it was an array.

Also I think you can drastically refactor your class and make it more flexible.

<?php
	
	abstract class TemplateBase extends ArrayObject
	{
		/**
		 *	Constructs a new TemplateBase object
		 * 	If an array is provided it is passed to the ArrayObject constructor
		 *
		 *	@param $options array
		 */
		public function __construct( $options = array() )
		{
			if( is_array( $options ) ){
				parent::__construct( $array() );
			}
		}
		
		/**
		 *	Adds an area to the template class
		 *	
		 *	@param $area string
		 *	@param $content mixed
		 *	@return self
		 */
		public function setArea( $area, $content = null )
		{
			$this[$area] = $content;
			return $this;
		}
		
		/**
		 *	Returns and area if it has previously been set.
		 *	If a default is provided that is returned when the area has not
		 *	previously been defined.
		 *	
		 *	@param $area string
		 *	@param $default mixed
		 *	@return mixed
		 */
		public function getArea( $area, $default = null )
		{
			if( isset( $this[$area] ) ){
				return $this[$area];
			}
			return $default;
		}
		
		/**
		 *	Checks if the area has been set or not
		 *	@param $area string
		 *	@return boolean
		 */
		public function has( $area )
		{
			return isset( $this[$area] );
		}
	}
	
	class Template extends TemplateBase
	{
		
	}

Hi mschroeder,
I was out of DW for a while and I'm back again. I see you have a good point. However, reading some tutorials on internet, the template *must* have fixed number of elements (at least Joomla do have fixed elements). From your code, I can see unlimited adding of areas (which is easy to limit), but I cannot understand how areas will be rendered by a view seeing that Developer will have no idea of what is footer and what is component (Joomla's term).
Are these to be done on Concrete class? Or should I add XML defining component name and its position in fixed number of components like joomla does?
Thanks a lot!

Are you trying to build something that is compatible with Joomla, or are you using Joomla as a reference for how they have solved a certain problem?

Are you trying to build something that is compatible with Joomla, or are you using Joomla as a reference for how they have solved a certain problem?

I'm not trying to emulate Joomla, it was the only reference I was having. After reading a bit I have little clear understanding a bit. I will modify the class you have given me and post back.

After some reading I re wrote everything into below class. I have give a sample template and an example. So far it is very simple and I wonder how can I implement caching to increase the speed and performance!

template Engine class

<?php 

/**
 * The Template engine of your application
 * Loads the templates and no compiling
 */
 
class HTemplate{
    private $tfile;//full path to the template file
    private $values; //array of values in the file
    private $templates_path = "templates/";//path to system templates

    public function __construct($file){
        $this->tfile = $this->templates_path.$file;
    }
    
    public function set($key, $value){
        $this->values[$key]=$value;
    }
    
    public function render(){
        //get file contents
        if(!file_exists($this->tfile)){
            return "Error: Template File ".$this->tfile." could not be found";
        }
        $file_contents =  file_get_contents($this->tfile);
        $tags = array_keys($this->values);
        $tags = array_map(array($this, "add_tags"), $tags);
        $replacer = array_values($this->values);
        
        return str_replace($tags, $replacer, $file_contents);
    }
    
    private function add_tags($key){
        return "{@".$key."}";
    }

}




/*End of file*/

Sample template layout.tpl

<!DOCTYPE html>
<html>
    <head>
        <title>{@title}</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <div>
            <h3 style="color:red;">{@heading}</h3>
        </div>
        <div>
            {@body}
        </div>
    </body>
</html>

Sample view (note that data comes from controller which gets it from DB)

<?php 
    
    $layout = new HTemplate("layout.tpl");
    $layout->set("title", $id);
    $layout->set("heading", $heading);
    $layout->set("body", $body);

    echo $layout->render();

?>
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.