prestashop源码研究(一)


分类: prestashop   1074人阅读  评论(0)  收藏  举报
hook module output tools header exception

   最近要仿一个网站,准备用prestashop来做,一直没怎么深入研究过这个东西,都只是在改一些外部

的东西,从今天开始好好看看,方便做后面的开发。

   从头开始index.php:

[php]  view plain copy print ?
  1. <?php  
  2.   
  3. include(dirname(__FILE__).'/config/config.inc.php');//加载一些配置信息  
  4.   
  5. if(intval(Configuration::get('PS_REWRITING_SETTINGS')) === 1)//url重写  
  6.     $rewrited_url = __PS_BASE_URI__;  
  7.   
  8. //这边很清楚的能看出页面结构了,头和尾定义在单独文件中,统一的头和尾,中间的内容可以变化,  
  9. //也就是母版页技术  
  10. include(dirname(__FILE__).'/header.php');  
  11.   
  12. //把挂载在home这个挂载点的模块加载进来,分配到tpl文件的变量HOOK_HOME是一个字符串,  
  13. //保存了模块显示的html结构,在tpl文件中{$HOOK_HOME}这样使用,就可以把模块显示出来  
  14. //这部分在Module.php的类文件中可以  
  15. $smarty->assign('HOOK_HOME', Module::hookExec('home'));  
  16. $smarty->display(_PS_THEME_DIR_.'index.tpl');  
  17.   
  18. include(dirname(__FILE__).'/footer.php');  
  19.   
  20. ?>  

 

来看看header.php:

[php]  view plain copy print ?
  1. <?php  
  2.   
  3. // P3P Policies (http://www.w3.org/TR/2002/REC-P3P-20020416/#compact_policies)  
  4. header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"');  
  5.   
  6. require_once(dirname(__FILE__).'/init.php');//初始化一些页面信息  
  7.   
  8. /* CSS */  
  9. $css_files[_THEME_CSS_DIR_.'global.css'] = 'all';//定义css文件和media信息  
  10.   
  11. /* Hooks are volontary out the initialize array (need those variables already assigned) */  
  12. $smarty->assign(array(  
  13.     'HOOK_HEADER' => Module::hookExec('header'),  
  14.     'HOOK_LEFT_COLUMN' => Module::hookExec('leftColumn'),  
  15.     'HOOK_TOP' => Module::hookExec('top'),  
  16.     'static_token' => Tools::getToken(false),  
  17.     'token' => Tools::getToken(),  
  18.     'priceDisplayPrecision' => _PS_PRICE_DISPLAY_PRECISION_,  
  19.     'content_only' => intval(Tools::getValue('content_only'))  
  20. ));  
  21. //可以看到header,leftColumn和top这三个挂载点的模块,都是在这个文件中加载的  
  22.   
  23. if(isset($css_files) AND !empty($css_files)) $smarty->assign('css_files'$css_files);  
  24. if(isset($js_files) AND !empty($js_files)) $smarty->assign('js_files'$js_files);  
  25.   
  26. $smarty->display(_PS_THEME_DIR_.'header.tpl');  
  27.   
  28. ?>  

 

然后是footer.php:

[php]  view plain copy print ?
  1. <?php  
  2.   
  3. if (isset($smarty))  
  4. {  
  5.     $smarty->assign(array(  
  6.         'HOOK_RIGHT_COLUMN' => Module::hookExec('rightColumn'),  
  7.         'HOOK_FOOTER' => Module::hookExec('footer'),  
  8.         'content_only' => intval(Tools::getValue('content_only'))));  
  9.     $smarty->display(_PS_THEME_DIR_.'footer.tpl');  
  10. }  
  11. //这个比较简单,结构上来说主要是加载rightColumn和footer这两个挂载点的模块  
  12. ?>  

 

 

从上面三个文件中,可以很清晰的看出prestashop的页面结构:

 

prestashop源码研究(一)_第1张图片

 

   上面三个文件都有类似:'HOOK_RIGHT_COLUMN' => Module::hookExec('rightColumn')

这样的模块加载函数,有必要去看看里面的代码。

 

   classes/Module.php中的hookExec函数:

[php]  view plain copy print ?
  1. /* 
  2.      * Execute modules for specified hook 
  3.      * 
  4.      * @param string $hook_name Hook Name 
  5.      * @param array $hookArgs Parameters for the functions 
  6.      * @return string modules output 
  7.      */  
  8.     public static function hookExec($hook_name$hookArgs = array(), $id_module = NULL)  
  9.     {  
  10.         if ((!empty($id_module) AND !Validate::isUnsignedId($id_module)) OR !Validate::isHookName($hook_name))  
  11.             die(Tools::displayError());  
  12.   
  13.         global $cart$cookie;  
  14.         $altern = 0;  
  15.   
  16.         if (!isset($hookArgs['cookie']) OR !$hookArgs['cookie'])  
  17.             $hookArgs['cookie'] = $cookie;  
  18.         if (!isset($hookArgs['cart']) OR !$hookArgs['cart'])  
  19.             $hookArgs['cart'] = $cart;  
  20.   
  21.         $result = Db::getInstance()->ExecuteS('  
  22.             SELECT h.`id_hook`, m.`name`, hm.`position`  
  23.             FROM `'._DB_PREFIX_.'module` m  
  24.             LEFT JOIN `'._DB_PREFIX_.'hook_module` hm ON hm.`id_module` = m.`id_module`  
  25.             LEFT JOIN `'._DB_PREFIX_.'hook` h ON hm.`id_hook` = h.`id_hook`  
  26.             WHERE h.`name` = /''.pSQL($hook_name).'/'  
  27.             AND m.`active` = 1  
  28.             '.($id_module ? 'AND m.`id_module` = '.intval($id_module) : '').'  
  29.             ORDER BY hm.`position`, m.`name` DESC');  
  30.         if (!$result)  
  31.             return false;  
  32.         $output = '';  
  33.         foreach ($result AS $k => $module)  
  34.         {  
  35.             $moduleInstance = Module::getInstanceByName($module['name']);  
  36.             if (!$moduleInstance)  
  37.                 continue;  
  38.             $exceptions = $moduleInstance->getExceptions(intval($module['id_hook']), intval($moduleInstance->id));  
  39.             $fileindex = basename($_SERVER['PHP_SELF']);  
  40.             $show = true;  
  41.             if (!empty($exceptions) AND is_array($exceptions))  
  42.                 foreach ($exceptions as $exception)  
  43.                     if ($fileindex == $exception['file_name'])  
  44.                         $show = false;  
  45.             if (is_callable(array($moduleInstance'hook'.$hook_name)) AND $show)  
  46.              {  
  47.                 $hookArgs['altern'] = ++$altern;  
  48.                 $output .= call_user_func(array($moduleInstance'hook'.$hook_name), $hookArgs);  
  49.             }  
  50.         }  
  51.         return $output;  
  52.     }  

 

大致的意思是这样,通过挂载点名称取得在这个挂载点上的模块的信息,然后遍历这些模块,

产生模块的实例,然后执行模块中的相应hook+hook_name的函数返回相应的html代码,

所有模块的html代码都以字符串型似记录在$output这个变量中,所以hook_Exec函数返回的就是

一个很长的构造好的html字符串,可以分配给tpl的变量直接使用。

这里用到了call_user_func()函数来动态执行模块中的方法,这个技巧很不错。

你可能感兴趣的:(prestashop)