1:zencart系统推荐商品
后台->商品管理->推荐商品,在列表中选择商品,选择推荐的时间段,提交.
2:zencart系统推荐商品的实现原理
1:tpl_box_default_left.php中,$box_id是循环整个产品推荐模块的一个根本,而column_left.php又是循环 选择模块标题和模块内容的一个模板.于是通过require(DIR_WS_MODULES . ‘sideboxes/’ . $column_left_display->fields['layout_box_name']);来实现对tpl_default.php的 包含.tpl_default.php中的 $random_featured_product = $db->ExecuteRandomMulti($random_featured_products_query, MAX_RANDOM_SELECT_FEATURED_PRODUCTS);
数组,把要包含的推荐产品条数记录下来。传递给tpl_default.php.
tpl_default.php是ZenCart中产品推荐的模块.下面的代码是对推荐产品的处理.
$content = “”;
$featured_box_counter = 0;
while (!$random_featured_product->EOF) {
$featured_box_counter++;
$featured_box_price = zen_get_products_display_price($random_featured_product->fields['products_id']);
$content .= ‘<div>’;
$content .=  ‘<a href=”‘ . zen_href_link(zen_get_info_page($random_featured_product->fields["products_id"]), ‘cPath=’ . zen_get_generated_category_path_rev($random_featured_product->fields["master_categories_id"]) . ‘&products_id=’ . $random_featured_product->fields["products_id"]) . ‘”>’ . zen_image(DIR_WS_IMAGES . $random_featured_product->fields['products_image'], $random_featured_product->fields['products_name'], SMALL_IMAGE_WIDTH, SMALL_IMAGE_HEIGHT);
$content .= ‘<br />’ . $random_featured_product->fields['products_name'] . ‘</a>’;
$content .= ‘<div>’ . $featured_box_price . ‘</div>’;
$content .= ‘</div>’;
$random_featured_product->MoveNextRandom();
}

---zen cart session处理---

zen cart自定义了session的处理函数,session_save_path设在了/cache/文件夹,在include /configure.php里有个选项 define(‘STORE_SESSIONS’, ‘db’); // use ‘db’ for best support, or ” for file-based storage 设置session的保存方式。

不同的程序间要想共享session数据,至少要遵循以下几个条件:session_save_path 相同,session_id相同,当然session的保存方式肯定要一样,php默认的session保存方式就是文件存储,而保存目录就在系统的临时目录。

这里我们要想zen cart 读取到我们自己定义的 session变量,就需要我们在自己的程序里把session的存储目录放到zc目录下的cache文件夹,例如 session_save_path(‘e:/zc/cache’),然后修改zc/include/configure.php文件中 define(‘STORE_SESSIONS’, ‘db’); 修改为 define(‘STORE_SESSIONS’, ”);这样就让zen cart的session也以文件形式存储,就可以实现自定义session的共享了!

---zencart模板结构及组成---

zen cart模板和ecshop模板还不大一样.ecshop模板主要是采用smarty引擎原理,而zen cart模板主要是通过对html文件的部分分割,包含在不同的文件.而ecshop模板只是htm格式或者dwt格式.而且都是完整的模板概念.而zen cart主要分为header,footer,sideboxes三个部分.

 index.php 主文件
includes/templates/[custom template folder]/common/html_header.php 页面的head部分
includes/templates/[custom template folder]/common/tpl_main_page.php 页面的body部分
includes/templates/[custom template folder]/common/tpl_header.php 所有页面的页眉
(column left)  
includes/templates/[custom template folder]/common/main_template_vars.php 决定页面的内容部分,缺省为 'tmp_index_default.php'
 

首页 - 缺省
includes/templates/[custom template folder]/templates/tmp_index_default.php 首页模板文件
 

首页 - 显示分类
includes/templates/[custom template folder]/templates/tpl_index_categories.php 首页上显示分类时的模板文件
includes/modules/[custom template folder]/pages/index/category_row.php 选择要显示的分类
includes/templates/[custom template folder]/templates/tpl_index_category_row.php 显示分类
 

首页 - 显示指定分类
includes/templates/[custom template folder]/templates/tpl_index_product_list.php 首页上显示指定的分类时采用的模板文件
includes/modules/[custom template folder]/product_listing.php 将商品数据添加到数组
includes/templates/[custom template folder]/templates/tpl_modules_product_listing.php 显示商品数量和商品导航菜单
includes/templates/[custom template folder]/common/tpl_list_box_content.php 显示商品数组
 

商品信息页面
includes/templates/[custom template folder]/templates/tpl_product_info_display.php 显示单件商品信息
 

