программно добавлять блок к определенному контейнеру


Мне нужно отобразить блок на странице сведений о продукте только для пакета продуктов, поэтому я просто добавляю предпочтение для перезаписи Magento/Каталог/Контроллер/Продукт/Представление

Затем измените метод выполнения контроллера страницы сведений о продукте, как показано ниже.

// Render page
$page = $this->resultPageFactory->create();

if($this->_type->getById($productId)->getTypeId()=='bundle')
{
    $block=$page->getLayout()->createBlock('Vendor\Module\Block\Index\Index');
    $page->getLayout()->getBlock('content')->append($block);
}      

$this->viewHelper->prepareAndRender($page, $productId, $this, $params);
return $page;

Но он всегда выдает ошибку, такую как

Неустранимая ошибка PHP: Вызов функции-члена append() в логическом

Мне нужно добавить свой блок в <referenceContainer name="content">

Author: Bilal Usean, 2017-06-22

2 answers

Почему бы просто не добавить обновление макета в catalog_product_view_type_bundle.xml?

Но в ответ на вашу проблему: вы создаете новый $page с завода. На этой странице еще не были добавлены дочерние элементы; другие методы делают это дальше по цепочке. Вот почему $page->getLayout()->getBlock('content') возвращает false: контейнер "содержимое" еще не существует.

 1
Author: Giel Berkers, 2017-06-22 14:37:33

Расширяя ответ @Gielberkers, вы можете использовать наблюдателя для программного изменения макета, как только он будет готов.

Nspace/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="core_layout_render_element">
    <observer name="Nspace_Module::modify_block" instance="Nspace\Module\Observer\ModifyBlock" />
</event>

Nspace/Module/Observer/ModifyBlock.php

<?php

namespace Nspace\Module\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

class ModifyBlock implements ObserverInterface
{
  protected $_scopeConfig;
  private static $_layoutSet = false;

  public function __construct(
    \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
  ) {
    $this->_scopeConfig = $scopeConfig;
  }

 public function execute(Observer $observer)
 {
    // Run this only once
    if(ModifyBlock::$_layoutSet) { return; }
    ModifyBlock::$_layoutSet = true;

    $layout = $observer->getLayout();

    // Optional step if you need to remove somethig
    $children = $layout->getChildBlocks('content');
    foreach($children as $key => $childB) 
    {
        if($childB->getType() === [some_type]) 
        {
            $layout->unsetElement($key);
            break;
        }
    }

    // Add a new block
    $layout->createBlock('Vendor\Module\Block\Index\Index', 'custom-index-index');
    $layout->setChild('content', 'custom-index-index', 'custom-index-index');
    return;
 }
}
 0
Author: Alan, 2018-02-01 11:43:36