How i can change block type programmatically from controller.
1 Answer
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.