假设我有3家商店。
我想禁用商店2中的模块。我只希望在商店1和商店3中启用它。
我看到我能做到: -
转到系统 - >配置 - >高级
从当前配置范围下拉列表中选择所需的商店。
但这并不完全有效。
并且,我也不想在模块代码本身中检查存储,或者为模块创建系统配置字段以检查/取消选中存储以启用/禁用。
我期待的是在 app / etc / modules / MyNamespace_MyModule.xml 中添加一些代码。我们可以这样做吗?
答案 0 :(得分:16)
要禁用商店范围内的模块,我发现可以这样做:
将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文件中的新节点&lt; restricted&gt;。如果节点存在,则该值将是您不希望模块加载的以逗号分隔的商店代码列表。如果您有多个商店,则应使用当前商店代码设置$ _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的商店中,模块甚至不会加载。 &lt;受限制&gt; tag是完全可选的,如果省略它,模块将按正常情况加载。
答案 1 :(得分:4)
此配置仅禁用前端布局中的模块输出,但模块控制器,事件观察器,管理页面等仍然有效。
另外,不要忘记在布局文件定义中指定模块名称,否则将为特定商店加载所有布局文件内容:
<config>
<layout>
<module_alias module="Module_Name">
<file>yourlayoutfile.xml</file>
</module_alias>
</layout>
</config>
如果您正在开发模块并希望在特定商店的前端禁用其功能,那么您应该创建“是/否”类型的配置字段并通过Mage :: getStoreConfigFlag('config'检查其值/ field / path')在模块代码中。
答案 2 :(得分:2)
我正在使用Eric解决方案一段时间。在我的情况下,我在我的一个商店中禁用了负责分层导航的某个模块 - 因此返回到默认的分层导航行为。
它看起来像是在工作,但过了一段时间我发现分层导航选项停止出现在应有的位置。很快我就注意到,实际上不应该在这家商店工作的模块继续工作。然后我意识到,当我禁用配置缓存时,Eric的解决方案可以正常工作,但是再次启用后它会停止。
过了一段时间,我意识到必须以这种方式工作,启用配置缓存,因为Eric的解决方案仅在生成此xml时包含(或不包含)全局xml中的指定配置文件。然后它只缓存并从缓存中调用。所以当它从网站生成时应该使用一些模块,它被包含在内,然后也在网站上使用,而不是假设使用它。
无论如何,我根据Eric的代码(在模块配置中使用受限)制定了另一个解决方案。我认为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;
}
答案 3 :(得分:1)
我的客户安装的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>
明显改变&#34; www.site1.com&#34;,&#34; www.site2.com&#34;,&#34; www.site3.com&#34;与您自己的位置。
感谢Eric的想法:)
答案 4 :(得分:0)