2011-01-14 46 views
1

基本上我们有很多客户有多个网站,我们必须为他们编写很多模块。有时候,一个扩展可能会覆盖Magento的核心在默认情况下所做的一些功能,他们希望为一个商店做到这一点,而不是另一个。显然,我们可以在代码中放置逻辑来查看它存储的是什么,但我认为有一些更优雅的方法可以做到这一点。什么是限制商店或网站模块功能的最佳方式

回答

2

好问题。

我会以另一种方式解决这个问题。 模块结构:

Custom 
| - Module 
| - - Model 
| - - - Product.php 
| - - - Customer.php 

针对我的意见是需要创建类,从商店的依赖。 如果您想为Store UK创建一些功能,则需要为UK store申报此类,并将其写入配置文件并使用工厂类来调用它。 例如在配置中。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); 
    } 
} 

这个类是店里屋类只

//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 

我希望这将有助于您的MultiStore发展

+0

非常好,我认为这是解决方案,如果有人想这样做。 – 2011-01-17 14:12:11

0

我认为实现这一目标的唯一方法是定制逻辑模块如何加载它的配置,因为所有的重写只取决于定制。

我最初的想法如何做到这一点是覆盖Mage_Core_Model_Config::_loadDeclaredModules()Mage_Core_Model_Config::_getDeclaredModuleFiles()之前加载配置文件,检查有没有店铺标识,但我意识到,店铺ID尚未初始化时,该方法被调用:如果你看看在Mage_Core_Model_App::run()你会看到_initCurrentStore()稍后调用。

第二个想法:自定义面料方法Mage::getModel()。如果您查看Mage_Core_Model_Config::getGroupedClassName(),您会发现它需要从节点global获取模块,块,助手等配置。您可以重写此方法以使其从节点'stores/current_store_code'中获取所有此配置,因此所有重写都将仅用于当前存储。

但我不确定100%是否可以实现这些解决方案。

+0

呀,这些都是一些很好的想法,我会惹他们一点点,但它似乎是一个有点多为了我们的情况。我并不想真正地将其深入到核心中,我认为将模块中的逻辑放在检查它是什么存储的情况下可能会更好。 – 2011-01-14 15:06:09

4

这是我过去常用的习语。它运作良好,当你被重写类和一次性的基础上修改的功能修改现有的逻辑:

public function overriddenFunc($arg) { 
    if(!$this->checkIfModuleIsEnabledForStore()) { 
     return parent::overriddenFunc($arg); 
    } 

    // do your magic here 
    return $something; 
} 

它主要用作该功能覆盖直通只要不启用该模块。然后,您可以使用商店级配置设置来通过商店打开和关闭功能。

为了保持自己的正常,请确保只覆盖必要的最小功能。

希望有帮助!

谢谢, 乔

+0

谢谢约瑟夫,这是一个相当不错的方法。 – 2011-01-14 16:05:38

相关问题