# Zend_Layout Advanced Usage

`Zend_Layout` has a number of use cases for the advanced developer who wishes to adapt it for different view implementations, file system layouts, and more.

The major points of extension are:

- Custom view objects. `Zend_Layout` allows you to utilize any class that implements `Zend_View_Interface`.

- Custom front controller plugins. `Zend_Layout` ships with a standard front controller plugin that automates rendering of layouts prior to returning the response. You can substitute your own plugin.

- Custom action helpers. `Zend_Layout` ships with a standard action helper that should be suitable for most needs as it is a dumb proxy to the layout object itself.

- Custom layout script path resolution. `Zend_Layout` allows you to use your own inflector for layout script path resolution, or simply to modify the attached inflector to specify your own inflection rules.

## Custom View Objects

`Zend_Layout` allows you to use any class implementing `Zend_View_Interface` or extending `Zend_View_Abstract` for rendering your layout script. Simply pass in your custom view object as a parameter to the constructor/`startMvc()`, or set it using the `setView()` accessor:

    $view = new My_Custom_View();
    $layout->setView($view);

### Not all Zend_View implementations are equal

While `Zend_Layout` allows you to use any class implementing `Zend_View_Interface`, you may run into issues if they can not utilize the various `Zend_View` helpers, particularly the layout and placeholder helpers. This is because `Zend_Layout` makes variables set in the object available via itself and placeholders.

If you need to use a custom `Zend_View` implementation that does not support these helpers, you will need to find a way to get the layout variables to the view. This can be done by either extending the `Zend_Layout` object and altering the `render()` method to pass variables to the view, or creating your own plugin class that passes them prior to rendering the layout.

Alternately, if your view implementation supports any sort of plugin capability, you can access the variables via the 'Zend_Layout' placeholder, using the placeholder helper:

    $placeholders = new Zend_View_Helper_Placeholder();
    $layoutVars   = $placeholders->placeholder('Zend_Layout')->getArrayCopy();

## Custom Front Controller Plugins

When used with the MVC components, `Zend_Layout` registers a front controller plugin that renders the layout as the last action prior to exiting the dispatch loop. In most cases, the default plugin will be suitable, but should you desire to write your own, you can specify the name of the plugin class to load by passing the `pluginClass` option to the `startMvc()` method.

Any plugin class you write for this purpose will need to extend `Zend_Controller_Plugin_Abstract`, and should accept a layout object instance as an argument to the constructor. Otherwise, the details of your implementation are up to you.

The default plugin class used is `Zend_Layout_Controller_Plugin_Layout`.

## Custom Action Helpers

When used with the MVC components, `Zend_Layout` registers an action controller helper with the helper broker. The default helper, `Zend_Layout_Controller_Action_Helper_Layout`, acts as a dumb proxy to the layout object instance itself, and should be suitable for most use cases.

Should you feel the need to write custom functionality, simply write an action helper class extending `Zend_Controller_Action_Helper_Abstract` and pass the class name as the `helperClass` option to the `startMvc()` method. Details of the implementation are up to you.

## Custom Layout Script Path Resolution: Using the Inflector

`Zend_Layout` uses `Zend_Filter_Inflector` to establish a filter chain for translating a layout name to a layout script path. By default, it uses the rules 'Word_CamelCaseToDash' followed by 'StringToLower', and the suffix 'phtml' to transform the name to a path. As some examples:

- 'foo' will be transformed to 'foo.phtml'.

- 'FooBarBaz' will be transformed to 'foo-bar-baz.phtml'.

You have three options for modifying inflection: modify the inflection target and/or view suffix via `Zend_Layout` accessors, modify the inflector rules and target of the inflector associated with the `Zend_Layout` instance, or create your own inflector instance and pass it to `Zend_Layout::setInflector()`.

### Using Zend_Layout accessors to modify the inflector

The default `Zend_Layout` inflector uses static references for the target and view script suffix, and has accessors for setting these values.

    // Set the inflector target:
    $layout->setInflectorTarget('layouts/:script.:suffix');

    // Set the layout view script suffix:
    $layout->setViewSuffix('php');

### Direct modification of Zend_Layout inflector

Inflectors have a target and one or more rules. The default target used with `Zend_Layout` is ':script.:suffix'; ':script' is passed the registered layout name, while ':suffix' is a static rule of the inflector.

Let's say you want the layout script to end in the suffix 'html', and that you want to separate MixedCase and camelCased words with underscores instead of dashes, and not lowercase the name. Additionally, you want it to look in a 'layouts' subdirectory for the script.

    $layout->getInflector()->setTarget('layouts/:script.:suffix')
                           ->setStaticRule('suffix', 'html')
                           ->setFilterRule(array('Word_CamelCaseToUnderscore'));

### Custom inflectors

In most cases, modifying the existing inflector will be enough. However, you may have an inflector you wish to use in several places, with different objects of different types. `Zend_Layout` supports this.

    $inflector = new Zend_Filter_Inflector('layouts/:script.:suffix');
    $inflector->addRules(array(
        ':script' => array('Word_CamelCaseToUnderscore'),
        'suffix'  => 'html'
    ));
    $layout->setInflector($inflector);

### Inflection can be disabled

Inflection can be disabled and enabled using accessors on the `Zend_Layout` object. This can be useful if you want to specify an absolute path for a layout view script, or know that the mechanism you will be using for specifying the layout script does not need inflection. Simply use the `enableInflection()` and `disableInflection()` methods.