4

I'm wondering if I'm doing something wrong, or there's a 'bug' in Magento.

When I add a couple of widgets in the same package/theme, say 'base/default', the sort order works just fine.

But, when I want to add a widget in a different package (customer/default) that has to show between those widgets, it's not working, this widget shows up at the end of all the base/default widgets.

So for example:

  1. Widget 1 - base/default - Sort order 1
  2. Widget 2 - base/default - Sort order 2
  3. Widget 3 - customer/default - Sort order 3
  4. Widget 4 - base/default - Sort order 4

This is not working correctly, Widget 3 shows up after Widget 4. Is this a bug, or am I doing something wrong, or does this work 'as designed'?

Thanks in advance!

  • This is for the cms pages, right? Can you maybe show us the code you are using to embed the widgets? – Duke Dylan May 13 '14 at 22:23
  • Which CE/EE version are you working with? Would be interesting to reproduce. – Anna Völkl Jun 5 '14 at 10:49
  • I just tried to reproduce it but I'm not sure which sort order is wrong on your side or where you think it goes wrong. Please add some more information and a screenshot. – Anna Völkl Jun 5 '14 at 11:03
2

I was struggling with widget sort order today, too, and I found this to be strange behaviour. The root cause of this issue is /app/code/core/Mage/Core/Model/Resource/Layout.php in current 1.9 core (which looked the same down in 1.6):

/**
 * Retrieve layout updates by handle
 *
 * @param string $handle
 * @param array $params
 * @return string
 */
public function fetchUpdatesByHandle($handle, $params = array())
{
    $bind = array(
        'store_id'  => Mage::app()->getStore()->getId(),
        'area'      => Mage::getSingleton('core/design_package')->getArea(),
        'package'   => Mage::getSingleton('core/design_package')->getPackageName(),
        'theme'     => Mage::getSingleton('core/design_package')->getTheme('layout')
    );

    foreach ($params as $key => $value) {
        if (isset($bind[$key])) {
            $bind[$key] = $value;
        }
    }
    $bind['layout_update_handle'] = $handle;
    $result = '';

    $readAdapter = $this->_getReadAdapter();
    if ($readAdapter) {
        $select = $readAdapter->select()
            ->from(array('layout_update' => $this->getMainTable()), array('xml'))
            ->join(array('link'=>$this->getTable('core/layout_link')), 
                    'link.layout_update_id=layout_update.layout_update_id',
                    '')
            ->where('link.store_id IN (0, :store_id)')
            ->where('link.area = :area')
            ->where('link.package = :package')
            ->where('link.theme = :theme')
            ->where('layout_update.handle = :layout_update_handle')
            ->order('layout_update.sort_order ' . Varien_Db_Select::SQL_ASC);

        $result = join('', $readAdapter->fetchCol($select, $bind));
    }
    return $result;
}

What happens here is that sort order is only used for sorting layout updates for a unique combination of store, area (e.g. frontend, package (base or customer in your case), theme (default) and layout handle (e.g. catalog_category_view).

Therefore, across different combinations, sort order does not yield the expected results.

I found a solution by rewriting two core classes and put it in an extension here: https://github.com/gruenspar/magento-sorted-db-layouts

It is untested in this exact form (as we have some more rewrites on these classes, unfortunately), but the main idea is working flawlessly for us.

If you encounter issues when installing it, let me know.

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.