My use case for this was that I needed a mechanism to change layout based on the customer group.

So with that in mind i decided adding a customer group layout handle was the way to go and that would allow me to use regular XML to change what I needed to.

So how?

To do this I used a plugin but I needed to know where to plug in to. In the Magento\Framework\View\Result\Page class there is a handy public function called addPageLayoutHandles.

Perfect, we can hook in to this.

In your frontend/di.xml;

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\View\Result\Page">
        <plugin name="[pluginName]" type="[Vendor]\[ModuleName]\Plugin\[ClassName]" sortOrder="10"/>
    </type>
</config>

[pluginName] is just a unique name to describe your plugin. Here, maybe use “custom-layout-handles”.

[ClassName] should also be descriptive of your plugin. For example “PageLayoutHandles”.

The plugin type is a path to your plugin class.

Magento seem to be all over the place with where they put their plugins but a good place seems to be in the Plugin directory inside your module root.

So, in app/code/[codePool]/[Vendor]/[ModuleName]/Plugin/[ClassName].php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php

namespace [Vendor]\[ModuleName]\Plugin;

use Magento\Customer\Model\Session;
use Magento\Framework\View\Result\Page;
use Magento\Store\Model\GroupFactory;

class [ClassName]
{
    protected $customerSession;

    protected $groupFactory;

    public function __construct(
        Session $customerSession,
        GroupFactory $groupFactory
    ) {
        $this->customerSession = $customerSession;
        $this->groupFactory = $groupFactory;
    }

    public function afterAddPageLayoutHandles(Page $subject)
    {
        $group = $this->groupFactory->create()
            ->load($this->customerSession->getCustomerGroupId());
        if ($group->getId() >= 0) {
            $handle = sprintf("customer_group_%s", strtolower(preg_replace("/[^A-Za-z0-9]/", '_', $group->getName())));
            $subject->addHandle($handle);
        }

        return $subject;
    }
}

This looks like a lot but it is fairly simple.

Firstly we need to get the current customer group id. We use the customer session for that.

Next we try loading the group (because we want the name of the group). For that we require the group factory class.

Then we create a handle from the group (line 28). I have done some formatting on the name of the group to get rid of any none alphanumeric characters and replace them with underscores. Also prefixing it will make it easier to find later on.

For a not logged in customer, the handle that gets generated is customer_group_default. This is key because this will map directly to a layout file located app/code/[codePool]/[Vendor]/[ModuleName]/view/frontend/layout/customer_group_default.xml

Caution: Although this is a fairly nice way of adding layout handles, the above does go to the database everytime. Care must be taken to ensure this does not have a negative impact on the performance of the website.

Code is available on github

  • magento2

Like this post? Share it :)


Related Posts

Back