0

I have to use different page layouts (<page>) depends on base layout (<layout>) specified for a product.

For example,

  • if I select a layout in product's 'Design' menu with the name '2columns-right', Magento 2 will render 'catalog_product_view.xml' for this layout.

  • If I select 'onemore-layout', Magento 2 will render 'catalog_product_view.xml' for this layout.

Currently I don't see relations between base layout (<layout>) and page layout (<page>).

0

I have resolved the problem.

I created a new module with a file inside to override a Magento 2 product helper which is responsible for generation of list of .phtml handles.

app/code/MyVendorName/MyModuleName/Helper/Product/View.php

<?php

namespace Uco\PageLayout\Helper\Product;

use Magento\Framework\Api\AttributeInterface;
use Magento\Framework\View\Result\Page as ResultPage;

class View extends \Magento\Catalog\Helper\Product\View
{
    /** @inheritDoc */
    public function initProductLayout(ResultPage $resultPage, $product, $params = null)
    {
        $settings   = $this->_catalogDesign->getDesignSettings($product);
        $pageConfig = $resultPage->getConfig();

        if ($settings->getCustomDesign()) {
            $this->_catalogDesign->applyCustomDesign($settings->getCustomDesign());
        }

        // Apply custom page layout
        if ($settings->getPageLayout()) {
            $pageConfig->setPageLayout($settings->getPageLayout());
        }

        $urlSafeSku = rawurlencode($product->getSku());

        // Load default page handles and page configurations
        if ($params && $params->getBeforeHandles()) {
            foreach ($params->getBeforeHandles() as $handle) {
                $resultPage->addPageLayoutHandles(['id' => $product->getId(), 'sku' => $urlSafeSku], $handle);
                $resultPage->addPageLayoutHandles(['type' => $product->getTypeId()], $handle, false);
            }
        }

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

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

        $attributeValue = $product->getCustomAttribute('page_layout');
        if ($attributeValue instanceof AttributeInterface) {
            $resultPage->addPageLayoutHandles(['page_layout' => $attributeValue->getValue()], 'catalog_product_view', false);
        }

        // Apply custom layout update once layout is loaded
        $update        = $resultPage->getLayout()->getUpdate();
        $layoutUpdates = $settings->getLayoutUpdates();
        if ($layoutUpdates) {
            if (is_array($layoutUpdates)) {
                foreach ($layoutUpdates as $layoutUpdate) {
                    $update->addUpdate($layoutUpdate);
                }
            }
        }

        $currentCategory = $this->_coreRegistry->registry('current_category');
        $controllerClass = $this->_request->getFullActionName();
        if ($controllerClass != 'catalog-product-view') {
            $pageConfig->addBodyClass('catalog-product-view');
        }
        $pageConfig->addBodyClass('product-'.$product->getUrlKey());
        if ($currentCategory instanceof \Magento\Catalog\Model\Category) {
            $pageConfig->addBodyClass('categorypath-'.$this->categoryUrlPathGenerator->getUrlPath($currentCategory))
                       ->addBodyClass('category-'.$currentCategory->getUrlKey());
        }

        return $this;
    }
}

Here is the only one change.

I added the next lines to get the code of the product's layout chosen to create an additional layer of flexibility (our new handle will have the maximum priority and will be triggered firstly):

$attributeValue = $product->getCustomAttribute('page_layout');
if ($attributeValue instanceof AttributeInterface) {
    $resultPage->addPageLayoutHandles(['page_layout' => $attributeValue->getValue()], 'catalog_product_view', false);
}

And now I am able to change something via new .phtml file like the next one:

catalog_product_view_page_layout_my-new-pretty-layout-code.xml

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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