用zencart来复制别人的网站成本低,效率高。前面我发了一篇有关开发自己的zencat模板的文章(《来自damon的zencart二次开发教程-3.1开发自己的zencart模板》),里面只有一些基础的理论,下面,我们就来实际操作一下。

1.利用离线浏览器将(《离线浏览器Teleport_Pro完全教程与安装文件下载》)你的目标网页文件(图片,html以及css样式表,js代码)统统下载下来。打开你的zencart文件夹,将默认模板文件复制一个,然后重命名为你自定义的名称,修改template_info.php文件(详细请参考《来自damon的zencart二次开发教程-3.1开发自己的zencart模板》)。将一些基本的操作做完之后,省下的就是分离将网页html文件分离为模板文件了。

2.在分离之前,我们需要对模板文件结构进行深入了解,可以参考我之前发的一篇文章(《zencart与drupal整合(第2天)—zencart模块调用机制》)。

2.1 头部模板文件html_header.php

$directory_array = $template->get_template_part($template->get_template_dir
('.css',DIR_WS_TEMPLATE, $current_page_base,'css'), '/^style/', '.css');

这段代码是用于加载样式表的,css文件只要满足文件名以style开头就会自动加载。(jscript文件也是同样的规则,加载文件夹有 includes/modules/pages/PAGENAME 和 includes/templates/YOURTEMPLATE/jscript。)

2.2页眉tpl_header.php

网站logo,tagline,产品分类导航以及登陆、搜索模块。

其中分类导航的模板文件是templates/tpl_modules_categories_tabs.php,代码如下:

 include(DIR_WS_MODULES . zen_get_module_directory(FILENAME_CATEGORIES_TABS));
?>
<?php if (CATEGORIES_TABS_STATUS == '1' && sizeof($links_list) >= 1) { ?>
<div id="navCatTabsWrapper">
<div id="navCatTabs">
<ul>
<?php for ($i=0, $n=sizeof($links_list); $i<$n; $i++) { ?>
  <li><?php echo $links_list[$i];?></li>
<?php } ?>
</ul>
</div>
</div>
<?php } ?>

我们可以利用id在style.css文件中找到相应的属性,修改样式。这里要注意的是,分类导航的字体,间距等都被定义在了230行中:

ul, #navSupp ul, #navCatTabs ul

搜索模块文件是sideboxes\tpl_search_header.php文件以及sideboxes\tpl_search.php。

常量HEADER_SEARCH_DEFAULT_TEXT用来修改搜索框中默认的文本。

