Zend View - Part 1

How to render html using Zend View

Posted on September 18, 2016

This is part one of a multi-series on using the zend-view as a stand-alone library. The code is available on https://github.com/lorenzoferrarajr/zend-view-examples.

Other parts:

zendframework/zend-view is the view layer of zend-mvc. To use it at its basic, two concepts are important: resolvers and renderes:

  • resolvers are responsible of finding the resources (view files) needed by the renderer
  • renderers are responsible of rendering views resources

Assumptions

I'm assuming that a view directory exists, containing some phtml files:

view/
  |- view-1.phtml
  |- view-2.phtml
  |- sub-1/
  |    \- view-3.phtml
  |
  \- sub-2/
       |- view-3.phtml
       \- view-4.phtml

The view/view-1.phtml file contains only text:

Hello, World!

The view/view-2.phtml file contains text and some PHP code:

Hello, <?=$who?>!

The view/sub1/view-3.phtml file also contains text and some PHP code:

This is view/sub1/view-3.phtml

Resolvers: TemplateMapResolver and TemplatePathStack

An instance of the TemplateMapResolver class can be configured to associate one or more keys to a view file.

$resolver = new \Zend\View\Resolver\TemplateMapResolver([
    'first-view' => 'view/view-1.phtml'
]);
var_dump($resolver->resolve('first-view')); // 'view/view-1.phtml'

In the example, the resolver is able to find the view/view-1.phtml file only when the string first-view is used as parameter of the resolve method.

Another resolver is TemplatePathStack: given one or more paths, the resolver can find a specified file searching it inside the paths.

$resolver = new \Zend\View\Resolver\TemplatePathStack([
    'script_paths' => [
        'view/sub1/'
    ]
]);
var_dump($resolver->resolve('view-3.phtml')); // '/.../view/sub1/view-3.phtml'
var_dump($resolver->resolve('view-3')); // '/.../view/sub1/view-3.phtml'

If two paths contain a view-3.phtml file, the one added last wins. Both view-3.phtml and view-3 are valid because the TemplatePathStack resolver adds the file suffix when not specified.

Resolvers: AggregateResolver

Another way to manage resolvers is by creating an AggregateResolver. As the name suggests, an AggregateResolver uses other resolvers to find files.

$resolver1 = new \Zend\View\Resolver\TemplatePathStack([
    'script_paths' => [
        'view/sub1/',
    ]
]);

$resolver2 = new \Zend\View\Resolver\TemplateMapResolver([
    'first-view' => 'view/view-1.phtml'
]);

$aggregateResolver = new \Zend\View\Resolver\AggregateResolver();
$aggregateResolver->attach($resolver1);
$aggregateResolver->attach($resolver2);

var_dump($aggregateResolver->resolve('first-view')); // 'view/view-1.phtml'
var_dump($aggregateResolver->resolve('view-1')); // bool(false)
var_dump($aggregateResolver->resolve('view-1.phtml')); // bool(false)
var_dump($aggregateResolver->resolve('view-2')); // bool(false)
var_dump($aggregateResolver->resolve('view-3')); // '/.../view/sub1/view-3.phtml'

Searching for view-1, view-1.phtml, or view-2 fails because the first resolver is configured to search in the view/sub1/ directory, which does not contain the view-1.phtml or view-2.html files, and the second resolver is a TemplateMapResolver, and the only view it has configured is first-view.

Renderer: PhpRenderer

A PhpRenderer object is responsible of generating markup. The object needs a resolver (or an aggregate resolver) to locate the resources. A very basic example:

$resolver = new \Zend\View\Resolver\TemplateMapResolver([
    'first-view' => 'view/view-1.phtml'
]);

$renderer = new \Zend\View\Renderer\PhpRenderer();
$renderer->setResolver($resolver);
var_dump($renderer->render('first-view')); // string(13) "Hello, World!"

The render method accepts a second argument, an array containing the data that will be passed to the resource to be rendered:

$resolver = new \Zend\View\Resolver\TemplatePathStack([
    'script_paths' => [
        'view/',
    ]
]);

$renderer = new \Zend\View\Renderer\PhpRenderer();
$renderer->setResolver($resolver);
$content = $renderer->render('view-2', ['who' => 'Earth']);
var_dump($content); // string(13) "Hello, Earth!"

What's next

This concludes the first part of this series. Next, I'll talk more about the TemplatePathStack and about how renderers can be enriched by the \Zend\View\HelperPluginManager.