A short tutorial about how to write a simple php-based template engine (similar to what they use in Yii)
To make it comfortable to use, lets write it by using OOP and php7. As the first thing to do, lets make a frame of View class:
class View { private $path = __DIR__ . '/templates/'; public $data = []; public function setData(array $data) : View { // } public function render(string $templateName) : string { // } }
Here we can see, the $data will contain parameters which will be passed to the template itself. A single method render
will compile the template with the data passed to it and return ready-to-use result. That would also allow us to render the page template from many module-based templates:
echo (new View) ->setData([ 'cart' => (new View) ->setData([...]) ->render() ]) ->render();
Now, lets describe an implementation for the method setData(). It will allow not to replace the data from $this->data, but merge it with the data from an argument:
public function setData(array $data) : View { $this->data = array_merge($this->data, $data); return $this; }
And lets make an implementation for render method. PHP has such functions as ob_start(), ob_get_clean() for dealing with buffer. The engine that we write will just open new buffer, then execute php code and return the result of php buffer with cleaning it content (this means that the content won’t be printed).
public function render(string $templateName) : string { $path = $this->path . $templateName; if (!file_exists($path)) { throw new Exception('Template file ' . $path . ' does not exists'); } extract($this->data); ob_start(); include($path); return ob_get_clean(); }
The logic is pretty simple: we check if file exists, then just use extract() function and compile the template.
As the result, we’ll have such implementation of out View class:
class View { private $path = __DIR__ . '/templates/'; public $data = []; public function setData(array $data) : View { $this->data = array_merge($this->data, $data); return $this; } public function render(string $templateName) : string { $path = $this->path . $templateName; if (!file_exists($path)) { throw new Exception('Template file ' . $path . ' does not exists'); } extract($this->data); ob_start(); include($path); return ob_get_clean(); } }