基本上我们有很多拥有多个网站的客户,我们必须为他们编写很多模块。有时,扩展可能会覆盖Magento的核心默认执行的某些功能,他们希望为一个商店而不是另一个商店执行此操作。显然我们可以在代码中放置逻辑来查看它是什么存储但是我认为有一些更优雅的方法来做到这一点。
答案 0 :(得分:4)
这是我过去常用的常用词。当您通过重写类并一次性修改函数来修改现有逻辑时,它可以正常工作:
public function overriddenFunc($arg) {
if(!$this->checkIfModuleIsEnabledForStore()) {
return parent::overriddenFunc($arg);
}
// do your magic here
return $something;
}
只要模块未启用,它就基本上可以作为功能覆盖的直通。然后,您可以使用商店级配置设置来按商店打开和关闭功能。
为了保持理智,请务必仅覆盖必要的最少功能。
希望有所帮助!
谢谢, 乔
答案 1 :(得分:2)
好问题。
我会以另一种方式解决这个问题。 模块结构:
Custom
| - Module
| - - Model
| - - - Product.php
| - - - Customer.php
对于我的观点,需要创建依赖于商店的类。 如果要为Store UK创建一些功能,则需要为UK store声明此类,将其写入配置文件并使用工厂类调用它。 例如在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>
创建类存储路由器:
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;
}
}
此类将作为默认自定义
//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);
}
}
这个类只是存储Uk类
//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;
}
}
完成此步骤后,您将拥有清晰的自定义类,其模块结构如下所示:
Custom
| - Module
| - - Model
| - - - Store
| - - - - Uk
| - - - - - Product.php
| - - - - - Customer.php
| - - - - En
| - - - - - Product.php
| - - - - Router.php
| - - - Product.php
| - - - Customer.php
我希望这有助于您的多线程开发
答案 2 :(得分:0)
我认为实现这一目标的唯一方法是自定义模块如何加载其配置的逻辑,因为所有重写仅取决于自定义。
我的第一个想法是如何覆盖Mage_Core_Model_Config::_loadDeclaredModules()
或Mage_Core_Model_Config::_getDeclaredModuleFiles()
并在加载配置文件之前检查存储ID,但我已经意识到,存储ID尚未初始化调用方法:如果查看Mage_Core_Model_App::run()
,您会看到稍后调用_initCurrentStore()
。
第二个想法:自定义结构方法Mage::getModel()
。如果你看一下Mage_Core_Model_Config::getGroupedClassName()
,你会发现它需要来自节点global
的模块,块,帮助器等配置。您可以覆盖此方法以使其从节点'stores/current_store_code'
获取所有此配置,因此将仅为当前存储加载所有重写。
但我不确定100%是否可以实现这些解决方案。