Magento2: Programmatically Create Custom Layout XML

This article shows how you can create a custom layout XML handle programmatically in your custom module in Magento 2.

I will be using event observer for this.

app/code/Company/Module/etc/frontend/events.xml

<?xml version="1.0"?>
<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="mycompany_custom_layout" instance="Company\Module\Model\Observer\CustomLayout" />
    </event>
</config>

app/code/Company/Module/Observer/CustomLayout.php

Here, I am checking if a customer is logged in or not & adding the custom layout handle only if the customer is not logged in.


<?php

namespace Company\Module\Model\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\Http\Context as HttpContext;

class CustomLayout implements ObserverInterface
{
    /**
     * @var HttpContext
     */
    protected $httpContext;

    public function __construct(
        HttpContext $httpContext
    ) {
        $this->httpContext = $httpContext;
    }

    public function execute(Observer $observer)
    {
        /** @var \Magento\Framework\View\Layout $layout */
        $layout = $observer->getLayout();

        $isCustomerLoggedIn = (bool)$this->httpContext->getValue(\Magento\Customer\Model\Context::CONTEXT_AUTH);
        
        if (!$isCustomerLoggedIn) {
            $layout->getUpdate()->addHandle('customer_not_logged_in');
        }
    }
}

app/code/Company/Module/view/frontend/layout/customer_not_logged_in.xml

In this layout file, I have added a custom stylesheet file. And, moved login.link.wrapper block to the header.panel.

So, the changes present in this layout XML file will be reflected to non-logged-in customers only.

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <css src="Company_Module::css/style.css" />
    </head>
    <body>
        <move element="login.link.wrapper" destination="header.panel" after="-"/>
    </body>
</page>

app/code/Company/Module/view/frontend/web/css/style.css

/**
your custom css
**/

Hope this helps. Thanks.