gigablah/silex-view

Engine-agnostic view component for Silex

Installs: 498

Dependents: 0

Stars: 6

Watchers: 1

Forks: 1

Language: PHP

0.0.1 2013-12-11 09:04 UTC

README

Build Status Coverage Status

The ViewServiceProvider gives engine-agnostic templating capabilities to your Silex application.

Installation

Use Composer to install the gigablah/silex-view library by adding it to your composer.json. You'll also need a rendering engine, such as Mustache.

{
    "require": {
        "silex/silex": "~1.0",
        "mustache/mustache": "~2.4",
        "gigablah/silex-view": "~0.0.1"
    }
}

Usage

Just register the service provider and optionally pass in some defaults.

$app->register(new Gigablah\Silex\View\ViewServiceProvider(), array(
    'view.globals' => array('foo' => 'bar'),
    'view.default_engine' => 'mustache'
));

The provider registers the ArrayToViewListener which intercepts the output from your controllers and wraps it with a View object. For it to work, you have to return an array of data from your controller function.

Views

Normally you do not need to instantiate any view entities on your own; the listener will convert your controller output. If you wish to do it manually, the syntax is as follows:

$view = $app['view']->create($template = '/path/to/template', $context = array('foo' => 'bar'));

Views can be rendered by calling the render() function, or casting to string:

$output = $view->render();
$output = (string) $view;

Again, you should not need to render your views manually since they will be handled by the Response object.

View Context

The view entity is simply an instance of ArrayObject, so you can use regular array notation to set the context, along with convenience functions like with():

$view['foo'] = 'bar';
$view->with(array('foo' => 'bar'));

To insert into the global context, use share():

$view->share(array('foo' => 'bar'));

You can initialize the global context by overriding view.globals.

Resolving Templates

How does the listener know which template to use? By default it reads the _route attribute from the request entity in lowercase, and appends the extension based on the value of view.default_engine. Some examples:

$app->get('/foobar', function () {}); // get_foobar.mustache
$app->get('/', function () {}); // get_.mustache
$app->match('/', function () {}); // _.mustache

Since you probably want more descriptive template names, you can use named routes:

$app->match('/', function () {})->bind('home'); // home.mustache

You can also set the _template attribute in the request, or as part of the controller output:

$app->get('/foo', function (Symfony\Component\HttpFoundation\Request $request) {
    $request->attributes->set('_template', 'foo.html');
});

$app->get('/bar', function () {
    return array('_template' => 'bar.html');
});

If you need custom logic for generating template paths, you can create your own class that implements TemplateResolverInterface and override view.template_resolver.

Engines

This library does not handle any actual view rendering; that task is delegated to the templating library of your choice. Currently adapters are provided for:

There is a special DelegatingEngine which acts as a registry for multiple different engines, selecting the appropriate one based on the template file extension. Since Aura.View, Plates and Raw PHP all use the same default file extension (.php), you will need to manually configure the extension mapping as follows:

$app->register(new Gigablah\Silex\View\ViewServiceProvider(), array(
    'view.default_engine' => 'php',
    'view.engines' => array(
        'php' => 'view.engine.plates'
    )
));

Composite Views

Views can be nested inside another:

$view->nest($app['view']->create('foobar.html'), 'section');

For a single view, it is equivalent to:

$view['section'] = $app['view']->create('foobar.html');

However, the difference lies in nesting multiple views in the same location. Doing this will place the child views adjacent to each other rather than overwriting:

$view->nest($app['view']->create('foobar.html'), 'section');
$view->nest($app['view']->create('foobar.html'), 'section'); // foobar.html is now repeated twice

What's more, you can mix and match different engines:

$mustacheView = $app['view']->create('foo.mustache');
$smartyView = $app['view']->create('bar.tpl')->nest($mustacheView, 'section');

Nested views will inherit the context of their parent views.

Exception Handling

All rendering exceptions are captured and stored in a shared ExceptionBag.

To access the last thrown exception, or return all of them:

$exception = $app['view']->getExceptionBag()->pop();
$exceptions = $app['view']->getExceptionBag()->all();

More Examples

You can view a code sample of various usage scenarios in the demo application.

License

Released under the MIT license. See the LICENSE file for details.