最近要仿一个网站,准备用prestashop来做,一直没怎么深入研究过这个东西,都只是在改一些外部
的东西,从今天开始好好看看,方便做后面的开发。
从头开始index.php:
- <?php
- include(dirname(__FILE__).'/config/config.inc.php');//加载一些配置信息
- if(intval(Configuration::get('PS_REWRITING_SETTINGS')) === 1)//url重写
- $rewrited_url = __PS_BASE_URI__;
- //这边很清楚的能看出页面结构了,头和尾定义在单独文件中,统一的头和尾,中间的内容可以变化,
- //也就是母版页技术
- include(dirname(__FILE__).'/header.php');
- //把挂载在home这个挂载点的模块加载进来,分配到tpl文件的变量HOOK_HOME是一个字符串,
- //保存了模块显示的html结构,在tpl文件中{$HOOK_HOME}这样使用,就可以把模块显示出来
- //这部分在Module.php的类文件中可以
- $smarty->assign('HOOK_HOME', Module::hookExec('home'));
- $smarty->display(_PS_THEME_DIR_.'index.tpl');
- include(dirname(__FILE__).'/footer.php');
- ?>
来看看header.php:
- <?php
- // P3P Policies (http://www.w3.org/TR/2002/REC-P3P-20020416/#compact_policies)
- header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"');
- require_once(dirname(__FILE__).'/init.php');//初始化一些页面信息
- /* CSS */
- $css_files[_THEME_CSS_DIR_.'global.css'] = 'all';//定义css文件和media信息
- /* Hooks are volontary out the initialize array (need those variables already assigned) */
- $smarty->assign(array(
- 'HOOK_HEADER' => Module::hookExec('header'),
- 'HOOK_LEFT_COLUMN' => Module::hookExec('leftColumn'),
- 'HOOK_TOP' => Module::hookExec('top'),
- 'static_token' => Tools::getToken(false),
- 'token' => Tools::getToken(),
- 'priceDisplayPrecision' => _PS_PRICE_DISPLAY_PRECISION_,
- 'content_only' => intval(Tools::getValue('content_only'))
- ));
- //可以看到header,leftColumn和top这三个挂载点的模块,都是在这个文件中加载的
- if(isset($css_files) AND !empty($css_files)) $smarty->assign('css_files', $css_files);
- if(isset($js_files) AND !empty($js_files)) $smarty->assign('js_files', $js_files);
- $smarty->display(_PS_THEME_DIR_.'header.tpl');
- ?>
然后是footer.php:
- <?php
- if (isset($smarty))
- {
- $smarty->assign(array(
- 'HOOK_RIGHT_COLUMN' => Module::hookExec('rightColumn'),
- 'HOOK_FOOTER' => Module::hookExec('footer'),
- 'content_only' => intval(Tools::getValue('content_only'))));
- $smarty->display(_PS_THEME_DIR_.'footer.tpl');
- }
- //这个比较简单,结构上来说主要是加载rightColumn和footer这两个挂载点的模块
- ?>
从上面三个文件中,可以很清晰的看出prestashop的页面结构:
上面三个文件都有类似:'HOOK_RIGHT_COLUMN' => Module::hookExec('rightColumn')
这样的模块加载函数,有必要去看看里面的代码。
classes/Module.php中的hookExec函数:
- /*
- * Execute modules for specified hook
- *
- * @param string $hook_name Hook Name
- * @param array $hookArgs Parameters for the functions
- * @return string modules output
- */
- public static function hookExec($hook_name, $hookArgs = array(), $id_module = NULL)
- {
- if ((!empty($id_module) AND !Validate::isUnsignedId($id_module)) OR !Validate::isHookName($hook_name))
- die(Tools::displayError());
- global $cart, $cookie;
- $altern = 0;
- if (!isset($hookArgs['cookie']) OR !$hookArgs['cookie'])
- $hookArgs['cookie'] = $cookie;
- if (!isset($hookArgs['cart']) OR !$hookArgs['cart'])
- $hookArgs['cart'] = $cart;
- $result = Db::getInstance()->ExecuteS('
- SELECT h.`id_hook`, m.`name`, hm.`position`
- FROM `'._DB_PREFIX_.'module` m
- LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_module` = m.`id_module`
- LEFT JOIN `'._DB_PREFIX_.'hook` h ON hm.`id_hook` = h.`id_hook`
- WHERE h.`name` = /''.pSQL($hook_name).'/'
- AND m.`active` = 1
- '.($id_module ? 'AND m.`id_module` = '.intval($id_module) : '').'
- ORDER BY hm.`position`, m.`name` DESC');
- if (!$result)
- return false;
- $output = '';
- foreach ($result AS $k => $module)
- {
- $moduleInstance = Module::getInstanceByName($module['name']);
- if (!$moduleInstance)
- continue;
- $exceptions = $moduleInstance->getExceptions(intval($module['id_hook']), intval($moduleInstance->id));
- $fileindex = basename($_SERVER['PHP_SELF']);
- $show = true;
- if (!empty($exceptions) AND is_array($exceptions))
- foreach ($exceptions as $exception)
- if ($fileindex == $exception['file_name'])
- $show = false;
- if (is_callable(array($moduleInstance, 'hook'.$hook_name)) AND $show)
- {
- $hookArgs['altern'] = ++$altern;
- $output .= call_user_func(array($moduleInstance, 'hook'.$hook_name), $hookArgs);
- }
- }
- return $output;
- }
大致的意思是这样,通过挂载点名称取得在这个挂载点上的模块的信息,然后遍历这些模块,
产生模块的实例,然后执行模块中的相应hook+hook_name的函数返回相应的html代码,
所有模块的html代码都以字符串型似记录在$output这个变量中,所以hook_Exec函数返回的就是
一个很长的构造好的html字符串,可以分配给tpl的变量直接使用。
这里用到了call_user_func()函数来动态执行模块中的方法,这个技巧很不错。