Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing data from layout to block controller using setData

Tags:

php

magento

I'm trying to set a variable in my local.xml file for my custom block:

<layout>
    <!-- ... -->
    <page_homepage>
        <!-- ... -->
        <reference name="root">    
            <!-- ... -->
            <block type="core/template" name="home_page_sections" template="page/homepage/sections.phtml">
                <block type="layout/carousel" name="featured_carousel">
                    <action method="setData">
                        <name>filter_attribute</name>
                        <value>is_featured_product</value>
                    </action>
                </block>
            </block>
        </reference>
    </page_homepage>
</layout>

But I am not getting the data on the other end in my controller:

class Foo_Layout_Block_Carousel extends Mage_Core_Block_Template
{
    public function __construct() 
    {
        parent::__construct();

        $filterAttribute = $this->getFilterAttribute(); // Nothing
        $filterAttribute = $this->getData('filter_attribute'); // Nada

        // Alright, fine, what DO I have?!
        var_dump($this->getData()); // array(0) {} ... Argh!
    }
}

From all my searching I've found that this really should work, but since it does not, I have a feeling I'm missing something obvious. Here is my layout module's configuration (I'm using a single module to define a homepage and any other blocks I need for the site):

<?xml version="1.0"?>
<config>
    <modules>
        <Foo_Layout>
            <version>0.1.0</version>
        </Foo_Layout>
    </modules>
    <global>
        <page>
            <layouts>
                <foo_homepage translate="label">
                    <label>Homepage</label>
                    <template>page/homepage.phtml</template>
                    <layout_handle>page_homepage</layout_handle>
                </foo_homepage>
            </layouts>
        </page>
        <blocks>
            <layout>
                <class>Foo_Layout_Block</class>
            </layout>
        </blocks>
    </global>
</config>
like image 682
The Maniac Avatar asked Mar 23 '12 18:03

The Maniac


2 Answers

When the layout rendering code encounters this

<block type="layout/carousel" name="featured_carousel">

It immediately instantiates the block. That means the block's __construct method is called before your setData method is called. So, at the time of construction, no data has been set, which is why your calls to var_dump return an empty array.

Also, immediately after being created, the block is added to the layout

#File: app/code/core/Mage/Core/Model/Layout.php
...
$block->setLayout($this);
...

When this happens, the block's _prepareLayout method is called.

#File: app/code/core/Mage/Core/Block/Abstract.php
public function setLayout(Mage_Core_Model_Layout $layout)
{
    $this->_layout = $layout;
    Mage::dispatchEvent('core_block_abstract_prepare_layout_before', array('block' => $this));
    $this->_prepareLayout();
    Mage::dispatchEvent('core_block_abstract_prepare_layout_after', array('block' => $this));
    return $this;
}

So, this means that any data set in your layout update xml is still not available, even in _prepareLayout. Once the system is done creating the block, it moves on to the next XML node.

<action method="setData">
    <name>filter_attribute</name>
    <value>is_featured_product</value>
</action>

and calls the setData method. Now your block has its data set.

Try defining a _beforeToHtml method on your block and checking for data there. (Assuming your block is being rendered)

like image 168
Alan Storm Avatar answered Nov 12 '22 23:11

Alan Storm


i think that the definition of the block is wrong. Can you try

<block type="layout/carousel"name="featured_carousel" attribute=value>

and in the phtml retrieve the value with $this->getAttribute()

You can see the next example:

class Elblogdeselo_Blocksparams_Block_Test extends Mage_Core_Block_Abstract{    
protected function _toHtml(){

    //$nombre=$this->getNombre();
    $nombre=$this->getData('nombre');
    $html=$html." ".$this->getData('nuevo_parametro');
    return $html;
}

}

And in the definition in the backend i put in my home CMS

{{block type="blocksparams/test" name="bloque_con_parametros" nuevo_parametro="nuevo" nombre="david"  template="blocksparams/test.phtml"}}

another example that i find in a extension:

protected function _construct(){
    parent::_construct();
    $this->setData('customer', Mage::getSingleton('customer/session')->getCustomer());
    $this->addData(Mage::getModel('model/model'));     
}
like image 23
davidselo Avatar answered Nov 12 '22 22:11

davidselo