3

Header.tpl文件中有一个钩子{$HOOK_TOP},其中包含所有标题部分,包括菜单、搜索等...您可以在此 URL 中检查

FrontController它显示... 'HOOK_TOP' => Hook::exec('displayTop'),这意味着在 Hook 页面中有一个名为 的函数exec()。但我无法正确理解exec()通话中的代码。

它告诉它为指定的钩子执行模块。当我搜索“ displayTop ”时,我得到了一个名为blocktopmenu.php.

执行仅通过 2 个功能:

    public function hookDisplayTop($param)
    {
        $this->user_groups =  ($this->context->customer->isLogged() ? $this->context->customer->getGroups() : array(Configuration::get('PS_UNIDENTIFIED_GROUP')));
        $this->page_name = Dispatcher::getInstance()->getController();
        if (!$this->isCached('blocktopmenu.tpl', $this->getCacheId()))
        {
            $this->makeMenu();
            $this->smarty->assign('MENU_SEARCH', Configuration::get('MOD_BLOCKTOPMENU_SEARCH'));
            $this->smarty->assign('MENU', $this->_menu);
            $this->smarty->assign('this_path', $this->_path);
        }

        $this->context->controller->addJS($this->_path.'js/hoverIntent.js');
        $this->context->controller->addJS($this->_path.'js/superfish-modified.js');
        $this->context->controller->addCSS($this->_path.'css/superfish-modified.css');

        $html = $this->display(__FILE__, 'blocktopmenu.tpl', $this->getCacheId());
        //print_r($html);//exit;
        return $html;
    }

protected function getCacheId($name = null)
{//echo"asdasdsad";exit;
    parent::getCacheId($name);
    $page_name = in_array($this->page_name, array('category', 'supplier', 'manufacturer', 'cms', 'product')) ? $this->page_name : 'index';
    return 'blocktopmenu|'.(int)Tools::usingSecureMode().'|'.$page_name.'|'.(int)$this->context->shop->id.'|'.implode(', ',$this->user_groups).'|'.(int)$this->context->language->id.'|'.(int)Tools::getValue('id_category').'|'.(int)Tools::getValue('id_manufacturer').'|'.(int)Tools::getValue('id_supplier').'|'.(int)Tools::getValue('id_cms').'|'.(int)Tools::getValue('id_product');
}

但是这个公共函数hookDisplayTop($param)永远不会在任何地方的整个文件夹中被调用。我搜索了它,但从未在任何文件中找到它。

exec()功能如下图

public static function exec($hook_name, $hook_args = array(), $id_module = null, $array_return = false, $check_exceptions = true)
    {

        // Check arguments validity
        if (($id_module && !is_numeric($id_module)) || !Validate::isHookName($hook_name))
            throw new PrestaShopException('Invalid id_module or hook_name');

        // If no modules associated to hook_name or recompatible hook name, we stop the function

        if (!$module_list = Hook::getHookModuleExecList($hook_name))
            return '';

        // Check if hook exists
        if (!$id_hook = Hook::getIdByName($hook_name))
            return false;

        // Store list of executed hooks on this page

        Hook::$executed_hooks[$id_hook] = $hook_name;
    //  print_r(Hook::$executed_hooks);exit;

        $live_edit = false;
        $context = Context::getContext();
        if (!isset($hook_args['cookie']) || !$hook_args['cookie'])
            $hook_args['cookie'] = $context->cookie;
        if (!isset($hook_args['cart']) || !$hook_args['cart'])
            $hook_args['cart'] = $context->cart;

        $retro_hook_name = Hook::getRetroHookName($hook_name);
//print_r($hook_name);exit;
        // Look on modules list
        $altern = 0;
        $output = '';
        foreach ($module_list as $array)
        {
            // Check errors
            if ($id_module && $id_module != $array['id_module'])
                continue;
            if (!($moduleInstance = Module::getInstanceByName($array['module'])))
                continue;

            // Check permissions
            if ($check_exceptions)
            {
                $exceptions = $moduleInstance->getExceptions($array['id_hook']);
                $controller = Dispatcher::getInstance()->getController();

                if (in_array($controller, $exceptions))
                    continue;

                //retro compat of controller names
                $matching_name = array(
                    'authentication' => 'auth',
                    'compare' => 'products-comparison',
                    );
                if (isset($matching_name[$controller]) && in_array($matching_name[$controller], $exceptions))
                    continue;
                if (Validate::isLoadedObject($context->employee) && !$moduleInstance->getPermission('view', $context->employee))
                    continue;
            }

            // Check which / if method is callable
            $hook_callable = is_callable(array($moduleInstance, 'hook'.$hook_name));
            $hook_retro_callable = is_callable(array($moduleInstance, 'hook'.$retro_hook_name));
            if (($hook_callable || $hook_retro_callable) && Module::preCall($moduleInstance->name))
            {
                $hook_args['altern'] = ++$altern;

                // Call hook method
                if ($hook_callable)
                    $display = $moduleInstance->{'hook'.$hook_name}($hook_args);
                else if ($hook_retro_callable)
                    $display = $moduleInstance->{'hook'.$retro_hook_name}($hook_args);
                // Live edit
                if (!$array_return && $array['live_edit'] && Tools::isSubmit('live_edit') && Tools::getValue('ad') && Tools::getValue('liveToken') == Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee')))
                {
                    $live_edit = true;
                    $output .= self::wrapLiveEdit($display, $moduleInstance, $array['id_hook']);
                }
                else if ($array_return)
                    $output[] = $display;
                else
                    $output .= $display;
            }
        }
        if ($array_return)
            return $output;
        else
            return ($live_edit ? '<script type="text/javascript">hooks_list.push(\''.$hook_name.'\'); </script>
                <div id="'.$hook_name.'" class="dndHook" style="min-height:50px">' : '').$output.($live_edit ? '</div>' : '');// Return html string
    }
4

2 回答 2

4

我不会在这里逐行向您解释代码,但我会向您解释 exec 静态成员的作用。

当你打电话

Hook::exec("HookName"); 

它为您执行以下过程。

1)首先它检查钩子是否可用?如果不可用,则返回 false;

2) 其次,它从数据库中获取该钩子的模块列表。还可以通过当前页面的钩子模块的例外来缩小列表的范围。

3) 在获取当前加载(或调用页面)页面调用的钩子的所有模块后,调用模块中的钩子函数。如果您检查特定钩子的模块,您会发现该钩子的公共函数。让我们考虑一下 Top 钩子。在模块中,您将拥有公共功能,例如

public function hookTop // or public function hookDisplayTop for compatibility reasons

请不要让 PS 也在那里执行一些其他操作。

上面的细节只是让你了解钩子和模块在 PS 中是如何工作的。同样采用上述理论,我在 Codeigniter 和 Zend Framework 中为我自己的项目实现了相同的操作,它就像一个魅力;)。

如果您还有其他问题,请告诉我,我会尽可能详细地为您提供。

谢谢

于 2013-05-17T12:50:46.003 回答
1

调用 HookDiplayTop 的行是:

// Call hook method
if ($hook_callable)
$display = $moduleInstance->{'hook'.$hook_name}($hook_args);
else if ($hook_retro_callable)
$display = $moduleInstance->{'hook'.$retro_hook_name}($hook_args);
于 2013-05-17T12:34:40.383 回答