In some situations you might want to render a ViewModel (which may or may not have childs) outside of the regular MVC flow. In my case I needed the raw html output to feed to mPDF.
Here’s a function that takes a ViewModel and renders it, including all of its childs.
public function renderViewModel($vm) { $vm->setOption('has_parent', true); $renderer = $this->getRendererFromVM($vm); if ($vm->hasChildren()) { foreach ($vm->getChildren() as $child) { if($vm->terminate() && $child->terminate()) { throw new DomainException('Inconsistent state; child view model is marked as terminal'); } $child->setOption('has_parent', true); $result = $this->renderViewModel($child); $child->setOption('has_parent', null); $capture = $child->captureTo(); if (!empty($capture)) { if ($child->isAppend()) { $oldResult=$vm->{$capture}; $vm->setVariable($capture, $oldResult . $result); } else { $vm->setVariable($capture, $result); } } } } $html = $renderer->render($vm); return $html; }
Because ViewModel classes can have different Renderer classes we need a function to determine what Renderer class to use.
public function getRendererFromVM($vm) { $template = $vm->getTemplate(); $ext = pathinfo($template, PATHINFO_EXTENSION); switch($ext) { case self::SMARTY_RENDERER_SUFFIX: return $this->getServiceLocator()->get('Smarty\View\Renderer'); default: return $this->getServiceLocator()->get('Zend\View\Renderer\PhpRenderer'); } }
In my case I was using ViewModel classes with Smarty templates and one of them had a ViewModel child with a phtml layout. Based on the extension of the template file (.tpl) I decide what Renderer class to use.
Here’s an example how to use these functions from within an Action in a Controller class. Please note that this is just for demonstration; ViewModel’s should be created within models, not controllers.
private function someAction() { //Create main ViewModel $vm = new ViewModel(); $vm->setTemplate('path/to/some_template.tpl'); $vm->setTerminal(true); //Create child ViewModel $vmChild = new ViewModel(); $vmChild->setTemplate('path/to/another_template.phtml'); $vm->addChild($vmChild, 'vmChild'); //Render ViewModel including childs $html = $this->renderViewModel($vm); //Create a Response object $response = new Response(); $response->setContent($html); return $response; }
No Comments