The problem

When implementing a dynamic theme switcher using controller_action_layout_load_before it turns out that certain routes do not have layout handles. This is due to how they load layout; in that technically they don't.

Consider checkout/onepage/progress:

public function progressAction()
    // previous step should never be null. We always start with billing and go forward
    $prevStep = $this->getRequest()->getParam('prevStep', false);

    if ($this->_expireAjax() || !$prevStep) {
        return null;

    $layout = $this->getLayout();
    $update = $layout->getUpdate();
    /* Load the block belonging to the current step*/
    $update->load('checkout_onepage_progress_' . $prevStep);
    $output = $layout->getOutput();
    return $output;

It generates XML and Blocks, but never actually calls loadLayout or renderlayout.

Because of this we cannot use layout handles to affect change. This is not ideal.

The question

Because of this, when affecting a theme change for Onepage checkout I'm forced to parse the requested Route. I don't like this:

public function controllerActionLayoutLoadBefore()
    $request = Mage::app()->getRequest();

    if($request->getModuleName()=='checkout' && $request->getControllerName()=='onepage'){
        //do the theme switching

Is there a better way? I've considered at least issuing loadLayout from a rewrite of OnepageController, but that requires a rewrite and I don't like that.

  • It seems the problem is further complicated - many ajax routes load blocks which should have theme-dependent templates. This likely means that a store switch is required. Any thoughts on how to avoid that? – philwinkle Mar 16 '15 at 14:43
  • Can you not listen to controller_action_predispatch? Pretty sure the area is loaded just before the event which should load the design package singleton, so presumably you could change the package / theme at this point. – Peter O'Callaghan Mar 16 '15 at 15:52

You can listen to the predispatch event. It always gets fired and has the route info that you need.

Use this in your config.xml


Then in the observer you could have-

public function changeTheme($observer) {
  • This is how I worked it out myself. However, it doesn't work with Enterprise Full Page Cache as predispatch isn't fired on cached routes. The search continues! – philwinkle Mar 17 '15 at 16:05

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.