I am writing an extension that creates a menu. The menu pulls the top-level categories of the store and displays subcategories in a dropdown menu. Also in the dropdown menu is a callout, which is actually a static block. In System->Configuration, administrators can choose a different callout for each top-level category. picture of callout

The way I have done this is by writing a custom frontend_model that grabs the top-level categories for the currently selected store scope. A text field is created for each top-level category where the identifier of a static block can be entered. When the menu is being built on the frontend, if the static block exists, it will be added into the dropdown menu of its associated top-level category.

class Cbad_Shoppablemenu_Block_Adminhtml_System_Config_Form_Fieldset_DynamicCallouts extends Mage_Adminhtml_Block_System_Config_Form_Fieldset {
    protected $_fieldRenderer;

    public function render(Varien_Data_Form_Element_Abstract $element)
        $html = $this->_getHeaderHtml($element);

        foreach ($element->getSortedElements() as $field) { 
            $html .= $field->toHtml(); // get static field html

        $store = Mage::app()->getRequest()->getParam('store');
        if($store) {
            $storeCode = Mage::getModel('core/store')->getCollection()->addFieldToFilter('code', $store);
            $storeItem = $storeCode->getFirstItem();
            $rootId = $storeItem->getRootCategoryId();
            $rootCategories = Mage::getModel('shoppablemenu/category')->getSubCats($rootId);
            $html .= '<p>Custom Callouts can be used to display a promotional area in the Shoppable Menu. Enter the identifier of the static block that you want to associate to a root category. Leave blank to use default.</p>';
            foreach ($rootCategories as $rootCat) {
                $html .= $this->_getFieldHtml($element, $rootCat); // get dynamic field html
        else {
            $html .= '<p>Custom Callouts can only be set at the "Store" Configuration Scope.</p>';
        $html .= $this->_getFooterHtml($element);

        return $html;

    protected function _getFieldRenderer()
        if (empty($this->_fieldRenderer)) {
            $this->_fieldRenderer = Mage::getBlockSingleton('adminhtml/system_config_form_field');
        return $this->_fieldRenderer;

    protected function _getFieldHtml($fieldset, $category)
        $configData = $this->getConfigData();
        $path = 'shoppablemenu/dynamic_callouts/category_'.$category->getId();
        if (isset($configData[$path])) {
            $data = $configData[$path];
            $inherit = false;
        } else {
            $data = (string)$this->getForm()->getConfigRoot()->descend($path);
            $inherit = true;

        $field = $fieldset->addField($category->getId(), 'text',
                'name'          => 'groups[dynamic_callouts][fields][category_'.$category->getId().'][value]',
                'label'         => $category->getName(),
                'value'         => $data,
                'inherit'       => $inherit,

        return $field->toHtml();

Configuration screenshot

Everything works. My question is if I should be worried about efficiency. A coworker thinks that administrators accessing System->Configuration may slow down the frontend of the site. I really don't think it is much of an issue but he wants to be sure.

This is on an offline development server so we don't have too many ways to test this.

2 Answers 2


A coworker thinks that administrators accessing System->Configuration may slow down the frontend of the site.

That doesn't look particularly problematic to me -- Magento's backend is typically under a very light traffic load -- i.e. you might have dozens of administrators (not thousands or tens of thousands) hitting that page at once. Unless your MySQL server is horribly tuned, the extra SQL queries needed to fetch the category data isn't going to bring things to a grinding halt.

If your coworker brings you evidence that this IS a problem true, pop the rendered HTML into Magento's cache, and add a category create/delete listener that will clear your new cache key whenever a category is saved/deleted.

  • 1
    Is there any reason not to do this? We weren't able to find any reputable modules that dynamically add fields like I've done here; at most they populate potential values in a dropdown/multiselect. Commented Dec 9, 2015 at 18:56

The menu visibility is already managed in Catalog -> Manage Categories - it would probably make sense to put the static block configuration in the same place so that the menu can be controlled from a single point in the backend.

  • It would be my fallback if there was an efficiency problem with my solution. The reason I elected not to take this approach is because I think it makes more sense to keep extension configuration in its proper section (System->Config). Also, it only makes sense to be able to choose a callout for top-level categories, not all categories (it would never be activated for a subcategory). Commented Dec 9, 2015 at 15:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.