ZenCart类库-shipping.php解读实现原理

本篇文章解读 includes/classes/shipping.php shipping类的实现
关于 MODULE_SHIPPING_INSTALLED
表示系统中已经安装的模块,在后台配置中描述如下

Installed Modules
List of shipping module filenames separated by a semi-colon. This is automatically updated. No need to edit. (Example: ups.php;flat.php;item.php)

请进行必要的更改

已安装的模块
装运模块文件名列表,以分号分隔。
这会自动更新。 无需编辑。 (例如:ups.php; flat.php; item.php)
————————————————

关于构造函数的作用

1.加载你安装的模块

加载原理就是上面 MODULE_SHIPPING_INSTALLED,这个数据库配置,此配置在隐藏配置组id=6里面,后台其实没有显示,但是可以通过http://localhost/ZenCart156cDev/sprAy-Dsk-birtH/configuration.php?gID=6 访问这个配置组

另外此字段的配置是在 includes/init_includes/init_db_config_read.php 初始化时加载到系统中的。

分割此字段的值,得到数组

循环数组--得到类名和文件的名字

然后在DIR_WS_MODULES . 'shipping/'目录下加载

先加载模块对应的语言文件,然后加载模块本身

最后注册到 $GLOBALS变量中去,类名字作为索引,类实例作为值
————————————————

2.加载模块对应的语言

3.根据模块属性,确定模块是否开启or关闭

检查的原理是使用 check_enabled 函数,该函数的参数类型--使用类实例作为 输入参数。其内部使用method_exists方法检查类实例对象是否有指定的方法,然后调用类实例的方法 check_enabled_for_zone 或者check_enabled。

至此shipping其实已经实现了,类似的.net反射的特性,也是实现插件机制的原理。

通过shipping可以调用某一个具体实现类,比如flat类中的函数,实现了易于扩展的特性。

按照以下的优先次序返回插件是否启用

第一:默认$enabled = $class->enabled;默认的,其实就是flat类构造函数执行时初始化的属性,其内部调用了zen_get_shipping_enabled函数,并对区域做了检查

第二:$enabled = $class->check_enabled_for_zone();

第三:$enabled = $class->check_enabled();
————————————————

4.实例化模块,构造实例对象,并注册到全局变量【这是最终的目的】

$modules

构造函数中定义了此属性

这个属性只是单纯的安装模块“MODULE_SHIPPING_INSTALLED”分割之后的结果,除此之外再无其他

MODULE_SHIPPING_INSTALLED

在初始化过程中,只是读取了配置组2和3的配置,MODULE_SHIPPING_INSTALLED在配置组6里面,那么它是如何读取的呢?

此问题已经解答了,从上面看

关于flat类–模块的属性

code--模块的标识代码,通常就是类名字,和类文件同名,同时在$GLOBALS变量中引用它

title--模块标题,在语言文件中定义

description--模块本身描述,在语言文件中定义

sort_order--排序,排序字段是否定义决定了模块是否启用,也是非常重要的

icon---图标

tax_class--使用的税种

tax_basis--税种基于什么计算 一下是说明

On what basis is Shipping Tax calculated. Options are
Shipping - Based on customers Shipping Address
Billing Based on customers Billing address
Store - Based on Store address if Billing/Shipping Zone equals Store zone

enabled--该模块是否被启用

_check--属性用来读取插件的MODULE_SHIPPING_FLAT_STATUS 状态值
————————————————

关于zen_get_shipping_enabled的作用

disable only when entire cart is free shipping
仅当整个购物车免费送货时禁用

此函数内部注释先列出来

for admin always true if installed
对于管理员,如果已安装,则始终为true


Free Shipping when 0 weight - enable freeshipper - ORDER_WEIGHT_ZERO_STATUS must be on
0重量时免费送货-启用freeshipper-订单重量必须为0状态


Free Shipping when 0 weight - disable everyone - ORDER_WEIGHT_ZERO_STATUS must be on
0重量时免费送货-禁用所有人-订单重量必须为0


Always free shipping only true - enable freeshipper
始终免费送货-启用freeshipper


Always free shipping only true - disable everyone
始终免费送货-禁用所有人


Always free shipping only is false - disable freeshipper
总是免费送货是错误的-禁用免费送货
————————————————

同时牵连出一下函数

$_SESSION[‘cart’]->in_cart_check(‘product_is_always_free_shipping’,’1′);

检查指定字段的产品数

$_SESSION[‘cart’]->count_contents();

统计购物item总数

$_SESSION[‘cart’]->show_weight();

统计购物车总重量
————————————————

关于quote方法

返回对方法的引用,此方法可以返回所有模块的引用,也可以单独返回某一个模块的引用

内部实现机制是:

首先引用$shipping_weight, $uninsurable_value;$uninsurable_value表示的是运费险,看某一具体的类是否有get_uninsurable_value方法

定义$quotes_array,这是我们最终要返回的数组对象,这个数组对象是只包含已经启用的模块

通过两个循环,从$this->modules属性中分析你要的模块

第一个foreach循环实现了从$GLOBALS检查,判断模块的启用状态,只将满足启用状态的模块存入到$quotes_array

第二个循环,更新状态;调用某一具体shipping的quote方法,重新赋值计算重量的全局变量
————————————————

接下来一个问题是:flat的运费是如何被计算出来的呢?
$shipping_weight是在何时定义的?
会话$_SESSION[‘shipping’]是在什么地方被写入的?
shipping模块在实例化的时候,就已经确定并检查好哪些模块是可以使用的

关于设想的需求环境
所有订单免邮费

所有订单固定一个邮费

所有订单固定一个邮费,但是对某一个区域单独启用

订单满多少金额,就免邮费

订单金额设置区间范围,在不用的范围内,运费不一样

订单安装数量免邮费

关于flat类
这是一个提供统一费率的运输模块,所有的订单运费都是一样的,但是还可以设置在某个地区开启

关于flat类quote方法

quote中文意思是引用,此方法就是返回对此类的相关信息的引用

存储在quotes数组内,结构如下

id--模块的唯一标识符,全局内不要重复

module--模块的标题,被定义在语言包内

methods--这是一个数组,其中包含了关于运费的计算

tax--税率

icon--运费图标

结合分析 flat.php模块和freeshipper.php模块,两者编写方式高度相同

flat.php—-表示所有的订单采用统一的运费,税率

freeshipper.php—-表示免邮费

flat配置模块的区域是在什么地方设置的?暂时未知

zen_cfg_pull_down_zone_classes