【问题标题】:Magento: Disable module for any particular storeMagento:禁用任何特定商店的模块
【发布时间】:2011-08-23 03:42:24
【问题描述】:

假设,我有 3 家商店。

我想禁用 Store 2 中的一个模块。我只想在 Store 1 和 Store 3 中启用它。

我知道我可以这样做:-

  • 转到系统 -> 配置 -> 高级

  • 当前配置范围下拉列表中选择所需的商店。

但这并不完全有效。

而且,我也不想在模块代码本身中检查存储或为模块创建系统配置字段以检查/取消选中存储以启用/禁用。

我期待的是在 app/etc/modules/MyNamespace_MyModule.xml 中添加一些代码。我们可以这样做吗?

【问题讨论】:

  • 我经常遇到这种情况...为什么不容易?! ????‍♂️

标签: configuration magento module


【解决方案1】:

我使用 Eric 解决方案有一段时间了。在我的情况下,我在我的一家商店中禁用了负责分层导航的某些模块 - 从而返回到默认的分层导航行为。

它看起来像它的工作,但过了一段时间我注意到分层导航选项停止出现在它们应该出现的位置。很快我就注意到,实际上不应该在这家商店工作的模块继续工作。然后我意识到,当我禁用配置缓存时,Eric 的解决方案有效,但再次启用后它停止了。

过了一会儿,我意识到它必须以这种方式工作,启用配置缓存,因为 Eric 的解决方案仅在生成此 xml 时在全局 xml 中包含(或不包含)指定的配置文件。然后它被缓存并仅从缓存中调用。因此,当它从应该使用某些模块的站点生成时,它被包含在内,然后也在不应该使用它的站点上使用。

无论如何,我根据 Eric 的代码(在模块配置中使用 restricted)制定了另一个解决方案。我认为 Magento 应该决定在请求课程时加载什么。然后它可以检查当前 MAGE_RUN_CODE 是什么并动态使用它。

Mage_Core_Model_Config中有一个方法负责获取类名:getGroupedClassName

这是我在那里使用的代码:

if (strpos($className, 'Pneumatig_') !== false) {
    $var = substr($className, 0, strpos($className, '_', strpos($className, '_') + 1));
    if (isset($this->_xml->modules->$var)) { 
        if ((bool)$this->_xml->modules->$var->restricted === true) {
            $code = isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : 'default';
            if (strpos((string)$this->_xml->modules->$var->restricted, $code) !== false) {
                $className = '';
            }
        }
    }
}

这个Pneumatig 条件是因为我所有的模块都以公司名称开头,所以我想避免不必要的处理,但它是可选的,代码应该在没有它的情况下工作,或者你可以将其更改为其他任何内容。

然后我得到实际的模块名称​​[Company]_[Module],然后检查它是否在_xml(这是当前配置对象)中启用。如果它受到限制,我会清除 $className 以强制 Magento 在下一行加载默认值。

并且这段代码是在空条件之前添加的:

    // Second - if entity is not rewritten then use class prefix to form class name
    if (empty($className)) {
        if (!empty($config)) {
            $className = $config->getClassName();
        }
        if (empty($className)) {
            $className = 'mage_'.$group.'_'.$groupType;
        }
        if (!empty($class)) {
            $className .= '_'.$class;
        }
        $className = uc_words($className);
    }

    $this->_classNameCache[$groupRootNode][$group][$class] = $className;
    return $className;

为了您的方便,我粘贴了整个 getGroupedClassName 代码:

public function getGroupedClassName($groupType, $classId, $groupRootNode=null)
{
    if (empty($groupRootNode)) {
        $groupRootNode = 'global/'.$groupType.'s';
    }

    $classArr = explode('/', trim($classId));
    $group = $classArr[0];
    $class = !empty($classArr[1]) ? $classArr[1] : null;

    if (isset($this->_classNameCache[$groupRootNode][$group][$class])) {
        return $this->_classNameCache[$groupRootNode][$group][$class];
    }

    $config = $this->_xml->global->{$groupType.'s'}->{$group};

    // First - check maybe the entity class was rewritten
    $className = null;
    if (isset($config->rewrite->$class)) {
        $className = (string)$config->rewrite->$class;
    } else {
        /**
         * Backwards compatibility for pre-MMDB extensions.
         * In MMDB release resource nodes <..._mysql4> were renamed to <..._resource>. So <deprecatedNode> is left
         * to keep name of previously used nodes, that still may be used by non-updated extensions.
         */
        if (isset($config->deprecatedNode)) {
            $deprecatedNode = $config->deprecatedNode;
            $configOld = $this->_xml->global->{$groupType.'s'}->$deprecatedNode;
            if (isset($configOld->rewrite->$class)) {
                $className = (string) $configOld->rewrite->$class;
            }
        }
    }

    //START CHECKING IF CLASS MODULE IS ENABLED
    if (strpos($className, 'Pneumatig_') !== false) {
        $var = substr($className, 0, strpos($className, '_', strpos($className, '_') + 1));
        if (isset($this->_xml->modules->$var)) { 
            if ((bool)$this->_xml->modules->$var->restricted === true) {
                $code = isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : 'default';
                if (strpos((string)$this->_xml->modules->$var->restricted, $code) !== false) {
                    $className = '';
                }
            }
        }
    }
    //END CHECKING IF CLASS MODULE IS ENABLED

    // Second - if entity is not rewritten then use class prefix to form class name
    if (empty($className)) {
        if (!empty($config)) {
            $className = $config->getClassName();
        }
        if (empty($className)) {
            $className = 'mage_'.$group.'_'.$groupType;
        }
        if (!empty($class)) {
            $className .= '_'.$class;
        }
        $className = uc_words($className);
    }

    $this->_classNameCache[$groupRootNode][$group][$class] = $className;
    return $className;
}

