7

What I have tried so far

As the title describes. How can one implement different layouts per product based on a value on that product (in this case a custom EAV on the Product entity)

At first I thought I'd create a custom product type for these type of products. This would work fine. Although you cannot change the product types for existing products.

Then I thought I could make a new page layout, though you can not add content to the product layout.

Lastly I thought I would simply add all these products in a category and change the product view there (via Design > Layout update XML) but this would involve the end user writing XML which is something I'd like to avoid if possible. Same goes for changing the Design > Layout update XML for each product.

Other info:

I have create a Magento module which should replace the product image with a different view. Currently I have overwritten (in my module) the view/frontend/layout/catalog_product_view.xml with my custom content (removing the original image/video blocks and adding my own blocks) this works fine though ALL products now have the new layout.

All products are simple products currently

2 Answers 2

10
+100

Yes you can achieve this thing by writing small code

What you need to do is add layout via event layout_load_before, you can use this event to add your dynamic layout.

Here is sample code for you, please modify as per your need

what you can do is create events.xml in your module

[Vendor]/[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">
    <!-- for diffrentiate layout.xml on product basis -->
    <event name="layout_load_before">
        <observer name="load_custom_handler" instance="[Vendor]\[Module]\Observer\LayoutLoadBefore" />
    </event>
</config>

In your [Vendor]\[Module]\Observer\LayoutLoadBefore.php file write below code

<?php

namespace [Vendor]\[Module]\Observer;

class LayoutLoadBefore implements \Magento\Framework\Event\ObserverInterface
{
    /**
     * @var \Magento\Framework\Registry
     */
    private $registry;

    public function __construct(
       ............
       \Magento\Framework\Registry $registry,
       ............
    ) {
        $this->registry = $registry;
    }


    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $product = $this->registry->registry('current_product');

        if (!$product) {
          return $this;
        }
        if ($product->getMyvalue()) { // your condition
           $layout = $observer->getLayout();
           $layout->getUpdate()->addHandle('your_handle_name');
        }

        return $this;
    }
}

And now go to [Vendor]\[Module]\view\frontend\layout\your_handle_name.xml file and write your code.

This file only added to your specific condition of product

7
  • What's this line stands for ? $layout->getUpdate()->addHandle('your_handler_name'); , I dont understand handler, I also R & D for layout handler, Resources doesn't make me understood. If you can help me out OR some useful links.
    – anonymous
    Commented Jun 2, 2018 at 6:12
  • 1
    @Vivek that line add layout and its find your_handler_name.xml file in all modules Commented Jun 2, 2018 at 16:40
  • Hi, Here all thing work fine, Even my observer also get called. But my custom handler is not render, It render only catalog_product_view.xml, Please let me know if anything I miss. I have created catalog_product_view_extension.xml
    – Ravi Soni
    Commented Jul 9, 2018 at 13:07
  • @Ravi , please check your handler path and name , or other wise ask new question and put your code over there and send me link of that question I will check Commented Jul 9, 2018 at 13:10
  • @Ravi , your_handler_name would be custom name any name you can give here, just create a file with that name Commented Jul 9, 2018 at 13:12
7

You can do it using xml for bulk products. for that you will have to override helper and create attribute for that. let me explain you descriptively.

Step 1: Create product attribute 'customlayout'.

  • Create cutom product-attribute for custom layout, here I have just created attribute 'customlayout' with type boolean(yes/no).
  • Assign this attribute in appropriate attribute-set.
  • Now 'customlayout' is visible in products , set yes in those products which you want to set different layout.

enter image description here

Step 2: Override Helper function initProductLayout().

Override above helper function in your custom module and also change in di.xml file to override helper.

app/code/YourCompany/YourModule/etc/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">
    <preference for="Magento\Catalog\Helper\Product\View" type="YourCompany\YourModule\Helper\Product\View" />
</config>

in YourCompany\YourModule\Helper\Product\view.php file.

public function initProductLayout(ResultPage $resultPage, $product, $params = null)
    {
      ......
      // add handle params
      ......
    if ($params && $params->getBeforeHandles()) {
        foreach ($params->getBeforeHandles() as $handle) {
            $resultPage->addPageLayoutHandles(['customlayout' => $product->getCustomlayout(), 'id' => $product->getId(), 'sku' => $urlSafeSku], $handle);
            $resultPage->addPageLayoutHandles(['type' => $product->getTypeId()], $handle, false);
        }
    }

    $resultPage->addPageLayoutHandles(['customlayout' => $product->getCustomlayout(), 'id' => $product->getId(), 'sku' => $urlSafeSku]);
    $resultPage->addPageLayoutHandles(['type' => $product->getTypeId()], null, false);

    if ($params && $params->getAfterHandles()) {
        foreach ($params->getAfterHandles() as $handle) {
            $resultPage->addPageLayoutHandles(['customlayout' => $product->getCustomlayout(), 'id' => $product->getId(), 'sku' => $urlSafeSku], $handle);
            $resultPage->addPageLayoutHandles(['type' => $product->getTypeId()], $handle, false);
        }
    }

   ........

    }

Here I have added custom attribute for custom layout handle. now you can create custom layout file to use this attribute.
let's create custom handle file.

Step 3: Create layout file for custom layout.

Create layout file in your custom theme/ custom module. catalog_product_view_customlayout_1.xml

Here you can set your custom changes in it. it will be applied to all the products which have 'customlayout' attibute value is 'yes'.

3
  • @tuim , please follow above steps, it will work for you. above steps are working for me . Commented Apr 7, 2018 at 5:33
  • @tuim, Have you tried our solution.? Is this work for you.? Commented Apr 7, 2018 at 12:23
  • Hi, I've decided to go with the solution below. Since I didn't want to override the complete initProductLayout function with a custom implementation. That would decrease maintainability.
    – Tuim
    Commented Apr 9, 2018 at 7:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.