1

Currently I have two different controllers and Magento checkout is split into two ways, let's say A and B, thus URL is checkout/A checkout/B - both available for customer. Both of them are onepage checkout. For both of them I have layout XML file; for B I'm removing many blocks from whole page so it's very simplified. I would like to move these changes to one URL, so by some settings there will be displayed checkout A or checkout B randomly. How to force in custom controller changes that I made with layout XML file?

  • did you have 2 modules for each checkouts ? – Rajeev K Tomy Jun 26 '14 at 11:06
  • One module that overrides default Magento Checkout. – Filip Górczyński Jun 26 '14 at 11:47
  • so one controller that you referenced is default one and other one is from your module itself. Am I right ? – Rajeev K Tomy Jun 26 '14 at 11:50
  • I have 2 controllers in one module. Onepage checkout overrides Magento OnepageCheckout. Second controller - Simplified version of Magento OnePageCheckout. – Filip Górczyński Jun 26 '14 at 12:14
3

Here I am demonstrating what is your current state(According to my understanding) and how to solve your problem.

So you have basically two controllers that is defined for checkout. The url paths that invoke your controllers then somewhat look like this www.yoursite.com/index.php/checkout/a (For controller with name A) and www.yoursite.com/index.php/checkout/b(For controller with name B). I assume indexAction() method in your controllers are used to load and render the layouts. They loads their own layouts. Everything is perfect untill here. Now you want to render layout that render by controller B along with layouts of controller A, when www.yoursite.com/index.php/checkout/a is requested.

You can achieve this in two ways (There may be other ways).

  • Through an event observer

  • through controller A

Through an event observer

We are going to listen to the event controller_action_layout_load_before. This event will call before any layout loads. We will inject the layout of controller B to that of control A. So

Config.xml

<config>
    <frontend>
        <events>
            <controller_action_layout_load_before>
                <observers>
                    <checkout_controller_action_layout_load_before>
                        <class>programmerrkt_checkout/observer</class>
                        <method>controllerActionLayoutLoadBefore</method>
                    </checkout_controller_action_layout_load_before>
                </observers>
            </controller_action_layout_load_before>
        </events>
    </frontend>
</config>

Observer

<?php
class Programmerrkt_Checkout_Model_Observer
{
        const LAYOUT_HANDLE_TO_CHECK_WITH = 'checkout_a_index';
        const LAYOUT_HANDLE_TO_ATTACH = 'checkout_b_index';
        public function controllerActionLayoutLoadBefore(Varien_Event_Observer $observer)
        {
            /** @var $layout Mage_Core_Model_Layout_Update */
            $update = $observer->getEvent()->getLayout()->getUpdate();
            $handles = $update->getHandles(); //get all handles 
            //If layout handle of controller A is not in action,  will not attach the handles
            if(in_array(self::LAYOUT_HANDLE_TO_CHECK_WITH , $handles))
            {
                $update->addHandle(self::LAYOUT_HANDLE_TO_ATTACH);
            }    
        }
}

Through Controller Method

Now we can load layout of controller B through controller A. This is little tricky. This is because we cannot use loadLayout() method, if we are planning to use controller for this purpose. Why ? this THREAD gives an answer for that (checkout alanstorm's answer). In short, if we add handle of controller B (checkout_b_index in this case), before or after the method loadLayout(), its not going to make any difference. So what we need to do is, we need to replace loadLayout() with our codes, so that checkout_index_b handle also added to the layout tree of controller A.

So your controller A should look like this.

 public function indexAction()
{
    //code follows some what replaces loadLayout() method
    $update = $this->getLayout()->getUpdate(); 
    $update->addHandle('default'); //attach layout handle of for controller A
    $this->addActionLayoutHandles(); 
    $update->addHandle('checkout_b_index'); //attach layout handle of controller B
    $this->loadLayoutUpdates();
    $this->generateLayoutXml();
    $this->generateLayoutBlocks();
    $this->_isLayoutLoaded = true;


    $this->renderLayout();
}

That's it. Now load the url www.yoursite.com/index.php/checkout/a. You can see content of both A and B in there.

Check my blog for better understanding http://rajeev-k-tomy.blogspot.in/2014/06/add-layout-to-another-layout.html

1

In your controller, you can always add another layout handle:

$update = $this->getLayout()->getUpdate();
$update->addHandle('layout_b_changes');

And then you make all the relevant changes in your layout XML file.

  • What shoul layout_b_changes in addHandle() contain? I tried with layout XML element name, block name, and few other but nothing worked. – Filip Górczyński Jun 26 '14 at 12:33
  • Don't forget to add $this->loadLayoutUpdates(); for the changes to take effect – Mayers Jun 26 '14 at 19:29
0

Source code from page http://makandracards.com/magento/8209-adding-a-layout-handle-from-a-controller solved my problem.

  • Please add at least an abstract of the page, so when the link is dead, your answer is still valuable. – Fabian Blechschmidt Jun 26 '14 at 22:39

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.