【讨论】:

    【解决方案2】:

    我的客户安装的 Magento 1.8.1.0 有一个有问题的模块,它在多商店设置中破坏了另一个站点的菜单。上面 Eric Hainer 发布的解决方案不适用于此安装,因此我对其稍作修改:

    我没有使用$_SERVER['MAGE_RUN_CODE'],而是使用了$_SERVER['SERVER_NAME']。像魅力一样工作。 :)

    所以而不是:

    $runCode = (isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : 'default');
    

    使用:

    $runCode = (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'www.site1.com');
    

    而不是:

    <restricted>mystore1,mystore4,mystore5</restricted>
    

    使用:

    <restricted>www.site2.com,www.site3.com</restricted>
    

    显然将“www.site1.com”、“www.site2.com”和“www.site3.com”更改为您自己的位置。

    感谢埃里克的想法 :)

    【讨论】:

      【解决方案3】:

      【讨论】:

      • 请注意 link-only answers 是不鼓励的,所以答案应该是寻找解决方案的终点(与另一个中途停留的参考相比,随着时间的推移往往会变得陈旧)。请考虑在此处添加独立的概要,并保留链接作为参考。
      【解决方案4】:

      要禁用商店范围内的模块,我发现可以这样做:

      将 app/code/core/Mage/Core/Model/Config.php 移动到 app/code/local/Mage/Core/Model/Config.php

      在 Config.php 中找到方法“loadModulesConfiguration” 什么都不做,添加如下代码,使方法看起来像这样。

      public function loadModulesConfiguration($fileName, $mergeToObject = null, $mergeModel=null)
      {
          $disableLocalModules = !$this->_canUseLocalModules();
      
          if ($mergeToObject === null) {
              $mergeToObject = clone $this->_prototype;
              $mergeToObject->loadString('<config/>');
          }
          if ($mergeModel === null) {
              $mergeModel = clone $this->_prototype;
          }
          $modules = $this->getNode('modules')->children();
          foreach ($modules as $modName=>$module) {
              if ($module->is('active')) {
                  // Begin additional code
                  if((bool)$module->restricted) {
                      $restricted = explode(',', (string)$module->restricted);
                      $runCode = (isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : 'default');
                      if(in_array($runCode, $restricted)) {
                          continue;
                      }
                  }
                  // End additional code
                  if ($disableLocalModules && ('local' === (string)$module->codePool)) {
                      continue;
                  }
                  if (!is_array($fileName)) {
                      $fileName = array($fileName);
                  }
      
                  foreach ($fileName as $configFile) {
                      $configFile = $this->getModuleDir('etc', $modName).DS.$configFile;
                      if ($mergeModel->loadFile($configFile)) {
                          $mergeToObject->extend($mergeModel, true);
                      }
                  }
              }
          }
          return $mergeToObject;
      }
      

      新代码将导致该方法还检查模块 xml 文件 中的新节点。如果节点存在,则该值将是您不希望模块加载的商店代码的逗号分隔列表。如果您有多个商店,则应使用当前商店代码设置 $_SERVER 变量“MAGE_RUN_CODE”。如果未设置,脚本将回退到假设商店代码为“默认”,这是默认情况下的默认值,除非出于某种奇怪的原因您决定在后端更改它。

      模块 xml 文件可能如下所示:

      <?xml version="1.0"?>
      <config>
          <modules>
              <MyPackage_MyModule>
                  <active>false</active>
                  <restricted>mystore1,mystore4,mystore5</restricted>
                  <codePool>local</codePool>
              </MyPackage_MyModule>
          </modules>
      </config>
      

      这样,在商店代码为 mystore1、mystore4 或 mystore5 的商店中,模块甚至不会加载。 标签是完全可选的,如果你省略它,模块将照常加载。

      【讨论】:

      • 启用缓存时此解决方案不起作用。如果您有任何其他解决方案来禁用模块和模块文件,例如观察者和所有,请告诉我。
      • @Nits:请在下面查看我的解决方案。它基于这个,但我解决了这个缓存问题。适用于 1.9.2.3。
      【解决方案5】:

      此配置只是禁用了前端布局中的模块输出,但模块控制器、事件观察器、管理页面等仍在工作。

      另外不要忘记在布局文件定义中指定您的模块名称,否则将为特定商店加载所有布局文件内容:

      <config>
         <layout>
             <module_alias module="Module_Name">
                 <file>yourlayoutfile.xml</file>
             </module_alias>
         </layout>
      </config>
      

      如果您正在开发一个模块并希望在特定商店的前端禁用其全部功能,那么您应该创建一个“是/否”类型的配置字段并通过 Mage::getStoreConfigFlag('config /field/path') 在你的模块代码中。

      【讨论】:

      • 我知道。我可以为商店启用创建系统配置字段。但是,我只为更改 app/etc/modules 目录中的模块配置文件寻求答案。
      • @chapagain 无法更改每个商店的 app/etc/modules,这是全局配置。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多