README

The icanboogie/view package provides the view part of the model-view-controller (MVC)
architectural pattern. It extends the features of the icanboogie/routing package—more precisely its
controllers—and together with the icanboogie/render package it helps in separating
presentation from logic.

Getting started

Before you get started you'll need to define some prototype methods to bind some render
components to View instances, and View instances to the Controller instances that use
them.

Views and controllers

Views are associated with controllers through the lazy getter view, thus $this->view
is all is takes to start a view inside a controller. The view then waits for
the Controller::action event, to perform its rendering.

The following example demonstrates how a query of some articles is set as the view content,
a title is also added to the view variables:

Altering the view before it is returned to the controller

The event View::alter of class View\AlterEvent is fired when the instance is
created by the view getter. Event hooks may used this event to alter the view before it is
returned to the controller.

The following example demonstrates how a view can be altered before it is returned to the
controller. If the route has a module property, the "template" directory of the module is
added to the template resolver:

<?phpuseICanBoogie\PropertyNotDefined;useICanBoogie\View\View;$app->events->attach(function(View\AlterEvent$event, View$view) use ($app) {try {$module_id=$view->controller->route->module; }catch (PropertyNotDefined$e) {// if the property is not defined we just returnreturn; }// adding a template path$view->template_resolver->add_path($app->modules[$module_id]->path.'templates');// adding a variable$view['log'] =$app->log->messages;// altering the layoutif ($app->is_mobile) {$view->layout.='.mobile'; }});

Rendering a view

Views are rendered using templates and layouts. Templates render the content of views,
while layouts decorate the templates. For instance an "articles/list" template would be used to
render a collection of articles, while a "page" layout would be used to decorate that rendered
collection with the layout of a website.

The template used to present the content of the view is resolved as follows:

From the template property of the view.

From the template property of the route.

From the template property of the controller.

From the name and action of the controller, if the controller has an action property e.g.
"articles/show".

The layout used to decorate the template is resolved as follows:

From the layout property of the view.

From the layout property of the route.

From the layout property of the controller.

"admin" if the identifier of the route starts with "admin:".

"home" if the pattern of the route is "/" and the template exists.

"page" if the template exists.

"default" otherwise.

Because the template and layout properties are lazily created, you can define them instead of
letting View find the right template names. The following example demonstrates how to cancel
the template and define "admin" as layout:

The templates and layouts are usually specified as names e.g. "page" or "articles/show", and not
by path e.g. "/path/to/my/template.phtml". A template resolver and an engine collection are used
to resolve these names into pathname, and the engine collection is used to render the templates
with the appropriate engines. The reason for this is that templates are usually defined as a
hierarchy in your application, and using this hierarchy they can be replaced to better suit
your application.

For instance, the framework ICanBoogie decorates the default template resolver to add additional
features, and also to add the application directories to the template resolver.

Please take a look at the icanboogie/render package for more details about template resolvers
and engine collections.

Providing a cached result

The event View::render:before of class View\BeforeRenderEvent is fired before a
view is rendered. Event hooks may use this event to provide a cached result and save the cost of
rendering.

The following example demonstrates how an event hook may provide a cached result of a previously
rendered view. Because the JSON of a view instance includes its template, layout, and variables,
its hash is perfect as cache key:

Rendering JSON and stuff

Views are often used to render HTML, but they can also render JSON, XML and other nice things,
and it's rather simple since all you have to do is alter the Response instance of your
controller according to what you are rendering. This is not really a View feature, but its
something to remember.

The following example demonstrates how the response is altered to suit the JSON response:

Cancelling a view

A view can be cancelled when you need to return a different result or when you want to cancel
its rendering. Views are automatically cancelled when the controller they are attached to returns
a result. A view can also be cancelled by setting the view property of its controller to null.

The following example demonstrates how views can be cancelled using these methods:

<?phpuseICanBoogie\Routing\Controller;useICanBoogie\View\ControllerBindingsasViewBindings;useICanBoogie\Module\ControllerBindingsasModuleBindings;classArticlesControllerextendsController{useController\ActionTrait, ViewBindings, ModuleBindings;protectedfunctionaction_any_index() {$this->view->content=$this->model->visible->ordered->limit(10);$this->view['title'] ="Last ten articles"; }protectedfunctionaction_any_json() {$this->action_any_index();$this->response->content_type="application/json";// The view is cancelled to return JSON textreturnjson_encode($this->view->content); }protectedfunctionaction_head_index() {$this->action_any_index();// The view is cancelled although no result is returned$this->view=null; }}

Rendering a partial

The partial() method renders a partial using the view's renderer:

Remember that the view is included in the variables passed to the template.

<?php$view->partial('articles/overview', [ 'article'=>$article ]);

Prototype methods

The following prototypes method are used. The ControllerBindings trait may be
used to help hinting code.

ICanBoogie\Routing\Controller::lazy_get_view: Returns the View instance associated with
the controller and also starts the view magic.

Events

ICanBoogie\View\View::alter of class View\AlterEvent: fired when the instance is
created by the Controller::view getter. Event hooks may use this event to alter the view before
it is returned to the controller.

ICanBoogie\View\View::render:before of class View\BeforeRenderEvent: fired before the
view is rendered. Event hooks may use this event to provide a cached result.

Installation

Cloning the repository

The package is available on GitHub, its repository can be
cloned with the following command line:

$ git clone https://github.com/ICanBoogie/View.git

Documentation

The package is documented as part of the ICanBoogie framework
documentation. You can generate the documentation for the package and its dependencies with
the make doc command. The documentation is generated in the build/docs directory.
ApiGen is required. The directory can later be cleaned with the
make clean command.

Testing

The test suite is ran with the make test command. PHPUnit and
Composer need to be globally available to run the suite. The command
installs dependencies as required. The make test-coverage command runs test suite and also
creates an HTML coverage report in build/coverage. The directory can later be cleaned with
the make clean command.