购物车页面
includes/templates/[custom template folder]/templates/tpl_shopping_cart_default.php 购物车页面
(column right)  
includes/templates/[custom template folder]/common/tpl_footer.php 所有页面的页脚

---后台产品上传及更新---

从product.php开始

require(‘includes/application_top.php’);      构建框架环境

require(DIR_WS_MODULES . ‘prod_cat_header_code.php’);    预处理文件

初始化货币类得到 $currencies 对象

根据 $_GET['product_type'] 获取合适的 $product_type,如果没有就默认为1

然后通过$product_type调用$zc_products->get_admin_handler($product_type)获得$type_admin_handler[类型处理器]

[这里要明白,产品可以分成几个类型,比如普通商品,文档等之类的虚拟产品,在添加新产品的时候,可以选择产品类型,针对不同的产品类型,处理方式不一(调用不同的文件实现差别处理),默认支持5种产品类型,在module文件夹中,对应了document_general document_product product product_free_shipping product_music 这些文件夹,在上传等操作进行时,会适当调用里面的文件。]

接下来把已经安装的产品类型装入$product_types_array,格式如下:

$product_types_array[] = array(‘id’ =>,’text’ =>);

判断是否有传递$_GET['action'],设置$action。

判断$action 是否为 insert|update|setflag,这些action需要加载DIR_WS_INCLUDES . ‘reset_seo_cache.php’ 文件[这个是ZC中文添加的页面缓存操作]

reset_seo_cache.php 文件中从缓存表中删除 like %seo_urls% 的文件。

接下来根据$action进行相应处理

如果是 setflag,直接调用zen_set_product_status更改状态,之后跳转到产品列表页[有三个参数,cPath, pID和page]

如果是delete_product_confirm ,根据$_POST['delete_linked']设置$delete_linked(这个来自删除目录操作的时候),根据$_POST['products_id']获取$product_type,然后到相对应的产品类型文件夹中加载delete_product_confirm.php,如果找不到就到module根下查找,这里说明可以重载模块。

delete_product_confirm.php文件分析

zen_admin_demo()判断是否在测试模式,如果是跳转防止删除

$_POST['product_categories']是一个数组,它保存了产品链接到的目录(最多只有两个,一个是直接目录一个是链接目录),比如希望挑选一些产品放到一个新目录中,那么产品的master_categories_id 将被设置为新目录的ID,这个字段默认存放它的直接目录ID。在products_to_categories 表中也会多添加这条记录进入。现在的问题是,如果要删除这个产品,那么products_to_categories中的记录也应该清理掉。

$product_id $product_categories $do_delete_flag = true;

然后判断是否存在$cascaded_prod_id_for_delete,这个变量在当删除目录时会删除里面的所有产品时,加载这个delete_product_confirm.php文件时会被带入。更新变量

$product_id = $cascaded_prod_id_for_delete;

$product_categories = $cascaded_prod_cat_for_delete; 是一个数组

[这一段代码要阅读categories.php的345行 case 'delete_category_confirm': 开始加以理解,这段代码也是先判断是否删除里面的产品有链接目录时是否删除链接对应记录($delete_linked 这个变量已经过时),默认是要删除的,然后根据要删除的目录的ID获取它的子目录树(包含当前目录),循环这个目录树,根据这个动态的目录ID,从products_to_categories表中循环抓取记录,这时获得两个变量$cascaded_prod_cat_for_delete 和 $cascaded_prod_cat_for_delete[],调用delete_product_confirm.php(循环被调用,一次从products_to_categories表中删除一条记录[确保这个产品脱离当前目录],如果这个产品没有再被引用,然后开始清理产品,至于如何删除,归zen_remove_product函数处理。在最后调用zen_remove_category 删除目录。)

问题:当删除一个目录时,里面的有从其它目录链接过来的产品,就是要删除的产品的master_categories_id还指向要删除的目录,可以确保这个链接产品从删除的目录中脱离,但是它的master_categories_id还指向已经删除了的目录ID. 没有问题吗?未知……,应该来说,链接它的目录没有了,也不能针对这个已经删除的目录搞什么花样了。

当删除一个目录时,这个目录里面的产品还被其它的目录链接,那么这个产品从当前目录脱钩的结果是这个产品直接变成链接目录的主产品,因为master_categories_id没有改动,而products_to_categories对应的只有一个记录其对应的目录和master_categories_id指向相同。(就是从一个目录移动到另一个目录,如此而已)]

接下来开始清理工作

1 清理要删除的产品对应的目录在products_to_categories 表中的记录(用目录 和 产品ID限定删除)

2 确保这个产品对应的目录记录已从products_to_categories 表中删除

