I've got this working by extending the Phalcon\Mvc\View\Engine\Volt
In the render($template_path, $params, $must_clean = null) method I set the alternative path, check if file is available and if so I switch the $template_path given with the alternative path. Then it's just a case of calling:
return parent::render($template_path, $params, $must_clean);
where $template_path contains the new (alternative) path.
If your alternative path might change on a per project basis and you need to set it in bootstrap, then rather than doing it when getting a "view" from di you would do it when getting volt.
Just remember that all views are rendered with that method so you will have to account for layout and partial views as well - depending on your implementation.
Example: (this has not been tested, it's based on a similar set up I have in my own code)
<?php
class Volt extends Phalcon\Mvc\View\Engine\Volt
{
private $skin_path;
public function render($template_path, $params, $must_clean = null)
{
$skin_template = str_replace(
$this->di->getView()->getViewsDir(),
$this->getSkinPath(),
$template_path
);
if (is_readable($skin_template)) {
$template_path = $skin_template;
}
return parent::render($template_path, $params, $must_clean);
}
public function setSkinPath($data)
{
$this->skin_path = $data;
}
public function getSkinPath()
{
return $this->skin_path;
}
}
In your bootstrap:
$di->setShared('volt', function($view, $di) {
$volt = new Volt($view, $di);
$volt->setSkinPath('my/alternative/dir/');
return $volt;
});
Many thanks to nickolasgregory@github who pointed me in the right direction.