программно добавлять блок к определенному контейнеру
Мне нужно отобразить блок на странице сведений о продукте только для пакета продуктов, поэтому я просто добавляю предпочтение для перезаписи 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">
2 answers
Почему бы просто не добавить обновление макета в catalog_product_view_type_bundle.xml
?
Но в ответ на вашу проблему: вы создаете новый $page
с завода. На этой странице еще не были добавлены дочерние элементы; другие методы делают это дальше по цепочке. Вот почему $page->getLayout()->getBlock('content')
возвращает false: контейнер "содержимое" еще не существует.
Расширяя ответ @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;
}
}