获取Joomla 2.5模块参数,针对未分配给当前页面的模块。

3
我想获取一个未分配给当前页面的模块的参数。帮助类JModuleHelper有一个getModule方法,但如此定义:http://docs.joomla.org/JModuleHelper/getModule,模块必须被分配给当前菜单项或所有菜单项。
显然,我可以进入数据库并自己提取参数,但我想以更整洁的Joomla方式完成它。
我的目标是编写一个库,但该库需要一些参数和自己的数据库表(库不能做这两件事),因此我正在尝试使用模块来填补空白。我需要从库代码中访问模块参数(可以从站点上的任何页面调用该库)。
感谢任何帮助!
我采用的解决方案是将以下代码添加到我的库中:
$db = JFactory::getDbo();
$query = $db->getQuery(true);

$query->select('m.params')
    ->from('#__modules AS m')
    ->where('m.module=' . $db->quote('mod_my_module_name'));
$db->setQuery($query);
$module = $db->loadObject();

$module_params = new JRegistry();
$module_params->loadString($module->params);

我没有将这个答案添加到这个问题中,因为我认为应该有一个更好的解决方案,不直接查询核心数据库。然而,我认为上面的方法目前是最好的解决方案。


更新

根据 Joomla! 开发者组的一个回答,我实现了一个库/插件解决方案。插件可以具有参数,可以使用以下代码从任何地方提取参数:

$plugin = JPluginHelper::getPlugin('plugin_type', 'plugin_name');
$parameteres = new JRegistry($plugin->params);
$param =$parameteres->get('parameter');

插件比模块的优势在于,不需要像模块一样将插件分配给所有项目ID。

经过我进一步的研究,我相信没有关于我的原始问题的优雅解决方案,即获取未分配给当前项目ID的模块参数。因此,如果您发现这个问题是因为您想做类似的事情,那么我建议使用上面的解决方案或cppl下面的解决方案。两者都可以工作,并且它们之间可能没有太大的区别。


你可能想通过将模块分配给所有菜单项,但将其放置在模板中不存在的位置来规避问题。然后,getModule会找到它,我想。但是,如果您需要有时显示它,这可能会很麻烦。 - David Fritsch
1个回答

3
为了绕过这个问题,您可以获取当前文档,然后加载module渲染器。例如,如果我想要使用标题为“体育新闻”的最新新闻模块,则可以使用以下代码:
$module    = 'mod_articles_latest';
$title     = 'Sport News';

$document  = JFactory::getDocument();
$renderer  = $document->loadRenderer('module');
$theModule = JModuleHelper::getModule($module, $title);

