Register An Observer & Add Layout Handles In Magento 2

Often, you may need to add layout handles to a page. The way I would approach this is by utilising an Observer.

The event we will want to listen to needs to have the layout passed as a parameter, also we need to make sure that layout XML isn’t generated yet. The perfect event for this is in the method Magento\Framework\View\Layout\Builder::loadLayoutUpdates():

    /**
     * Load layout updates
     *
     * @return $this
     */
    protected function loadLayoutUpdates()
    {
        Profiler::start('LAYOUT');
        /* dispatch event for adding handles to layout update */
        $this->eventManager->dispatch(
            'layout_load_before',
            ['full_action_name' => $this->request->getFullActionName(), 'layout' => $this->layout]
        );
        Profiler::start('layout_load');
    
        /* load layout updates by specified handles */
        $this->layout->getUpdate()->load();
    
        Profiler::stop('layout_load');
        Profiler::stop('LAYOUT');
        return $this;
    }

As you can see, this fires an event attaching data, which is the action name of the request and the layout module which is an implementation of View\LayoutInterface.

In Magento 1.x to register an observer you would define some XML in config.xml, however now we should add our event definition within etc/events.xml, this is how our file should look:

    <?xml version="1.0" encoding="UTF-8"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
        <event name="layout_load_before">
            <observer name="brideo_example_layout_load_before" instance="Brideo\Example\Observer\AddHandles" />
        </event>
    </config>

Next we must create an observer class, in Magento 1.x we typically had one observer class in Model/Observer.php. However I like the idea of having my observers in an Observer directory within my directory.

Your observer should implement the ObserverInterface, here is what that interface looks like at the time of writing this article:

    <?php
    /**
     * Observer interface
     *
     * Copyright © 2015 Magento. All rights reserved.
     * See COPYING.txt for license details.
     */
    namespace Magento\Framework\Event;
    
    interface ObserverInterface
    {
        /**
         * @param Observer $observer
         * @return void
         */
        public function execute(\Magento\Framework\Event\Observer $observer);
    }
    

Just like with controllers, each observer must implement a execute() method which is automatically called, so this is where your main logic should go.

Here is what a very basic example would look like of an Observer which adds layout handles to the page:

Brideo/Example/Observer/AddHandles.php

    <?php
        
    namespace Brideo\Example\Observer;
    
    use Magento\Framework\Event\ObserverInterface;
    use Magento\Framework\Event\Observer;
    use Magento\Framework\View\LayoutInterface;
    
    /**
     * Class AddHandles
     *
     * Add custom layout handles to te page
     *
     * @package Brideo\Example\Observer
     */
    class AddHandles implements ObserverInterface
    {
    
        /**
         * Add handles to the page.
         *
         * @param Observer $observer
         * @event layout_load_before
         *
         * @return void
         */
        public function execute(Observer $observer)
        {
            /** @var LayoutInterface $layout */
            $layout = $observer->getData('layout');
            $layout->getUpdate()->addHandle('brideo_custom_handle');
        }
    
    }
    

That should be it, you now have added a custom layout handle to the page. Obviously you would have some logic in regarding when you want your layout handle added, for instance like checking if your extension is enabled.

comments powered by Disqus