Line 14至Line 20是用来判断提交按钮的样式是图片还是普通的按钮:

  if (strtolower(IMAGE_USE_CSS_BUTTONS) == 'yes') {
 //当常量IMAGE_USE_CSS_BUTTONS为 yes时
    $content .= zen_draw_input_field('keyword', '', 
    'size="6" maxlength="30" style="width: 100px" 
     value="' . HEADER_SEARCH_DEFAULT_TEXT . '" οnfοcus=
     "if (this.value == \'' . HEADER_SEARCH_DEFAULT_TEXT . '\') 
      this.value = \'\';" οnblur="if (this.value == \'\') this.value = \'' . 
      HEADER_SEARCH_DEFAULT_TEXT . '\';"') . '&nbsp;' . 
      zen_p_w_picpath_submit (BUTTON_IMAGE_SEARCH,HEADER_SEARCH_BUTTON);
     //图片形式的提交按钮
  } else {
    $content .= zen_draw_input_field('keyword', '', 
    'size="6" maxlength="30" style="width: 100px" 
    value="' . HEADER_SEARCH_DEFAULT_TEXT . '" οnfοcus="
    if (this.value == \'' . HEADER_SEARCH_DEFAULT_TEXT . '\') this.value = \'\';" 
    οnblur="if (this.value == \'\') this.value = \'' . 
    HEADER_SEARCH_DEFAULT_TEXT . '\';"') . '&nbsp;<input type="submit" value="' . 
    HEADER_SEARCH_BUTTON . '" style="width: 45px" />';
    //普通按钮。
  }

其中输出 submit 提交表单图片按钮函数 zen_p_w_picpath_submit($p_w_picpath, $alt = '', $parameters = '', $sec_class = '')

该函数的功能主要就是输出一个提交表单的图片按钮,跟一般的输出图片按钮差不多一样,不一样的是这个函数输出的是<input type="p_w_picpath" />类型的按钮,而一般的图片按钮zen_p_w_picpath_button输出的是图片的链接。
参数解析:
$p_w_picpath:输出图片的名字,默认的目录是在模板目录下的buttons/目录下面的图片名字,输入对应的图片名字就可以了
$alt:图片<img>标签的alt属性值。
$parameters:参数,可以是其他属性的值,一般这个很少使用,默认为空
$sec_class:该图片按钮的CSS类,默认为空,只有使用CSS按钮的使用该参数才会用到

function zen_p_w_picpath_submit($p_w_picpath, $alt = '', $parameters = '', $sec_class = '') {
    global $template, $current_page_base, $zco_notifier;
    if (
        strtolower(IMAGE_USE_CSS_BUTTONS) == 'yes' && strlen($alt)<30) 
        return zenCssButton(
                    $p_w_picpath, $alt, 'submit', $sec_class /*, $parameters = ''*/
                   );
    $zco_notifier->notify('PAGE_OUTPUT_IMAGE_SUBMIT');
    $p_w_picpath_submit = '<input type="p_w_picpath" src="' . zen_output_string(
     $template->get_template_dir($p_w_picpath, DIR_WS_TEMPLATE, $current_page_base, 'buttons/' . 
     $_SESSION['language'] . '/') . $p_w_picpath) . '" alt="' . zen_output_string($alt) . '"';
    if (zen_not_null($alt)) $p_w_picpath_submit .= ' title=" ' . zen_output_string($alt) . ' "';
    if (zen_not_null($parameters)) $p_w_picpath_submit .= ' ' . $parameters;
    $p_w_picpath_submit .= ' />';
    return $p_w_picpath_submit;
  }

2.3整体布局tpl_main_page.php
sidebox边框以及左、右边栏left/right column 都可以在后台控制开启和关闭状态。而中间id为"centerColumn"的广告则为变量$body_code:

require($body_code);   //Line 122 prepares and displays center column

定义$body_code的相关文件:
includes/modules/pages/$main_page/main_template_vars.php
includes/templates/mytemplate/$main_page/tpl_{$main_page}_default.php
includes/templates/template_default/$main_page/tpl_{$main_page}_default.php
includes/templates/mytemplate/templates/tpl_{$main_page}_default.php
includes/templates/template_default/templates/tpl_{$main_page}_default.php
//定义整个HTML模板
includes/languages/english/html_includes/define_main_page.php

我们在这个位置放的最多的功能就是幻灯片效果,具体有关幻灯片安装与修改的教程,可以参考我的另一篇文章《来自damon的zencart二次开发教程-4.1制作首页幻灯片方法》。
2.4页脚tpl_footer.php,第一行中

require(DIR_WS_MODULES . zen_get_module_directory('footer.php'));

加载模块函数zen_get_module_directory($check_file,  $dir_only = ‘false’),根据当前输入的模块文件的名字,返回该文件所在的模块目录下的路径。用于验证该文件是否在模块目录下。验证该文件的时候首先验证模块目 录下当前选择的模板目录下是否有该文件,如果有的话,就引用当前模板目录下的模块文件,如果没有就选择默认的模块目录下面的模块文件。

function zen_get_module_directory($check_file, $dir_only = 'false') {
global $template_dir;
$zv_filename = $check_file;
if (!strstr($zv_filename, ‘.php’)) $zv_filename .= '.php';
if (file_exists(DIR_WS_MODULES . $template_dir . '/' . $zv_filename)) {
$template_dir_select = $template_dir . '/';
} else {
$template_dir_select = '';
}
if ($dir_only == 'true') {
return $template_dir_select;
} else {
return $template_dir_select . $zv_filename;
}
}

底部导航调用了模块文件tpl_ezpages_bar_footer.php,

<?php require($template->get_template_dir
('tpl_ezpages_bar_footer.php',DIR_WS_TEMPLATE, 
 $current_page_base,'templates'). 
 '/tpl_ezpages_bar_footer.php'); ?>

tpl_ezpages_bar_footer.php的第22 Line:

$page_query = $db->Execute("select * from " . TABLE_EZPAGES . " 
where status_footer = 1 and 
footer_sort_order > 0 order by footer_sort_order, pages_title");

我们可以知道表格EZPAGES是用来控制底部导航显示的内容的。此外,修改字段EZPAGES_STATUS_FOOTER中的数字可以控制是否显示(1为显示)。

if (EZPAGES_STATUS_FOOTER == '1' or (EZPAGES_STATUS_FOOTER == '2' 
and (strstr(EXCLUDE_ADMIN_IP_FOR_MAINTENANCE, $_SERVER['REMOTE_ADDR']))))

$_SERVER['REMOTE_ADDR']是获取到的访问者ip,利用这一点,我们可以实现依据用户的IP来自动调用语言包,在 index.php文件中获取访问者的ip:$_SERVER['REMOTE_ADDR'],获取ip后,对ip进行判断,这里用 http://api.liqwei.com /location/?ip=$ip提供的接口,对访问者的ip进行判断,$IPINFO = file_get_contents ( “http://api.liqwei.com/location/?ip=$ip” );返回的内容会是国家,ip地址,已经线路,对返回的内容进行截取preg_match(‘|日本|’,$IPINFO),然后在调用相应的语言包。

3 zencart 商品列表

这部分的模板文件主要包括:\templates\tpl_index_product_list.php(主文件)、\templates \tpl_modules_product_listing.php(商品列表模块)、classes \split_page_results.php(分页函数).
关于zencart的分页功能,我们可以下载一款专门的分页插件:(product_pagination下载>>)。这款插件会重写分页函数,也就是split_page_results.php文件。下面,我们再来仔细研究一下这个函数:

class splitPageResults extends base {
  var $sql_query, $number_of_rows, $current_page_number, $number_of_pages, 
      $number_of_rows_per_page, $page_name;
/*
$sql_query:查询数据库的SQL语句,初始化该类的对象的时候会给这个变量赋值。
$number_of_rows:保存返回查询结果数。
$current_page_number:当前页面的数字,就是第几页。
$number_of_pages:总共有多少页,
计算方法 $this->number_of_pages = ceil($this->number_of_rows / $this->number_of_rows_per_page);
$number_of_rows_per_page:每页显示的数量。这个变量由构造函数赋值。
如果要改变每页显示的数量,可以修改这个参数的值。
$page_name:分页的参数名字,默认是page,就是page=?这样。
*/
  var $formSuffix; /*v1.4.5-a-lat9*/
/*构造函数,主要是对类变量赋值,其中$query这个是必须要输入的参数值,
这个就是查询数据库的SQL语句,$max_rows这个是每页显示的数量,也必须的参数。
其他的可以使用默认值。*/
  function splitPageResults($query, $max_rows, $count_key = '*', $page_holder = 'page', 
                            $debug = false, $countQuery = "") {
    ...
  }

  /* class functions功能函数 */
  // 显示分页链接
/*
第一个参数就是显示的页面数量,这个就是除了显示下一页的文字以外的数字,如果是6,那 就是显示从1-6,
第七个就是“下一页”这样的提示。$parameters 就是当前页面的一些参数。
*/
  function display_links($max_page_links, $parameters = '') {
    ...
  }

  // 显示商品总数(Display Num)
  function display_count($text_output) {
   ...
}

\templates\tpl_modules_product_listing.php中的函数调用代码:

$listing_split->display_links(MAX_DISPLAY_PAGE_LINKS, 
                      zen_get_all_get_params(array('page', 'info', 'x', 'y', 'main_page')))

zen_get_all_get_params()函数,获取$_GET这个数组的所有键和值,然后把指定不需要的变量去了,然后把剩下的参数重新 组合起来,返回这个组合的结果做为URL的参数 ,用来过滤掉$_GET中的指定参数('page', 'info', 'x', 'y', 'main_page')
建议:zencart 仿站的步骤应根据目标网站代码样式的复杂程度来区分,对于一些整体样式变化不大(相对于默认模板来说),JS代码较少的网站,我们可以直接把目标网站的源 码当做模板来套,而对于一些将整个默认模板的整体样式都做了较大修改,特效比较多的网站,建议还是直接复制一份默认模板的代码,然后对照着目标网站来修 改。