php 订单折扣计算,zen cart根据购物车产品数量或订单总额进行折扣

zen cart关于折扣的插件不少,但大部分是基于产品的,比如买多少个产品时,价格打多少折,或者是买多少个产品送多少。今天要探讨的是基于订单总金额或整个购物车产品的数量来打折。如,

当订单金额超过$500时,优惠$26

当订单金额超过$1000时,给%8的折扣

当订单中产品总数量超过5个时,给予整个订单总额%5的折扣

当订单中产品数量超过20个时,整个订单打9折

等等… …

经过对zen cart相关代码的分析,我发现实施上面的这睦规则其实很容易。只是zen cart本身并没有非常好的模块和数据分离机制,所以我就先把简单实施的方法写出,待以后有空再整理形成模块发布。

几乎所有的zen cart模板通常只会有两到三个地方会显示订单的汇总信息,一个是在购物车页面shopping_cart,再一个是订单信息确认页面checkout_confirmation,最后还有可能显示的则是相关的sidebox.当然某些zen cart模板可能会有更多的页面有显示这个内容。不过总结下来,不外乎这两个页面的修改。所以,实现这个打折功能的主要工作就是修改这两个页面和生成订单的类。事实上经过代码分析我发现shopping_cart页面的订单统计采用的方法和checkout_confirmation页面的不一样,前者是调用shopping_cart类,而后者是调用order类。

先看下shopping_cart页面的模板includes/templates/[模板名称]/templates/tpl_shopping_cart_default.php:

原先购物车只显示订单总金额,现在要显示三项,分别是打折前总金额,优惠的金额,折扣后的总金额,模板要修改成

那么就需要在shopping_cart对应的header_php.php文件中定义初始化这三个变量includes/modules/pages/shopping_cart/header_php.php:

$flagHasCartContents = ($_SESSION['cart']->count_contents() > 0);

$cartShowTotal = $currencies->format($_SESSION['cart']->show_total());

//added by george

$cartOtotal = $currencies->format($_SESSION['cart']->show_ototal());

$discountTotal = $cartOtotal - $cartShowTotal;

$cartOtotal是订单原价,$cartShowTotal是打折后的订单总额.$discountTotal优惠的金额。下一步则是对shopping_cart类的修改了:修改calculate成员方法实现打折规则;添加一个成员属性来保存原价;添加一个方法也读取原价;代码如下:

-------includes/classes/shopping_cart.php

...

...

var $contents;

/**

* shopping cart total price

* @var decimal

*/

var $total;

/**

* shopping cart total weight

* @var decimal

*/

//added by george

//添加成员属性$ototal

var $ototal;

/**

* Method to calculate cart totals(price and weight)

*

* @return void

* @global object access to the db object

*/

function calculate() {

global $db;

$this->total = 0;

$this->weight = 0;

...

...

...

// + or blank adds

if ($attribute_weight->fields['products_attributes_weight_prefix'] == '-') {

$this->weight -= $qty * $new_attributes_weight;

} else {

$this->weight += $qty * $new_attributes_weight;

}

}

} // attributes weight

}

//added by george to apply discount

//实现打折规则

$this -> ototal = $this -> total; //save origianl order total

if ( $this -> count_contents() == 2) {

$this -> total = $this -> total * 0.95;

} elseif ( $this -> count_contents() >= 3) {

$this -> total = $this -> total * 0.9;

}

//end of discount code

}

/**

* Method to calculate price of attributes for a given item

...

...

/**

* Method to calculate total price of items in cart

*

* @return decimal Total Price

*/

function show_total() {

$this->notify('NOTIFIER_CART_SHOW_TOTAL_START');

$this->calculate();

$this->notify('NOTIFIER_CART_SHOW_TOTAL_END');

return $this->total;

}

//added by george

//获取原价的方法

function show_ototal() {

$this->notify('NOTIFIER_CART_SHOW_TOTAL_START');

$this->calculate();

$this->notify('NOTIFIER_CART_SHOW_TOTAL_END');

return $this->ototal;

}

到目前为止,对购物车页面的修改算是完成了。当然CSS之类的修饰是必要的。这里就不提了。不过订单确认页面checkout_confirmation还末修改。

if (MODULE_ORDER_TOTAL_INSTALLED) {

$order_totals = $order_total_modules->process();

?>

output(); ?>

}

?>

显然checkout_confirmation页面的订单汇总信息是通过$order_total_modules对象生成的而这个对象是在checkout_confirmation页面的header_php.php中定义的:

./includes/modules/pages/checkout_confirmation/header_php.php:66:$order_total_modules = new order_total;

那么再往上追踪一步应该是查看order_total类的output方法了:

