How To Create a Suite of Modules in Magento

Posted by Carlo Tasca on 17 September 2012

In a recent project, I had to deal with creating a suite of modules in Magento (a module that contains other modules). After several searches on Google, I realised that nobody had created a proper solution for this - I was looking to create the following module structure:

app/code/local/Company/SuiteModule
app/code/local/Company/SuiteModule/Core
app/code/local/Company/SuiteModule/OtherModule

After setting up the above structure, I started testing whether Blocks, Helpers and Models could be instantiated correctly by Magento Factory methods, and I also tested setting up resources for each module to ensure that they would install correctly. 

The following structure would work perfectly in Magento without any modification:

app/code/local/Company/SuiteModule
app/code/local/Company/SuiteModule/etc
app/code/local/Company/SuiteModule/Helper
app/code/local/Company/SuiteModule/Model
app/code/local/Company/SuiteModule/Core
app/code/local/Company/SuiteModule/Core/etc
app/code/local/Company/SuiteModule/Core/Block
app/code/local/Company/SuiteModule/Core/Helper
app/code/local/Company/SuiteModule/Core/Model
app/code/local/Company/SuiteModule/OtherModule
app/code/local/Company/SuiteModule/OtherModule/etc
app/code/local/Company/SuiteModule/OtherModule/Block
app/code/local/Company/SuiteModule/OtherModule/Helper
app/code/local/Company/SuiteModule/OtherModule/Model

Magento Factory methods would look as follows:

Mage::helper('suitemodule');
Mage::getModel('suitemodule/model');
Mage::helper('suitemodule_core');
Mage::getModel('suitemodule_core/model');
Mage::helper('suitemodule_othermodule');
Mage::getModel('suitemodule_othermodule/model');

The problems with such a module structure started when I tried adding controllers to nested Modules. Magento could not correctly route the request to the correct controller. This sent me back on Google big time!!!

After a bit of searching I found a post on the Magento Forum that put me in the right direction...Read post here.

I had to find a way to have my own implementation of getControllerFileName method defined in Mage_Core_Controller_Varien_Router_Standard class. After a bit of thinking I decided that creating custom routers for the suite of modules would have allowed me to implement getControllerFileName as I needed.

I didn't want the new router's classes encapsulated in the suite though, as projects with similar requirements could come up. Because I was not overriding any already defined Magento class, I thought the best way would be to put the new routers in local/Mage/Core namespace (extending like this Mage Core codebase).

I added app/code/local/Mage directory and defined the following:

app/code/local/Mage/Core/Controller/Varien/Router/Suite.php
app/code/local/Mage/Core/Controller/Varien/Router/Suiteadmin.php

In app/code/local/Mage/Core/Controller/Varien/Router/Suite.php I defined getControllerFileName method as follow:

public function getControllerFileName($realModule, $controller)
    {
        $parts = explode('_', $realModule);
        $realModule = implode('_', array_splice($parts, 0, 3));
        $file = Mage::getModuleDir('controllers', $realModule);
        if (count($parts)) {
            $file .= DS . implode(DS, $parts);
        }
        $file .= DS.uc_words($controller, DS).'Controller.php';
        return $file;
    }

All I did in the above method was change the following line:

$realModule = implode('_', array_splice($parts, 0, 2));

to:

$realModule = implode('_', array_splice($parts, 0, 3));

The final step was to edit config.xml for my suite modules and set them to use the suite routers instead of Magento Standard/Admin ones.

Firstly, I had to register the router in 'default/web' config area:

	

<default>
		<web>
			<routers>
				<suiteadmin>
                    <area>admin</area>
                    <class>Mage_Core_Controller_Varien_Router_Suiteadmin</class>
                </suiteadmin>
				<suite>
					<area>frontend</area>
					<class>Mage_Core_Controller_Varien_Router_Suite</class>
				</suite>		
			</routers>
		</web>
</default>

And then to specify routers for frontend and admin config area:

<frontend>
	<routers>
		<othermodule>
			<use>suite</use>
			<args>
				<module>GPMD_SuiteModule_OtherModule</module>
				<frontName>othermodule</frontName>
			</args>
		</othermodule>
	</routers>
</frontend>

<admin>
        <routers>
            <othermodule>
                <use>suiteadmin</use>
                <args>
                    <module>GPMD_SuiteModule_OtherModule</module>
                    <frontName>othermodule</frontName>
                </args>
            </othermodule>
        </routers>
</admin>

That's it!!!

Comments

No one has commented on this page yet.

Post your comment