Search code examples
phplithium

How to define custom handler for Lithium layout


I'm looking to define my own custom handler in the layout view, much like $this->title() or $this->scripts() so that I can render content in the layout that is supplied by the view.

To be precise, I'd like to display the date of a newspaper edition in a part of the view that's defined in the default.html.php file. In the layout, I'd like to use <?= $this->date(); ?> and then, use something like

<?= $this->html->date('Jan 1, 2013', ['inline' => false]); ?>

in the views/posts/view.html.php file. The lithium\template\view\Renderer class appears to have methods for creating handlers (e.g., Renderer::applyHandler), but I can't seem to get it to work like the built-in handlers, like $this->title() etc. Online documentation says little about customizing the handlers in the Renderer/View classes.


Solution

  • This can be done without subclassing the lithium\template\view\Renderer class. In the media.php bootstrap, use the 'handlers' key with Media::type() to pass a customized handler to the renderer:

        Media::type('html', 'text/html', [
            'view' => 'lithium\template\View',
            'handlers' => ['date' => function($date) use (&$ctx) {
                if (!is_null($date)) {
                    $ctx['date'] = $date;
                }
                return $ctx['date'];
            }]
        ]);
    

    Then, $this->date() becomes available in the views and layouts, e.g.:

        //in the default.html.php layout
    
        echo $this->date(); //value passed from /views/controller/index.html.php
    
        //in the views/controller/index.html.php
    
        $this->date(date('Y-m-d'));
    

    As a side note, the $ctx variable is necessary for accessing the rendering context; see the lithium\template\view\Renderer::_init() method for where the 'handlers' array gets merged with the rendering context.