1

I have a 3rd party extension creating a block like so in block class:

class Namespace_Modulenam_Block_Custom extends Mage_Core_Block_Template
{
protected function _construct()
{
    parent::_construct();
    $this->setTemplate("amasty/amlanding/custom.phtml");
}

and assigning it to layout in a controller:

class Namespace_Modulename_PageController extends Mage_Core_Controller_Front_Action {
....
public function viewAction(){
....
$this->getLayout()->getBlock('content')->insert(
            $this->getLayout()->createBlock(
                'modulename/custom'
                )
        );
}

I just want to move the placement of the block (i.e. out of 'content', to a text/list block that i've created in a layout.xml file. If I edit this module to:

$this->getLayout()->getBlock('my_block')

the object is empty, presumably becuase the layout.xml defined block has not been created when the controller executes.

If i try adding a name to the block i.e.

 $this->getLayout()->getBlock('content')->insert(
            $this->getLayout()->createBlock(
                'modulename/custom',
                 'my_name'
                )
        );
}

I can't edit it in layout.xml. So to test:

<remove name='my_name'/>

...does nothing.

What is the correct method to interact with this dynamic block? Should I be using event observers? Is there a simple way to do this in my layout.xml?

EDIT BASED ON fschmengler's ASNWER:

I've implemented fschmengler's solution and I am successfully assigning the block name and then unsetting it from the 'content' block.

However in Step2, moving the block:

$layout->getBlock('name.of.new.parent')->append(
    $layout->getBlock('modulename.custom.name')
);

gives Call to a member function append() on a non-object

this would be because (as you fschmengler points out), this parent block is presently defined in layout.xml:

<reference name="root">
    <block type="core/text_list" name="name.of.new.parent" as="name.of.new.parent" translate="label" />
</reference>

Do I need to define this block parent block in another way?

2
  • Does the original block have a name? Commented Sep 4, 2015 at 19:16
  • it doesn't. I thought that I would start by rewriting the class method there to add a name. But even so (if i test this by just hacking the module first) I can' figure out how to manipulate it even when the name is defined.
    – baku
    Commented Sep 4, 2015 at 19:21

1 Answer 1

3

The problem is that this block is created after the layout XML has been processed (after loadLayout()), that's why you cannot modify it with XML and have to use code as well, preferably using an observer.

Usually you will need a name to reference the block in the layout, but if this is the only block of the type modulename/custom, there is a way without changing the extension's code:

Step 1: Give the block a name

Write an observer for core_layout_block_create_after.

In this observer, check the type of the block and assign it a unique name:

if ($observer->getBlock() instanceof Modulename_Block_Custom) {
    $observer->getBlock()->setNameInLayout('modulename.custom.name');
}

Step 2: Move the block

Then, observe controller_action_layout_render_before, and move the block in that observer like this:

$layout = Mage::app()->getLayout();
$layout->getBlock('content')->unsetChild('modulename.custom.name');
$layout->getBlock('name.of.new.parent')->append(
    $layout->getBlock('modulename.custom.name')
);

Don't use remove because this will remove the block entirely from the layout, but unsetChild to just remove it from the content block. Usually unsetChild needs the alias as parameter, but as no alias has been defined in the insert() call, the name can be used.


Regarding your update: The new parent block must be defined before you append the block, so defining it in XML is perfectly fine (remember, first the XML is loaded, then the manipulations via extension controller and observers happen)

So if you are sure that the parent block is rendered, you probably made a mistake with the block name. If not, something might be wrong with the layout file. But the code that you are showing looks fine to me.

3
  • Thank you so much for this detail and insightful answer. I've implemented your solution, but still facing problem accessing the parent block (question edited with details).
    – baku
    Commented Sep 4, 2015 at 20:56
  • @baku I updated the answer Commented Sep 4, 2015 at 21:22
  • thanks a lot, marking your answer as accepted while i figure out the layout xml!
    – baku
    Commented Sep 4, 2015 at 21:23

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.