因此,为了处理模块未分配给当前或所有菜单项的情况,您可以创建自己的帮助程序,继承自JModuleHelper并覆盖_load()这个受保护的函数。请注意,不要更改html标签。
class MyModuleHelper extends JModuleHelper
{
    protected static function &_load()
    {
        static $clean;

        if (isset($clean))
        {
            return $clean;
        }

        $Itemid = JRequest::getInt('Itemid');
        $app = JFactory::getApplication();
        $user = JFactory::getUser();
        $groups = implode(',', $user->getAuthorisedViewLevels());
        $lang = JFactory::getLanguage()->getTag();
        $clientId = (int) $app->getClientId();

        $cache = JFactory::getCache('com_modules', '');
        $cacheid = md5(serialize(array($Itemid, $groups, $clientId, $lang)));

        if (!($clean = $cache->get($cacheid)))
        {
            $db = JFactory::getDbo();

            $query = $db->getQuery(true);
            $query->select('m.id, m.title, m.module, m.position,    m.content, m.showtitle, m.params, mm.menuid');
            $query->from('#__modules AS m');
            $query->join('LEFT', '#__modules_menu AS mm ON mm.moduleid =    m.id');
            $query->where('m.published = 1');

            $query->join('LEFT', '#__extensions AS e ON e.element =     m.module AND e.client_id = m.client_id');
            $query->where('e.enabled = 1');

            $date = JFactory::getDate();
            $now = $date->toSql();
            $nullDate = $db->getNullDate();
            $query->where('(m.publish_up = ' . $db->Quote($nullDate) . '    OR m.publish_up <= ' . $db->Quote($now) . ')');
            $query->where('(m.publish_down = ' . $db->Quote($nullDate) . '  OR m.publish_down >= ' . $db->Quote($now) . ')');

            $query->where('m.access IN (' . $groups . ')');
            $query->where('m.client_id = ' . $clientId);
            // Disable this line in your override class's _load()...
            // $query->where('(mm.menuid = ' . (int) $Itemid . ' OR     mm.menuid <= 0)');

            // Filter by language
            if ($app->isSite() && $app->getLanguageFilter())
            {
                $query->where('m.language IN (' . $db->Quote($lang) .   ',' . $db->Quote('*') . ')');
            }

            $query->order('m.position, m.ordering');

            // Set the query
            $db->setQuery($query);
            $modules = $db->loadObjectList();
            $clean = array();

            if ($db->getErrorNum())
            {
                JError::raiseWarning(500,   JText::sprintf('JLIB_APPLICATION_ERROR_MODULE_LOAD', $db->getErrorMsg()));
                return $clean;
            }

            // Apply negative selections and eliminate duplicates
            $negId = $Itemid ? -(int) $Itemid : false;
            $dupes = array();
            for ($i = 0, $n = count($modules); $i < $n; $i++)
            {
                $module = &$modules[$i];

                // The module is excluded if there is an explicit   prohibition
                $negHit = ($negId === (int) $module->menuid);

                if (isset($dupes[$module->id]))
                {
                    // If this item has been excluded, keep the     duplicate flag set,
                    // but remove any item from the cleaned array.
                    if ($negHit)
                    {
                        unset($clean[$module->id]);
                    }
                    continue;
                }

                $dupes[$module->id] = true;

                // Only accept modules without explicit exclusions.
                if (!$negHit)
                {
                    // Determine if this is a 1.0 style custom  module (no mod_ prefix)
                    // This should be eliminated when the class is  refactored.
                    // $module->user is deprecated.
                    $file = $module->module;
                    $custom = substr($file, 0, 4) == 'mod_' ?  0 :  1;
                    $module->user = $custom;
                    // 1.0 style custom module name is given by     the title field, otherwise strip off "mod_"
                    $module->name = $custom ? $module->module :     substr($file, 4);
                    $module->style = null;
                    $module->position = strtolower($module- >position);
                    $clean[$module->id] = $module;
                }
            }

            unset($dupes);

            // Return to simple indexing that matches the query order.
            $clean = array_values($clean);

            $cache->store($clean, $cacheid);
        }

        return $clean;
    }
}

谢谢尝试,但你的代码对我来说不起作用。而且我看不出它怎么能工作,因为你从未加载缺失的模块,你只是加载了渲染器。你是否缺少类似于 $renderer->render($module) 的一行代码? - Dom
我想我刚刚理解了你试图解决的问题,但那不是我所面临的问题。你试图解决的问题是,在我尝试访问它们的时候,没有模块被加载到文档中,但我遇到的问题是,我想要获取的模块未分配给当前菜单项。我已经多次说明过了,JModuleHelper::getModule无法检索未分配给当前菜单项的模块。 - Dom
是的,我确实错过了这一点,JModuleHelper的受保护的_load()函数只会获取发布到当前或所有菜单项的模块。加载所有可能的模块(因此网站有数百个,其中一半未放置或未发布)不是很有效率 - 您可以自己制作帮助程序类并覆盖它。请参阅我的更新答案。 - Craig
创建自己的子类似乎是一个很麻烦的方法。我认为更好的解决方案是直接从数据库获取模块数据。我知道这不够优雅,但我认为它是可用解决方案中最好的一个。 - Dom
我不确定有什么需要“费劲”的,因为你所要做的就是将那段代码复制到一个帮助文件中,然后加载它。无论如何至少在那里给你提供了SQL。 - Craig
我认为以下原因使得它"笨重":你正在添加超过100行的代码;代码拉入了所有模块,而不仅仅是你需要的一个;代码复制了核心代码,如果核心代码在安全补丁中更新,则会创建维护问题;你的代码与数据库中的核心表紧密耦合,而不是使用API调用。我认为我在问题编辑中展示的解决方案稍微好一些,但我仍然认为我的解决方案并不特别好,但这是我必须采取的选项。 - Dom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接