0

In trying to come up with my own solution to my other active question, I've been trying to add child blocks to my own custom block so that I can use them as renderers for the product options, thus replicating the general way that product forms are rendered on the product page.

The problem is that I get an error stating that the block I'm trying to add already exists. Taking that into account, I have tried several methods of determining if the child block already exists and none of them have worked yet.

Attempt 1 (check to see if we can get the child block)

protected function _prepareLayout() {
    if (!$this->getChildBlock('default')) {
        $childBlock = $this->getLayout()->createBlock('Magento\Catalog\Block\Product\View\Options\Type\DefaultType', 'product.info.options.default');
        $childBlock->setTemplate('Magento_Catalog::product/view/options/type/default.phtml');
        $this->addChild('default', $childBlock);
    }
    return parent::_prepareLayout();
}

Attempt 2 (check to see if the name already exists in layout)

protected function _prepareLayout() {
    $layout = $this->getLayout()
    if (!$layout->getChildName($this->getNameInLayout(), 'default')) {
        $childBlock = $this->getLayout()->createBlock('Magento\Catalog\Block\Product\View\Options\Type\DefaultType', 'product.info.options.default');
        $childBlock->setTemplate('Magento_Catalog::product/view/options/type/default.phtml');
        $this->addChild('default', $childBlock);
    }
    return parent::_prepareLayout();
}

Attempt 3 (check local variable to determine if this code has already been run)

protected function _prepareLayout() {
    if (!$this->_layoutPrepared) {
        $childBlock = $this->getLayout()->createBlock('Magento\Catalog\Block\Product\View\Options\Type\DefaultType', 'product.info.options.default');
        $childBlock->setTemplate('Magento_Catalog::product/view/options/type/default.phtml');
        $this->addChild('default', $childBlock);
        $this->_layoutPrepared = true;
    }
    return parent::_prepareLayout();
}

In each attempt, I have received the frontend error of "We're sorry, an error has occurred while generating this content." (which is spectacularly helpful considering error display is turned on).

From the exception log, I find this error twice: report.CRITICAL: Element with ID 'form_0.default' is already defined. which tells me that the code appears to be running multiple times.

What I gather from this is that somehow the code is being run three times: once successfully, and twice with errors. If I comment out the code, the child block cannot be found at all so it is not the case that there is a block with the same alias. It also doesn't matter what the alias is, as this has been tested with multiple variations.

I can't see any reason why _prepareLayout would get called multiple times, nor why it wouldn't be able to find the already existing child blocks and prevent the duplication using the code I have tried.

Any assistance in resolving this issue would be welcomed.

For reference, if relevant, this is Magento Commerce 2.2.2.

  • You need to set Magento mode to Developer mode to see the errors in the front end. Also try using Xdebug to line by line debug the issue. – Binod Kalathil Mar 7 '18 at 11:28
  • Awww, I wish it had been that simple. – indefinitedevil Mar 8 '18 at 12:04
0

The problem is that when you make :

$childBlock = $this->getLayout()->createBlock(...)

you create the block in the layout, then when you try to do :

$this->addChild('default', $childBlock);

you also add the block in the layout.

That's why you have an error.

| improve this answer | |

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.