Reputation: 3523
Basically we have a lot of clients that have multiple websites and we have to write a lot of modules for them. Sometimes an extension may override some functionality that Magento's core does by default and they want to do this for one store but not another. Obviously we can put logic in the code to see what store it is but I am thinking there is something more elegant way to do this.
Upvotes: 1
Views: 759
Reputation: 1379
Good question.
I would have solved this problem on another way. Module structure:
Custom
| - Module
| - - Model
| - - - Product.php
| - - - Customer.php
For my opinion it is need to be created class that depends from store. If you want to create some functionality for Store UK, you need to declare this class for UK store, write it in configuration file and call it with factory class. For example in the config.xml
<config>
<stores>
<store_uk>
<catalog_product>Custom_Module_Model_Store_Uk_Product</product_attribute>
<customer>Custom_Module_Model_Store_Uk_Customer</customer>
</store_uk>
<store_en>
<catalog_product>Custom_Module_Model_Store_En_Product</catalog_product>
</store_en>
</stores>
</config>
Create class store router:
class Custom_Module_Model_Store_Router
{
public function callMethod($method, $args)
{
if (strpos($method, '/') !== false) {
$method = explode('/', $method);
}
if (count($method) != 2) {
return false;
}
$handler = $method[0];
$method = $method[1];
$object = $this->_getObject($handler);
if ($object) {
//already checked if method exists
retun $object->$method($args);
}
return false;
}
public function hasStoreMethod($method)
{
if (strpos($method, '/') !== false) {
$method = explode('/', $method);
}
if (count($method) != 2) {
return false;
}
$handler = $method[0];
$method = $method[1];
$object = $this->_getObject($handler);
if (method_exists($object, $method)) {
//Bingo
return true;
}
return false;
}
protected function _getObject($handler)
{
$storeCode = Mage::app()->getStore(true)->getCode();
$handlerClassName = Mage::getStoreConfig($storeCode . '/' . $handler);
if (empty($handlerClassName)) {
return false;
}
$handlerInstance = Mage::getModel($handlerClassName);
//here we can save instance into the _handlers etc.
return $handlerInstance;
}
}
This class will be as default customization
//in your custom module product class
Custom_Module_Model_Product extends Mage_Catalog_Model_Product_Attribute
{
public function getAttributes($groupId = null, $skipSuper = false)
{
$routerStore = Mage::getSingleton('custom_module/store_router');
if ($routerStore->hasStoreMethod('catalog_product/getAttributes')) {
$attributes = $routerStore->callMethod('catalog_product/getAttributes', array('groupId' => $groupId, 'skipSuper' => $skipSuper));
return $attributes;
}
return parent::getAttributes($groupId, $skipSuper);
}
}
And this class is store Uk class only
//custom module product class for uk store
Custom_Module_Model_Store_Uk_Product extends Mage_Catalog_Model_Product_Attribute
{
public function getAttributes($groupId = null, $skipSuper = false)
{
$attributes = parent::getAttributes($groupId, $skipSuper);
// do some specific stuff
return $attributes;
}
}
After this steps you will have clear customization classes with module structure listed below:
Custom
| - Module
| - - Model
| - - - Store
| - - - - Uk
| - - - - - Product.php
| - - - - - Customer.php
| - - - - En
| - - - - - Product.php
| - - - - Router.php
| - - - Product.php
| - - - Customer.php
I hope this will help for your multistore development
Upvotes: 2
Reputation: 27119
Here is a common idiom I have used in the past. It works well when you are modifying the existing logic by overriding classes and modifying the functions on a one-off basis:
public function overriddenFunc($arg) {
if(!$this->checkIfModuleIsEnabledForStore()) {
return parent::overriddenFunc($arg);
}
// do your magic here
return $something;
}
It basically functions as a passthrough on the functionality override whenever the module is not enabled. Then, you can use a store-level configuration setting to turn the functionality on and off by store.
To keep yourself sane, make sure to override only the minimum necessary functions to get by.
Hope that helps!
Thanks, Joe
Upvotes: 4
Reputation: 713
I think the only way to achieve this is to customize the logic how module is loaded it's configuration, because all rewrites depends on customization only.
My first idea how to do this was to override Mage_Core_Model_Config::_loadDeclaredModules()
or Mage_Core_Model_Config::_getDeclaredModuleFiles()
and check there store id before load config file, but I've realized, that store id isn't initialized yet when this methods is called: if you look at Mage_Core_Model_App::run()
you will see that _initCurrentStore()
is called later.
The second idea: customize fabric method Mage::getModel()
. If you look at Mage_Core_Model_Config::getGroupedClassName()
you'll see that it takes modules, blocks, helpers, etc configuration from node global
. You could override this method to make it take all this configuration from node 'stores/current_store_code'
, so all rewrites will be loaded for current store only.
But I'm not sure on 100% are these solution implementable.
Upvotes: 0