Super simple template engine

It may be trivial to more experienced PHP developers but I’ve been asked and here is a more long form answer to the question

Can I include a .php  file without it echoing to the page?

The include instruction

PHP allows a developer to include another .php file at any point in its code flow via the include and require control structures.
Since the statement will “includes and evaluates the specified file” this means that any HTML code will be printed to the current output, usually a page, and any PHP function that echoes will do the same.

What reusing templates allows me NOT to do

A template allows me not to rewrite the same piece of 90% HTML code over and over.
I’m a big fan of code separation and keeping the business logic separated from it’s presentation makes code cleaner and easier to understand. Code is also more reusable, avoiding copying and pasting, and way easier to maintain because that can be done in one place alone. That’s where templating engine like Mustache shine..

A super simple template engine

Having to get out a working version of my mVC framework as soon as possible I’ve come up with a very simple class that will include a file and output it on command. It’s not much of an OOP jewel but will still do its job, the usage is to construct it pointing some template file

$templateFilePath = '/some/file/path.php';
$output = new SuperSimpleTemplateEngine($templateFilePath);

and render it at will

$context = array('name' => 'John', 'age' => 20);
echo $output->render($context);

The class

The class will actually read the file once only at __construct time and will then use the stored string to return its output for increased efficiency.

class SuperSimpleTemplateEngine

    protected $template;
    public function __construct($templateFilePath)
    {
        $this->setTemplate($templateFilePath);
    }
    public function render($context = null)
    {
        if (!is_null($context) and !$this->isAssoc($context)) {
            throw new \InvalidArgumentException("Context must be either null or an associative array", 1);

        }
        $out = '';
        ob_start();
        if (!is_null($context)) {
            foreach ($context as $key => $value) {
                ${$key} = $value;
            }
        }
        eval($this->template);
        $out = ob_get_flush();
        return $out;
    }
    public function getTemplate()
    {
        return $this->template;
    }
    public function setTemplate($templateFilePath)
    {
        if (!is_string($templateFilePath) and !file_exists($templateFilePath)) {
            throw new \InvalidArgumentException("Template $templateFilePath doesn't exist.", 1);

        }
        $this->template = file_get_contents($templateFilePath);
        return $this;
    }
    protected function isAssoc($array)
    {
        foreach (array_keys($array) as $k => $v) {
            if ($k !== $v) {
                return true;
            }
        }
        return false;
    }

hmm… Can I avoid echoing to the page when including a file then?

Use output buffering as I’ve done in the class above

ob_start();             //start output buffering
$out = '';              //here be output
echo "hello world!";    //will NOT print to the page
$out = ob_get_flush();  //what was not printed to the page is now here
echo $out;              //and can be echoed at pleasure