function output($return_html=false) {

global $template, $current_page_base;

$output_string = '';

if (is_array($this->modules)) {

reset($this->modules);

while (list(, $value) = each($this->modules)) {

$class = substr($value, 0, strrpos($value, '.'));

$size = sizeof($GLOBALS[$class]->output);

// ideally, the first part of this IF statement should be dropped, and the ELSE portion is all that should be kept

if ($return_html == true) {

for ($i=0; $i

$output_string .= '

' . "\n" .

'

' . $GLOBALS[$class]->output[$i]['title'] . '

' . "\n" .

'

' . $GLOBALS[$class]->output[$i]['text'] . '

' . "\n" .

'

';

}

} else {

// use a template file for output instead of hard-coded HTML

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

}

}

}

return $output_string;

}

显然最终调用的是tpl_modules_order_totals.php这个模板:

for ($i=0; $i

output[$i]['text']; ?>

output[$i]['title']; ?>

通过分析zen cart的order_total类的构造函数order_total(代码如下),再综合order_total类的output方法,process方法,可以确定tpl_modules_order_totals.php这个模板是通过调用includes/modules/order_total/目录下的ot_subtotal,ot_shipping,ot_total这三个类。通过在tpl_modules_order_totals.php这个模板

function order_total() {

global $messageStack;

if (defined('MODULE_ORDER_TOTAL_INSTALLED') && zen_not_null(MODULE_ORDER_TOTAL_INSTALLED)) {

$module_list = explode(';', MODULE_ORDER_TOTAL_INSTALLED);

reset($module_list);

while (list(, $value) = each($module_list)) {

//include(DIR_WS_LANGUAGES . $_SESSION['language'] . '/modules/order_total/' . $value);

$lang_file = zen_get_file_directory(DIR_WS_LANGUAGES . $_SESSION['language'] . '/modules/order_total/', $value, 'false');

if (@file_exists($lang_file)) {

include_once($lang_file);

} else {

if (IS_ADMIN_FLAG === false) {

$messageStack->add(WARNING_COULD_NOT_LOCATE_LANG_FILE . $lang_file, 'caution');

} else {

$messageStack->add_session(WARNING_COULD_NOT_LOCATE_LANG_FILE . $lang_file, 'caution');

}

}

//由此可确定调用的是includes/modules/order_total/目录下的这些类

$module_file = DIR_WS_MODULES . 'order_total/' . $value;

if (@file_exists($module_file)) {

include_once($module_file);

$class = substr($value, 0, strrpos($value, '.'));

$GLOBALS[$class] = new $class;

$this->modules[] = $value;

}

}

}

}

Ok,终于快找到我们要修改的代码了。再分析一下,现在checkout_confirmation显示的三项是subtotal,shipping,order total,订单原价,运费,加运费后订单总额。

通过分析ot_subtotal,ot_shipping,ot_total这三个类对output数组的初始化,我最终发现数据最终来源于order类[includes/class/order.php],以ot_total为例看一下代码:

function process() {

global $order, $currencies;

$this->output[] = array('title' => $this->title . ':',

'text' => $currencies->format($order->info['total'], true, $order->info['currency'], $order->info['currency_value']),

'value' => $order->info['total']);

}

最终我通过修改了order类cart成员方法,直接应用了打折规,实现代码如下:

*********************************************/

$index++;

}

//下面的代码实现打折规则,不过这样写运费是没参与打折的

$this->info['osubtotal'] = $this->info['subtotal'];

if ( $_SESSION['cart'] ->count_contents() == 2) {

$this->info['subtotal'] *= 0.95;

} elseif( $_SESSION['cart'] ->count_contents() >= 3) {

$this->info['subtotal'] *= 0.9;

}

// Update the final total to include tax if not already tax-inc

if (DISPLAY_PRICE_WITH_TAX == 'true') {

$this->info['total'] = $this->info['subtotal'] + $this->info['shipping_cost'];

} else {

$this->info['total'] = $this->info['subtotal'] + $this->info['tax'] + $this->info['shipping_cost'];

}

需要注意的是,上面的这个代码打折是针对产品的总价,没有对运费打折。如果要对运费也打折,那就要修改成这样:

*********************************************/

$index++;

}

// Update the final total to include tax if not already tax-inc

if (DISPLAY_PRICE_WITH_TAX == 'true') {

$this->info['total'] = $this->info['subtotal'] + $this->info['shipping_cost'];

} else {

$this->info['total'] = $this->info['subtotal'] + $this->info['tax'] + $this->info['shipping_cost'];

}

//在这边应用打折规则,是对订单总金额,包括运费一起打折

if ( $_SESSION['cart'] ->count_contents() == 2) {

$this->info['total'] *= 0.95;

} elseif( $_SESSION['cart'] ->count_contents() >= 3) {

$this->info['total'] *= 0.9;

}

以上的只是我实施后的对实现思路的粗略回忆,待有空再整理成zen cart模块形式发布。并在zen cart后台设置一个界面进行打折规则的设置。而不是将打折规则写死在代码中。

(责任编辑:最模板)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值