0

How i can change block type programmatically from controller.

1

Here i change login form url without change .phtml and layout xml file.

Original login handler is

<customer_account_login translate="label">
    <label>Customer Account Login Form</label>
    <!-- Mage_Customer -->
    <remove name="right"/>
    <remove name="left"/>

    <reference name="root">
        <action method="setTemplate"><template>page/1column.phtml</template></action>
    </reference>
    <reference name="content">
        <block type="customer/form_login" name="customer_form_login" template="customer/form/login.phtml" />
    </reference>
</customer_account_login>

I going to change "customer_form_login" block block type

Create Controller which extend Mage_Customer_AccountController which contain loginAction()

class Namespace_ModuleName_AccountController extends Mage_Customer_AccountController{
public function loginAction()   {
  if ($this->_getSession()->isLoggedIn()) {
        $this->_redirect('*/*/');
        return;
    }
    $this->getResponse()->setHeader('Login-Required', 'true');
    $this->loadLayout();

    $update = $this->getLayout()->getUpdate();
    $update->addHandle('customer_account_login');
    $this->loadLayoutUpdates();
    $this->generateLayoutXml();
    $this->generateLayoutBlocks();
    $this->_isLayoutLoaded = true;

    $blockList = $this->getLayout()->getBlock('customer_form_login');
    $template = $blockList->getTemplate();
    $blockChildBlock = $blockList->getChild();

    $this->getLayout()->unsetBlock('customer_form_login');
    $parentBlock = $this->getLayout()->createBlock('blockname/customer_form_login','customer_form_login')->setTemplate($template);

    if($blockChildBlock){
        foreach($blockChildBlock as $childBlock){
            $this->getChildBlockLogin($parentBlock,$childBlock);
        }
    }
    $this->_initLayoutMessages('customer/session');
    $this->_initLayoutMessages('catalog/session');
    $this->renderLayout();   
 }
}

public function getChildBlockLogin($parentBlock,$childBlock){

    /*echo "ChildB: ".$childBlock->getNameInLayout()."<br/>";
    echo "Alias: ".$childBlock->getBlockAlias()."<br/>";
    echo "Child: ".$childBlock->countChildren()."<br/>";
    echo "Type: ".$childBlock->getType()."<br/>";
    echo "Template: ".$childBlock->getTemplate()."<br/>";*/
    $childName = $childBlock->getNameInLayout();

    if($childBlock->getBlockAlias()!=''){
        $childName = $childBlock->getBlockAlias();
    }
    if($childBlock->getTemplate()!=''){
        //$child = $this->getLayout()->createBlock($childBlock->getType(),$childName)->setTemplate($childBlock->getTemplate());
        $parentBlock->setChild($childName,$childBlock);
    }
    else{
        //$child = $this->getLayout()->createBlock($childBlock->getType(),$childName);
        $parentBlock->setChild($childName,$childBlock);
    }
    $parentBlockData = $this->getLayout()->getBlock($childBlock->getNameInLayout());
    $blockChildBlockData = $parentBlockData->getChild();
    if($blockChildBlockData){
        foreach($blockChildBlockData as $childBlockData){
            $this->getChildBlockLogin($parentBlockData,$childBlockData);
        }
    }       
 }
}

Create block "\app\code\local\Namespace\ModuleName\Block\Customer\Form\Login.php"

class ModuleName_ModuleName_Block_Customer_Form_Login extends Mage_Customer_Block_Form_Login{
  public function getPostActionUrl(){
     return Mage::getUrl('modulefrontname/account/loginPost');
 }
}

From this code you can also copy original block child block in new created block. Try below code to test child blocks

<customer_account_login translate="label">
    <label>Customer Account Login Form</label>
    <!-- Mage_Customer -->
    <remove name="right"/>
    <remove name="left"/>

    <reference name="root">
        <action method="setTemplate"><template>page/1column.phtml</template></action>
    </reference>
    <reference name="content">
        <block type="customer/form_login" name="customer_form_login" template="customer/form/login.phtml">
            <block type="core/template" name="test.block" template="customer/form/test.phtml" >
                <block type="core/template" name="test.block1" as="testB1" template="customer/form/test1.phtml" />
            </block>
        </block>
    </reference>
</customer_account_login>

Create file in "\app\design\frontend\base\default\template\customer\form\test.phtml"

<?php echo $this->getChildHtml('testB1')?>

Create file in "\app\design\frontend\base\default\template\customer\form\test1.phtml"

Child Block<br/>

This code return error while enable cache from admin. To fixed that issue we have to comment below code

/*$update = $this->getLayout()->getUpdate();
$update->addHandle('customer_account_login');
$this->loadLayoutUpdates();
$this->generateLayoutXml();
$this->generateLayoutBlocks();
$this->_isLayoutLoaded = true;*/

and created layout file in "\app\design\frontend\base\default\layout\layoutname.xml "

<?xml version="1.0"?>
<layout version="0.1.0">
    <layout_handler translate="label">
        <update handle="customer_account_login"/>
    </handler>
</layout>

This is not best solution for me because i did not want to use .xml file. Please suggest me if any one get good solution for this issue.

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.