3 如果目录记录已经清除,开始清理产品zen_remove_product($product_id, $delete_linked); 这个是一个复杂操作。我操,这个函数完全无视第二个参数的存在。

这个函数首先检查产品图片,如果产品图片没有被其它产品引用,全部干掉,否则不动。

如果产品被设置为特价产品,从特价列表中干掉。

TABLE_PRODUCTS

TABLE_PRODUCTS_TO_CATEGORIES

TABLE_PRODUCTS_DESCRIPTION TABLE_META_TAGS_PRODUCTS_DESCRIPTION

zen_products_attributes_download_delete($product_id);

TABLE_PRODUCTS_ATTRIBUTES

TABLE_CUSTOMERS_BASKET

TABLE_CUSTOMERS_BASKET_ATTRIBUTES

TABLE_REVIEWS 然后删除关联的记录  TABLE_REVIEWS_DESCRIPTION

TABLE_FEATURED

TABLE_PRODUCTS_DISCOUNT_QUANTITY

如果$action 是 insert_product_meta_tags update_product_meta_tags时,加载update_product_meta_tags.php,加载准备添加产品meta信息的处理代码。

如果$action是insert_product update_product时,加载update_product.php处理代码。

如果$action是copy_to_confirm时,加载copy_to_confirm.php

如果$action是new_product_preview_meta_tags,加载new_product_preview_meta_tags.php,这个将导向$action 是 insert_product_meta_tags update_product_meta_tags时的情况处理。

如果$action是new_product_preview,加载new_product_preview.php,这个将导向$action是insert_product update_product时的情况处理。new_product_preview.php 这个文件主要处理上传的图片……………………..

以下部分是视图控制

<?php if ($action != ‘new_product_meta_tags’ && $editor_handler != ”) include ($editor_handler); ?> 编辑或更新meta信息都不需要编辑器的支持。

如果$action 是new_product 或 new_product_meta_tags

是new_product,加载collect_info.php      重点理清

初始化一个对象$pInfo

如果有$_GET['pID'] 但是 $_POST数组是空的,说明是编辑产品,从数据库里面读取数据并且填充$pInfo对象,否则要是有$_POST数组,用$_POST数组更新$pInfo对象,并记录下$products_name $products_description $products_url(这些是数组变量,语言相关)[不得不说,这是一个技巧,当数据提交到预览页面时,如果要返回,那么它又把之前POST过去的数据又POST回来,表单中使用了一个name=’edit’ 的表单域,判断是返回编辑页面]

$manufacturers_array[]

$tax_class_array[]

$languages = zen_get_languages();

if (!isset($pInfo->products_status)) $pInfo->products_status = ’1′;  默认启用

switch ($pInfo->products_status) {

case ’0′: $in_status = false; $out_status = true; break;

case ’1′:

default: $in_status = true; $out_status = false;

break;

}

接下来一连串的变量更正。

开始写表单,POST到new_product_preview

用变量填充视图。关键看图片处理:

读取图片文件夹所有子文件夹 $dir_info   id  对应 ‘目录名/’  text 对应 ‘目录名’

$default_directory 根据$pInfo->products_image截获目录,如果是新产品上传就是空

生成一个文件域products_image,如果$pInfo->products_image不为空还显示这图片地址,并且把$pInfo->products_image值保持到一个名叫products_previous_image的隐藏域中

用$dir_info, $default_directory生成一个选择框,名为img_dir

接下来是 image_delete 和 overwrite  products_image_manual 指定一个图片链接给它。

…………………………………………………

是new_product_meta_tags,加载collect_info_metatags.php

否则如果是new_product_preview 或 new_product_preview_meta_tags

是new_product_preview,加载preview_info.php  重点理清

注意:这里如果是上传了图片,$products_image_name记录了新图片的地址,如果上传文件失败就用$_POST['products_previous_image']填充这个标量,如果$_POST['products_previous_image']为空,就把它至为空。这段代码关键地方是 当编辑产品时$_POST['products_previous_image']不能过来是空,否则上传的文件失败或者直接没有设置上传文件,那么上传文件解析失败,使用$_POST['products_previous_image']填充$products_image_name

用$_POST填充$pInfo,从$_POST记录$products_name $products_description $products_url这些语言相关的变量。

接下来确定提交update_product 还是 insert_product

显示提交的数据

开始隐藏数据,方便回显,特别注意zen_draw_hidden_field(‘products_image’, stripslashes($products_image_name)); 他用$products_image_name 赋值给products_image。这样回显后又把这个products_image赋值给products_previous_image,实现来回转换。

是new_product_preview_meta_tags加载preview_info_meta_tags.php

否则就加载category_product_listing.php进行目录货产品列表