如何清理微信缓存调整 secache 缓存

ShopEx-共享资料网
ShopEx 完全手册author : ShopEx 开发团队 since :
$Rev: 308 $1. 前言和导读 2. 安装和使用o ? o o ? ? ? o ? ? o o o ? ? ? ? ? ? ? ? ? ?2.1. 安装 shopex 2.1.1. 如何选择主机 2.2. 初始化配置系统 2.3. 系统调优 2.3.1. url rewrite 2.3.2. 搜索引擎优化(SEO) 2.3.3. 服务器配置 2.4. 操作技巧 2.4.1. 使用快捷键 2.4.2. 使用条码扫描器 2.5. 业务成长之后... 2.6. 升级方法3. 扩展 shopex 3.1. 插件体系 3.1.1. 用户登录插件(passport) 3.1.2. 图片存储方式插件(storager) 3.1.3. 支付方式插件(payment) 3.1.4. 网店机器人动作插件(actions) 3.1.5. 数据导入导出插件(dataio) 3.1.6. 用户消息插件(messenger) 3.1.7. 单独页面布局插件(layout) 3.1.8. 地区数据插件(location) 3.1.9. 网页挂件(widgets) 3.1.10. 商品插件(schema) ? ? o o ? o o ? ? ? o ? ? o o o ? ? ? ?6. 附录 4. 系统探秘3.1.11. 前台功能插件(shop) 3.1.12. 后台功能插件(admin) 3.2. 软件功能包(app) 3.3. 使用二次开发接口 3.3.1. 案例 A: 更改友情链接页面显示个数 3.4. 自定义核心流程页面模板4.1. 系统结构 4.1.1. 数据库结构定义文件 4.1.2. 网店对象 4.1.3. 业务模型(model) 4.2. 运行过程 4.2.1. 前台流程 4.2.2. 后台流程 4.3. 配置信息的存储 4.4. 模板系统 4.5. 缓存机制 4.5.1. 基于 http 协议的浏览器缓存 4.5.2. 前台全页缓存-控制器 4.5.3. 前台全页缓存-存储器 4.5.4. 模板缓存5. shopex 对外数据接口o o o6.1. setting 6.2. 数据库手册 6.3. 结构图1. 前言和导读本手册对应版本 shopex 4.8.5 本手册部分内容由 shopex 系统源代码直接生成,因此会持续保持更新 ? ? html 版本: http://docs./shopex-b2c/ pdf 版本: http://docs./shopex-b2c/shopex-book.pdf相关文档 ? 模板手册: http://docs./shopex-b2c/tplbook/本手册适合谁来阅读: ? 网店店主: 查看包括怎样获取 shopex。如何选择主机。怎样安装和调优你的网店系统。 ? 开发者: 希望扩展 shopex 功能的朋友,本手册将为你展示多种扩展系统的方法,你将发现 shopex 已经为你很多准备工作。手册后面的附录里包含了 shopex 系统的数据对象和数 据库的定义细节。2. 安装和使用ShopExV4.8 网店系统是一套基于网上快速建店的标准化 B2C 电子商务系统。系统集成了最基本最普通最常用的电子商务运作流程及使用功能,可以满足正常的开店需求。2.1. 安装 shopex 2.1.1. 如何选择主机 shopex 提供了一个服务器性能检测探针文件,位于 install/svinfo.php。你可以单独上传这个文件到被测的服务器环境上。这个探针所探测的数据和你在系统安装时或者后 台看到的服务器状态 是完全一样的。 下面就是个典型的服务器检测报告:$Rev: 308 $ ShopEx 服务器测评 ================================================================ 服务器基本信息 ================================================================ 操作系统 WINNT 服务器软件 Apache/2.0.59 (Win32) DAV/2 SVN/1.4.0 PHP/5.2.3 php 运行方式 apache2handler ================================================================ php 基本信息 ================================================================ php 版本 5.2.3 程序最多允许使用内存量 memory_limit 128M POST 最大字节数 post_max_size 8M 允许最大上传文件 upload_max_filesize 2M 程序最长运行时间 max_execution_time 30 被禁用的函数 disable_functions 无 ================================================================ 基本需求 ================================================================ PHP4 以上 5.2.3 zend.ze1_compatibility_mode 关闭 Off 支持文件锁(flock) 支持 php 可以解析 xml 文件 支持 MySQL 函数库可用 5.0.37 数据库 Mysql 3.2.23 以上 127.0.0.1:3306 ZEND Optimizer2.5.7 以上 未安装 DNS 配置完成,本机上能通过域名访问网络 成功 ================================================================ 推荐配置 ================================================================ unix/linux 主机 WINNT php 版本 5.2.0 以上 5.2.3 MySQL 版本 4.1.2 以上 5.0.27 GD 支持 freetype,gif,jpg,png,bmp Zlib 支持 支持 Json 支持 支持 mbstring 支持 支持 fsockopen 支持 支持 iconv 支持 支持 register_globals 关闭 已关闭 allow_url_include 关闭 (php5.2.0 以上) 已关闭 高速缓存模块(apc,memcached) Memcached小技巧: ? 你可以在 ie 浏览器里直接 ctrl+a,ctrl+c 复制出来,不需要担心格式问题 ? 这是个独立的文件,同时也会检测 php 环境和 zend opt。2.2. 初始化配置系统 2.3. 系统调优 2.3.1. url rewrite? ? ? 如果开启 rewrite,过去的网址将依然有效,用户可以同时通过新老两种 url 访问你的系统。同时我们会通过发送 301 头信息更新搜索引擎的记录为新地址 该转换规则存在于 plugins/functions/urlmap.php 文件中。 其他系统转换过来的用户可以通过修改该文件,使得旧地址依然有效 新版本 url 地址映射关系是由 plugins/functions/actmapper.php 文件所定义, 熟悉 php 的用户可以自己设计独特的 url 方式Apache 的 rewrite 规则RewriteEngine on # 设置 RewriteBase 的值为你的商店目录地址 RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?$1 [L]rewrite 启用方法,就是把 root.htaccess 改名成.htaccess。更改.htaccess 文件中 rewritebase 为你 url 的前缀如果感觉麻烦,直接在后台 设置-&基本设置-&启用伪静态。由 程序自动完成上面两个工作。 IIS 下的配置方法 iis 下需要 isapi_rewrite 第三版 , 老版本的 rewrite 不支 持 RewriteCond 语法。下载地址 /download-isapi_rewrite3.htm 下载那个 ISAPI_Rewrite Lite for Windows NT4/2000/XP/2003 (Freeware!)即可,免费软件! 安装好后,规则和 apache 类似。直接复制到 httpd.conf 文件中即可,有的系统也可能 叫 httpd.ini。# 设置 RewriteBase 的值为你的商店目录地址 RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?$1 [L]管理工具-& internet 信息服务-& 网站 点右键. -& 属性 ISAPI 筛选器看到下面那个 ISAPI_Rewrite3 了吧。 转到 rewrite 的选项卡 可以看到里面的 rewrite 规则 设置 mime 类型,启用 javascript 加速Nginx 请修改 PATH 为你的安装路径location /PATH/ { if (!-e $request_filename) { rewrite ^/PATH/(.*)$ /PATH/index.php?$1 } }webserver 众多,我们仅列出具有代表性的几款2.3.2. 搜索引擎优化(SEO) 2.3.3. 服务器配置 2.4. 操作技巧 2.4.1. 使用快捷键快捷键 alt+1 alt+2 alt+3 alt+4 alt+5 alt+6 alt+5 esc R 功能 商品 订单 会员 营销推广 站点管理 统计报表 站点管理 关闭对话框 / 关闭列表详细 刷新主区域 切换左侧导航 U 打开使用向导 H 定位到搜索框 / 按下 Ctrl 点击鼠标拖动列表页 将航向滚动列表到拖动方向2.4.2. 使用条码扫描器 2.5. 业务成长之后...当你需要丰富的权限分配,工作流,来规范你的业务流程的时候。可以选用 shopex 提供的订单处理中心系统。 当你需要扩展网店系统功能来支撑精细化的销售运作的时候。你可以寻找一些有技术实例的团队来解决这个问题。当然你也可以组织自己的技术部门,把本手册第三章后面的部分扔 给他们就好了。shopex 内建的插件体系足够让他们满足你的要求。2.6. 升级方法现在的升级逻辑很简单 先跑 php 然后调用 diff 先跑 php 是让数据库里的东西可以跟着变过来 调用数据库 diff 去处理 php 没搞完的杂事3. 扩展 shopex扩展有两种办法,一种是通过增加插件。另一种是采用我们称之为&第三方开发方案&的方式。 ? shopex 对插件的设计目标是语法简单,并且可以很方便的将成果发布,传递出去。 ? 第三方开发方案的特点是,无所不能,功能强大。但实现稍微复杂。 除了一些基本的模板改动之外,其他都要求开发者要基本的懂得 PHP 语法,并且有一些最基础的面向对象编程的知识。函数不熟可以去查手册,大多数时候,只要会改的技能就可 以了。3.1. 插件体系shopex 系统支持 13 种插件,其中促销方式可能在会后面的版本有大的改动。插件名 用户登录插件 图片存储方式插件 支付方式插件 促销方式插件 网店机器人动作插件 数据导入导出插件 用户消息插件 单独页面布局插件 地区数据插件 网页挂件 商品插件 前台功能插件 后台功能插件类型 -标示名默认路径passport plugins/passport storager plugins/storager payment plugins/payment pmtScheme plugins/pmtScheme action plugins/action dataio plugins/dataio messenger plugins/messenger layout plugins/layout location plugins/location widgets plugins/widgets schema plugins/schema shop admin -从插件的文件组织方式上可以分成目录型和文件型两大类插件。 ? 文件型插件: 每个单独的 php 文件就是一个插件,文件名和其中的类的名称要符合一下规则: o o 文件名: &标示名&.插件名.php 类名: &标示名&_插件名 例如: 支付插件 taobao 的文件名是:payment.taobao.php, 对应的文件内容是:&?php class payment_taobao { var $name = ... //插件名称 var $version = ... //版本号 ... } ?&可以被放置在除目录型插件里面的任何 plugins 下的任何位置。到后台刷新插件数据库时,就会被发现。 ? 目录型插件: 因为有些自己的资源,所以被设计成独立的一个目录,其中必须放置一个主插件 php 文件,文件的命名规则和类的内容都和文件型插件相同。 一个目录下只能放置一 个主文件。其余文件都作为这个主文件的资源存在。 可以被放置在除目录型插件里面的任何 plugins 下的任何位置。 在 4.8.5 版本之后,不同类型插件不需要放在各自类型的目录里。只要放在 plugins 下面就都可以被扫描到。这是为下一步 app 机制作的准备。3.1.1. 用户登录插件(passport)文件型 可以集合 msn passport, google account, openid 等统一登录系统 &?php class passport_phpwind extends modelFactory { var var var var var $passport_name = &PhpWind 论坛 V6.3.2&; //整合论坛名称 $passport_memo = &描述&; //整合论坛描述内容 $_config = //初始化配置变量 $forward = 0; //初始化跳转链接变量 $name = &phpwind&; //用户登陆插件名称/** * setConfig,发送时调用 * 必有方法,config 参数为 getOptions 取得的所有项的配置结果 */ function setConfig($config) { $this-&_config = $ } /** * verifylogin,用户登陆验证 * 可选方法,login 参数为用户名,passwd 参数为用户密码 */ function verifylogin($login,$passwd){ } /** *decode,解码 *可选方法 */ function decode($responseData){ } /** * getoptions * 必有方法,取得的所有项的配置结果 * 返回一个配置结果的数组 */ function getoptions(){ return $ } /** * login,用户登陆 * 必有方法,userId 参数为用户 Id 号,rurl 参数为返回的跳转链接 */ function login($userId, $rurl) { } /** * regist,用户注册 * 必有方法,userId 参数为用户 Id 号,rurl 参数为返回的跳转链接 */ function regist($userId,$rurl) { } /** * logout,用户退出 * 必有方法,userId 参数为用户 Id 号,rurl 参数为返回的跳转链接 */ function logout($userId,$rurl) { } /** * _StrCode,编码/解码 * 可选方法,string 参数为需要进行处理的字符串, * action 参数表示对数据进行 ENCODE 编码还是 DECODE 解码 */ function _StrCode($string,$action='ENCODE'){ } /** * ClientUserAction * 必有方法,action 参数为作为客户端操作动作, * userdb 参数为数据库名,forward 参数为跳转链接 */ function ClientUserAction($action,$userdb,$forward=''){ } /** * StrCode,编码/解码 * 可选方法,string 参数为需要进行处理的字符串, * action 参数表示对数据进行 ENCODE 编码还是 DECODE 解码 */ function StrCode($string,$action='ENCODE'){ } /** * ServerClient * 必有方法,action 参数为作为服务器端操作动作 */ function ServerClient($action){ } /** * getPlugCookie,取得插件 Cookie * 可选方法,action 参数为作为服务器端操作动作 */ function getPlugCookie(){ } /** * setPlugCookie,设置插件 Cookie * 可选方法,val 参数为设置插件 Cookie 的值 */ function setPlugCookie($val){ } } ?& 3.1.2. 图片存储方式插件(storager)文件型 如果你去查看 shopex 系统里存放商品图片的数据表 sdb_gimages,会发现图片存放是一个竖线分割的字符串, 规则如下:网址|资源定位|存储方式比如:images/goods/01/02.jpg|goods/01/02.jpg|fs_storager为什么要这样设计? 我们把这个字符串叫 storager 格式,他的好处是可以方便的使用多种存储后端,shopex 可以把图片存在 ftp 上,存在 flickr 里,存在 amazon 的 s3 里,或者存在 memcache 里。 在此分段解释一下各部分的使用方式: ? 第一个段是用来在前台访问的:就是 url,可以是绝对地址,也可以是相对地址。 ? 第二段是存储代码用来定位资源的:比如是 flickr 里的图片 id, ftp 服务器里的相对资源 ? 第三段是图片存储器的类型表示, 代码会定位到 plugins/function/&存储类型&.php 规则很简单,只取第一个竖线前面的部分,我们通过一个 smarty 插件做 storager 格式和 url 的转换:&img src=&$storager_str|storager& alt=&& /& 如果是远程图片,或者是从其他系统导入的数据,就不会有竖线。storager 过滤器就把整条数据都当第一段来处理,以此保证这个结构的兼容性。 第二段和第三段是用来管理资源 的当对这个图片进行删除,修改等操作时,系统会找到由第三段定义的存储插件,然后用插件通过第二段进行定位进而对资源进行操作。下面贴一个使用 nginx + Tokyo Tyrant 进行存储的方案: nginx 的 NginxHttpMemcachedModule 有个很牛 X 的特性,可以使用 url 作为 memcache 的 key 进行资源访问。这使得建造分布式的图片存储集群变得简 单,同时,性能也有大规模提升。 使用内存做存储有两个缺点, 一是有容量限制, 二是不能永久存储。 因此我们使用 Tokyo Tyrant 做存储方案。 Tokyo Tyrant 是 Tokyo Cabinet 的网络接口, 可以使用 memcached 一样的协议。同 memcache 相比,Tokyo Cabinet 可以将资源存放在硬盘中,可以实现互备,可以作为永久存储方案。 实施分两部分,首先配置软件端,我们增加一个 shopex 的存储插件 C tt_storager 在其中实现向 tt 服务器的存储部分,很简单:把它当 memcache 用就可以了。function save($file,&$url,$type,$addons){ $id = $this-&_get_ident($file,$type,$addons,$url,$path); if($path && $this-&memcache-&set($path,file_get_contents($file))){ $this-&memcache-&delete($file,10); return $ }else{ } }接着配置 nginx,让他可以对那个访问的 url 到 tt 上取资源:#这里可以配置 n 组 tt_server upstream tt_server1{ #配置一个 tt 服务器组 server 192.168.2.35:11211; server 192.168.2.36:11211; #双主互备 } server { server_ listen *:80; location / { set $memcached_key $ memcached_pass tt_server1; } }接下来,搭建一组这样的 nginx 服务器,再配合 lvs,nginx 集群+tt 集群,一个高性能,高可用互备的图片集群就建立起来了。3.1.3. 支付方式插件(payment)文件型&?php require('paymentPlugin.php'); class pay_xxxx extends paymentPlugin{ var $name = 'xxx'; //支付方式名称 //支付方式 logo 名称, //logo 图片保存在\plugins\payment\images 下, //命名规则比如:logourl.gif var $logo = 'logourl'; var $version = ; //支付方式版本 var $charset = 'gb2312'; //编码设置 //订单提交正式交易地址 var $submitUrl= '/Payment.aspx'; //提交按钮的图片地址 var $submitButton = '提交按钮 url'; //支持支付的货币类型,定义的数组中货币类 //型键值根据支付网关给出的技术文档来决定 var $supportCurrency = array(&CNY&=&&RMB&, &USD&=&&02&); //支持支付的地区 var $supportArea = array('AREA_CNY','AREA_USD'); var $desc = ''; //支付方式描述 var $intro = ''; //支付方式介绍 var $M_Language = &1&; //语言选择,表示商家使用的页面语言 //在添加支付方式时,下拉列表的排列顺序(越小越靠前显示) var $orderby = 29; var $head_charset = &gb2312&; //编码设置 //支持真实的外币交易 var $cur_trading = /** * toSubmit,向支付网关发出支付请求 * 必有方法,payment 参数为需要提交的订单详细信息 */ function toSubmit($payment){ return $ } /** * callback,支付网关向系统发出支付应答 * 必有方法,返回四种状态: * 1.PAY_ERROR:签名认证失败; * 2.PAY_SUCCESS:支付成功; * 3.PAY_FAILED:支付失败; * 4.PAY_PROGRESS:交易处理中; */ function callback($in,&$paymentId,&$money,&$message,&$tradeno){ return PAY_ERROR; } /** * getfields * 必有方法,返回所需要配置的信息数组 */ function getfields(){ return array( 'member_id'=&array( 'label'=&'客户号', //配置信息标签 'type'=&'string' //配置信息类型 ), 'PrivateKey'=&array( 'label'=&'私钥', 'type'=&'string' ) ); } /** * applyForm,支付方式申请的表单 * 可选方法,agentfield 参数为申请表单需要提交的信息 * 返回一个支付方式申请的表单 */ function applyForm($agentfield){ return $tmp_ } } ?&3.1.4. 网店机器人动作插件(actions)文件型&?php class action_order{ var $name = '订单触发器可用动作'; //动作名称 var $action_for = 'trading/order'; //绑定的特殊模块 /** * actions,机器人执行动作 * 必有方法,返回机器人执行动作数组 */ function actions(){ return array( 'addPoint'=&array( 'label'=&'增加积分', //执行动作标签名称 //执行动作的内容,以及该内容的类型 'args'=&array('点数'=&array('type'=&'number'))), 'delPoint'=&array('label'=&'扣除积分' ,'args'=&array('点数'=&array('type'=&'number'))), 'addCoupon'=&array('label'=&'送订单优惠券' ,'args'=&array('优惠券'=&array( 'required'=&true, //引用对象的特殊模块 'type'=&'object:trading/coupon', 'filter'=&'cpns_type=1&ifvalid=1') )), ); } /** * addPoint,根据 actions 方法返回的动作命名的函数 * 必有方法,data 参数为订单信息,point 参数为变化的积分 */ function addPoint($data,$point){ ... } /** * delPoint,根据 actions 方法返回的动作命名的函数 * 必有方法,data 参数为订单信息,point 参数为变化的积分 */ function delPoint($data,$point){ ... } /** * addCoupon,根据 actions 方法返回的动作命名的函数 * 必有方法,data 参数为订单信息,coupon 参数为优惠券信息 */ function addCoupon($data, $coupon){ ... } } actions 返回的数组,在网店后台工具箱-&网店机器人-&订单-&添加规则中,“执行动作”的下拉列表(见下图示),下拉列表的选择项就是返回数组的'label'标签名称。后面的输入框是根据返回数组的键 args 来判断,假如'type'类型是 number,则显示文本框,假如'type'类型是引用特殊模块,则根据特殊模块来显示内容。 3.1.5. 数据导入导出插件(dataio)文件型 &?php class io_txt{ var $name = 'txt-制表符分隔的文本文件'; //数据导入导出插件名称 /** * export_begin * 必有方法,keys 参数为导出文件类型的键名数组, * type 参数为导出文件类型,count 参数为导出数据数量 */ function export_begin($keys,$type,$count){ //文件下载方法,其中第一个参数为文件名 download($type.'-'.date('Ymd').'('.$count.').txt'); //以制表符为间隔来输出每一个键名 echo implode(&\t&,$keys).&\r\n&; flush(); //刷新输出缓冲 } /** * export_rows * 必有方法,rows 参数为需要导出所有行 */ function export_rows($rows){ foreach($rows as $row){ foreach($row as $k=&$v){ $row[$k] = str_replace(&\n&,'\n',$v); } //以制表符为间隔来输入每一行的每一列,并且最后换行 echo implode(&\t&,$row).&\r\n&; } flush(); } /** * export_finish * 必有方法,导出结束 */ function export_finish(){ } } ?&目前数据导入方法暂时不公布。3.1.6. 用户消息插件(messenger)目录型&?php class messenger_email{ var $name = '电子邮件'; //名称 var $iconclass=&sysiconBtn email&; //操作区图标 var $name_show = '发邮件'; //列表页操作区名称 var $version='$ver$'; //版本 var $updateUrl=''; //新版本检查地址 var $isHtml = //是否 html 消息 var $hasTitle = //是否有标题 var $maxtime = 300; //发送超时时间 ,单位:秒 var $maxbodylength =300; //最多字符 var $allowMultiTarget= //是否允许多目标 var $targetSplit = ','; //目标分隔符 var $dataname='email'; //数据库名 var $debug = /** * ready,准备发送时触发 * 可选方法,config 参数为 getOptions 取得的所有项的配置结果 */ function ready($config){ ... } /** * finish,结束发送时触发 * 可选方法,config 参数为 getOptions 取得的所有项的配置结果 */ function finish($config){ ... } /** * send,发送时调用 * 必有方法,to 参数为发送对象,subject 参数为消息主题, * body 参数为消息内容,config 参数为 getOptions 取得的所有项的配置结果 */ function send($to, $subject, $body, $config){ ... } /** * getOptions,取得配置信息 * 必有方法,返回配置信息的数组 */ function getOptions(){ ... } } ?&在网店后台,会员-&邮件短信设置-&电子邮件下的配置,就可以根据用户消息插件中 getOptions 定义的配置信息来配置发送方式、发送地址等。3.1.7. 单独页面布局插件(layout)目录型├─3-columns //三列 │ layout_3-columns.php //布局配置文件 │ preview.png //布局缩略图预览 │ layout.html //布局模板 │ ├─2-columns-left //两列,左为主 │ preview.png │ layout_2-columns-left.php │ layout.html │ ├─2-columns-right //两列,右为主 │ preview.png │ layout_2-columns-right.php │ layout.html │ └─1-column //单列 layout.html preview.png layout_1-column.phplayout.html 比如:在 2-columns-left 目录下的布局模板,布局:两列,左为主。&div style=&float:width:180 overflow:&& &{widgets}& &/div& &div style=&margin-left:190 overflow:&& &{widgets}& &/div&layout_2_columns_left.php 比如:在 2-columns-left 目录下的布局配置文件。&?php class layout_2_columns_left{ var $name='两列,左为主'; //布局插件名称 var $slotsNum = 2; //布局列数 } ?&在网店后台,页面管理-&站点栏目-&添加顶级栏目-&选择单独页面-&选择布局-&设置布局(如下图示) ,就可以根据自定义的单独页面布局插件,来选择布局。3.1.8. 地区数据插件(location)目录型&?php class local_difang{ var $name = '某地方'; //地区插件名称 var $desc = '地区描述'; //地区插件描述 var $maxdepth = 3; //地区最大深度为 3 层 /** * install * 必有方法,安装时调用,将 area.txt 文件内地区信息插入数据库表中。 */ function install(){ .... } }3.1.9. 网页挂件(widgets)3.1.9.1. 一步步做个 widgets 基础篇首先建立一个目录 plugins/widgets/helloword 这个就是新的挂件目录,系统的每个 widgets 都是一个目录 里面放两个文件: widgets.php:&?php $setting['author']='我'; //挂件作者 $setting['name']='Helloword'; //挂件名称 $setting['version']='0.0.1'; //挂件版本 $setting['catalog']='我的原创'; //挂件目录 $setting['description'] = '这是我自己的 helloword 板块'; //挂件描述 ?& default.html:&h1&HelloWorld&/h1&&br /&这时目录看起来这个样子:我们到后台可视化模板编辑里面添加板块。 保存,前台就能看到了添加一个输入框 下面我们来改进这个板块:在后台输入一串文字,在前台显示出来。 增加一个配置文件_config.html 这个文件名是定死的,只要存在这个文件,那么就会把这个文件内容放到后台的版块编辑里面 _config.html输入我的文字: &input type=&text& value=&&{$setting.string_1}&& name=&string_1& /&注意:这个输入框的 value 在这里设置的是&{$setting. string_1}& , 这样在版块编辑的时候,才会作为把你上次填的文字放在输入框里我们在这里做的每个 input/select 元 素,都会作为$setting 这个变量的一部分 编辑的时候就是这个样子: 下面把输入的字符串在前台显示出来:修改 default.html&h1&Hello:&{$setting.string_1}&&/h1&这时前台的样子:加入控制程序 再在这个目录下添加一个 widgets_helloword.php,这里的文件和 php 函数,要用 widget_ + 目录的名字(helloword)命名 widget_helloword.php&?php function widget_helloword(&$setting,&$system){ return '&b style=&color:red&&'.$setting['string_1'].'&/b&'; } ?&下面修改 default.html,让他输出通过 php 修改过的文字。只要把&{$setting.string_1}& 改成&{$data}&即可。 default.html &h1&Hello:&{$data}&&/h1&写到这里发现写错字了,helloword... 只好继续&你好单词&下去... 前台表现:3.1.9.2. 一步步做个 widgets 实战篇很多人做挂件的动机一般都是看到一个比较好效果或者是对官方提供的功能进行更深入的修改。比如看到了一个很好的效果,想把他用到自己的网店上,同时也可以在后台维护,下 面的一个效果挂件,就是出于这样的一个动机来制作的。 原始的效果:/demos/slider_class/ 感觉这个带有数字控制的滑动的效果还是不错,想把它改成的 ShopEx 的挂件,只要店主在后台设置了图片的 路径和这个图片上的链接就可以实现这个广告效果。 下面的图帮你来温习一下挂件的制作基础。 首先要想清楚,挂件里面有些什么东西是需要店主设置的: 1、图片的路径,这个当然需要店主自己改了,否则就不能自己添加广告了。 2、点击图片所链接的地址,这个也是必 须的。 3、每一个图片停留的时间,是让浏览者看 3 秒还是看 5 秒,这个也是需要店主自定义的 4、图片滑动的时间,就是从一张图片向另外一张图片切换的时候所需要的时间。 5、数字的颜色和背景,因为是带有数字的,所以就有当前的图片的数字和非当前的图片数字,这两个地方的颜色都需要用户可以设定的。 然后看看,上面看到的那个效果的 HTML 和 js 是不是支持上面所理想中设定,当然,这个地方需要你了解一些 js 了。看了一下这个效果整个的 js 和 HTML 结构,ok,没有问题, 都是可以支持的。把这些定下来以后,就可以去制作_config.html 了。 制作_config.htm 文件的时候,可以直接从一个类似的官方挂件中复制一个过来,这样有些现在的 html 和 js 都是可以使用。比如从 exchangeeffect 这个挂件中把_config 文件 复制过来。现在还是对这个文件动手了。在制作_config.htm 的时候,也不需要考虑太多,凡是需要店主定义的地方,统统写成 &{$setting.XXXXX}&的格式。
制作好_config.htm 以后,在后台插入这个挂件的时候,就可以看到大概的样子了。 然后接下来制作 default.html,这个就是这个挂件的主区域。按部就班的把 js 和 html 调整好,保证在静态页面的情况下(就是没有嵌入到 ShopEx 系统中) ,可以正常使用。
上面的步骤全部做好以后,就可以使用这个挂件了,简单的预览如下: 3.1.10. 商品插件(schema)目录型─custom │ schema.custom.php │ icon-48x48.png │ └─view init.html商品可以定义商品的发货函数可以实现点卡自动充值,机票的代理自动化等等甚至向工厂自动传送用户的下单信息。 schema.custom.php &?php class schema_custom{ var $name='自定义商品类型'; //商品插件名称 var $version='11689$'; //商品插件版本号 var $use_brand = //本类型商品是否有品牌 var $use_params = //本类型商品是否有参数表 var $use_props = //本类型商品是否有属性 var $use_minfo = //本类型商品是否有用户购买时的必填信息 /** * init,自定义商品类型初始化 * 可选方法 */ function init(&$post){ if(!isset($post['is_physical']))$post['is_physical'] = } } ?&3.1.11. 前台功能插件(shop)&?php class shop_helloworld{ var $name = 'hello'; function index(){ echo 'hello'; } }3.1.12. 后台功能插件(admin)&?php class admin_helloworld{ var $name = 'hello'; var $workground = 'tools'; function index(){ echo 'hello'; } }3.2. 软件功能包(app)即将出现在 485 正式版我们提供了一个很干净的机制让开发者扩展网店的功能,实现以下特性: ? 建立自己的数据库表 ? 创建自己的控制器 ? 在前后台增加栏目 ? 用自己的控制器替换系统默认的(自定义业务流程) ? 添加事件侦听器,使得系统事件时调用自己的代码 可以看到,这基本相当提供给大家一个简单的 php 框架了。下面说下技术细节。 每个程序包占一个目录。 我们推荐将所有的包都放置在 plugins/app 文件夹下。下面用个例子, 阐述下功能包的各个控制点。假设这个文件夹的名字为:demo, 包里面必须有 一个 app.demo.php。并且里面必须含有一个 app_demo 的类。该类需要继承 shopex_appdef 这个基类,例如: plugins/app/demo/app.demo.php&?php class app_demo extends shopex_appdef{ var var var var $ver = 0.8; $name='样例程序'; $website = ''; $author = '';//可选函数 //定义接管系统哪些流程,由自身的哪个类/方法去执行 //本例表示,启用后前台将把所有访问购物车的控制器请求重定向 //到本软件包内 democtl 对象的 cartidx 方法里。 function ctl_mapper(){ return array( 'shop:cart:index' =& 'demo_ctl:cartidx', ); } //可选函数 //侦听系统哪些事件 //此处可用关键字 any 表示所有事件 //本例表示: //侦听订单新建事件 -& 调用 event_handle 类的 order_new 方法执行 //侦听会员新建事件 -& 调用 event_handle 类的 member_create 方法执行 function listener(){ return array( 'trading/order:create' =& 'demo_event_handler:order_new', 'member/account:register' =& 'demo_event_handler:member_create', 'any'=&'demo_event_handler:any', ); } //可选函数, 返回需要建表的信息 //本例是建立两个表, 系统会自动加前缀 sdb_&ident& function dbtables(){ $tables['table_2'] = array ( 'columns' =& array ( 'controller' =& array ( 'type' =& 'varchar(100)', 'required' =& true, 'pkey' =& true, 'editable' =& false, ), 'plugin' =& array ( 'type' =&'varchar(100)', 'required' =& true, 'editable' =& false, ), ), ); $tables['table_1'] = array ( 'columns' =& array ( 'controller' =& array ( 'type' =& 'varchar(100)', 'required' =& true, 'pkey' =& true, 'editable' =& false, ), 'plugin' =& array ( 'type' =&'varchar(100)', 'required' =& true, 'editable' =& false, ), ), ); return $ } //我承认这是个非常邪恶的设计... //但你要承认它可以让你无所不能 function output_modifiers(){ return array( 'admin:goods/product:index'=&'demo_modifiers:product_edit' ); } //重载安装时的方法... //同样可重载的还有: // uninstall -& 卸载 // enable -& 程序启动 // disable -& 程序关闭 function install(){ //别忘了调用父类的 install return parent::install(); } }为了防止命名冲突,请使用自己包的名字作为类的前缀。 plugins/app/demo/demo_event_handler.php&?php class demo_event_handler{ //订单新建时本方法将被自动执行 //此处 event 被赋值为 order:new function order_new($event_type,$order_data){ ... } //会员新建时本方法将被自动执行 //此处 event 被赋值为 order:new function member_create($event_type,$member_data){ ... } //任何事件都将调用此函数 function any($event_type,$event_data){ ... } }建立一个类来重定义购物车页面 plugins/app/demo/demo_ctl.php&?php require('app_page.php'); class demo_ctl extends app_page{ function cartidx(){ ... //输出模板:软件包文件夹里的 cart.html $this-& //可以调用系统入口 $this-& //可以直接使用数据库 //载入包里的类... require(dirname(__FILE__).'/demo_my_model_layer.php'); $obj = new demo_my_model_ $this-&output('view/cart.html'); } }建立一个类来重定义购物车页面用关键字&{$_BASE_PATH_}&可以定位到插件文件夹的 url。 plugins/app/demo/view/cart.html&p& 例如输出&br /& plugins/app/demo/images/cart.png &/p& &img src=&&{$_BASE_PATH_}&/images/cart.png& /&过滤器,将商品列表页面的“新建商品”按钮上的文字换掉。 plugins/app/demo/demo_modifiers.php&?php class demo_modifiers{ function product_edit( &$content ){ return str_replace('添加商品','别看我是只羊!',$content); } }在第一次运行时会进行初始化。本例初始化时出现的信息是:欢迎来到样例程序初始化向导 即将初始化 样例程序 0.8 到你的网店系统中。 注意!本应用程序将: ? 向数据库里安装 2 个表: sdb_demo_table_2 , sdb_demo_table_1 。 ? 接管你的查看购物车流程。 ? 监督订单新建事件。 ? 监督会员注册事件。 ? 监督所有事件。 是否继续安装流程?3.3. 使用二次开发接口 定制可以根据客户的需求对网站进行相应功能的添加修改或者删除,同时定制也存在一定的弊端。ShopExV4.8 以前版本的定制是在原来的程序上修改的所以定制过的网站就不能 使用该版本后发布的相关补丁。 ShopExV4.8 版本采用 MVC 开发模式,二次开发解决了定制在原程序上进行修改导致程序不能升级的问题,使新的程序模块可以很好的融合到 ShopExV4.8 系统中同时也可以继承原有程序的所有功能。 本着不与原程序冲突的原则,需要新建一个目录去存放二次开发所用的程序,这就要求在 ShopExV4.8 的配置文件中定义一个存放二次开发程序目录的常量。同时为了使二次开发 程序能够兼容原程序的所有功能也要求要包含原来的控制器文件或模型层文件,通过类继承和函数重载的方式实现原有功能的保留、修改和新功能的开发,当然如果该功能完全与原 有功能没有联系则只需继承控制器文件或模型层文件的基类。 1. 配置 config.php 文件:2. define(‘CUSTOM_CORE_DIR’,’自定义文件路径’)自定义文件路径建议和 core 同级 3. 后台菜单新增规则(customSchema.php): 格式参照原有后台菜单文件的书写格式但数组名必须为$cusmenu 新增菜单项 此处格式参照 adminSchema.php 即可,数组名称注意应为$cusmenu 在已有菜单项中添加 根据菜单出现的位置添加不同的参数 如在“统计报表”下新增二级菜单“测试二次开发”$cusmenu['analytics']=array( 'items'=&array( array( 'type'=&'group', 'label'=&'测试二次开发', 'position'=&'after|begin|end|before', 'reference'=&'访问统计', 'items'=&array( array( 'type'=&'menu', 'label'=&'测试二次开发 1', 'link'=&'index.php?ctl=vip/vote&act=index' ), array( 'type'=&'menu','label'=&'测试二次开发 2', 'link'=&'index.php?ctl=vip/vote&act=index' ) ) ) ) );position 值及说明: o o o o after:在某个菜单项的后面,此时 reference 必须为一个同级已存在的 菜单项。如上述例子中为“访问统计”则“测试二次开发”出现在”访问 统计”的下面 before:同 I,只是位置在前 begin:在同级目录的最前面,refernce 可以为空 end:在同级目录的最后面,refernce 可以为空4. 在三级菜单中插入某菜单项同上述二级菜单的操作 5. 控制器文件: 控制器文件必须以 cct 命名 6. 继承原有控制器文件,前提是原控制器文件必须存在7. cct_原控制器名称 extends ctl_原控制名称{ 8. function 新增函数名(){ 9. 10. 11. 12. 13. 14.//新增功能函数 } function 原有函数名(){ //函数重载 } }15. 新建控制器后台控制器文件16. 17. 18. 19. 20. 21.或者cct_control extends adminPage{ function __construct(){ //自定义操作 } //自定义函数 }cct_control extends objectPage{ function __construct(){ //自定义操作 } //自定义函数 }前台控制器文件cct_control extends shopPage{ function __construct(){ //自定义操作 } //自定义函数 }22. 模型层文件: 模型层文件必须以 cmd 开头命名,继承原有模型层文件,前提是原模型层文件必须存在cmd_原模型层名称 extends mdl_模型层名称{ function 新增函数(){ //新增函数 } function 原函数名(){ //重载函数 } }新建模型层文件cmd_model extends shopObject{ function __construct(){ //自定义操作 } //自定义函数 ... }或cmd_model extends modlFactory{ function __construct(){ //自定义操作 } //自定义函数 ... }3.3.1. 案例 A: 更改友情链接页面显示个数前台友情链接页面默认每页显示的友情链接为 10 个,大多数店主会觉得这个数字太少导致页面太空,所以想修改此处的数字为 30 或者更多。要实现这个修改,首先设置好二次开 发目录。 然后在二次开发目录下新建目录。 shop/controller 然后在此目录下建立文件 cct.link.php 继承原始的 ctl_link 类,之后重载控制器函数。 内容为:&?php class cct_link extends ctl_link{ function showList($page=1){ $sitemapts=$this-&system-&loadModel('content/sitemap'); $title=$sitemapts-&getTitleByAction('link:showList'); $title=$title['title']?$title['title']:'友情链接'; $this-&path[]=array('title'=&$title); $this-&title = $ $pageLimit = 100; $oLink=$this-&system-&loadModel('content/frendlink'); $result=$oLink-&getList('*', '', ($page-1)*$pageLimit,$pageLimit,$linkCount); $this-&pagedata['pager'] = array( 'current'=&$page, 'total'=&ceil($linkCount/$pageLimit), 'link'=&$this-&system-&mkUrl('link', 'showList',array(($tmp = time()))), 'token'=&$tmp); if($page & $this-&pagedata['pager']['total']){ trigger_error('查询数为空',E_USER_NOTICE); } $this-&pagedata['data'] = $ $this-&output(); } }将其中第九行 $pageLimit = 100; 改为您要的数字就行了。3.4. 自定义核心流程页面模板相比大家都感觉 48 只能修改框架而感到束手束脚了吧很多东西只有修改 core/shop/view 下的 html 文件才可以实现,而这些都是核心的东西。模板又无法控制~~ 其实有办法的:可以在模板目录下 建一个 view 文件夹。 然后按照 core/shop/view 同样的路径,建立新的 html 文件。系统输出的时候就会优先调用模板里自定义的核心业务 html 部分了 例如:修改会员后台的样式需要修改 core/shop/view/member/main.html 才能实现。 现在自己做了一个模板叫 myth,模板目录在 themes/myth。就可以建立一个,把原来的 core/shop/view/member/main.html 文件复制themes/myth/view/member/main.html 到想要自定义的细节样式,通过修改新的 themes/myth/view/member/main.html 文件即可实现。现在,你可以随心所欲的控制样式了。注意! 这样的话,模板就不能跟随升级了,因为里面有自定义的核心业务所需的模板。 很可能你修改过的 member/main.html 里面的一些变量在新版本里已经失效。 于是,这需要你手动修改 member/main.html 文件来跟随系统升级。 因此我们建议,你可以自用,但尽量不要使用自定义的核心业务区域 html 去做通用模板。 否则,需要你亲自升级。当然,你也可以为这个服务提高模板价格....自定义导入导出介质,支付方式,配送方式,促销规则,促销页面模板等等扩展接口…4. 系统探秘 4.1. 系统结构以下文档均以最新的 shopex 4.8.5 为准。 程序为 mvc 3 层结构。模型-视图-控制器。 ? ? ?模型是前后台公用。完成业务逻辑,所有的数据库操作,文件等资源调用,都由此层实现。 控制器则是前后台独立。负责业务模型的调用,拼接,变量的转换等等。 视图层采用类似 smarty 的实现。在任何时候都有一个全局变量$system 指向唯一的一个内核类:core/kernel.php 结构图 公共类图 公共函数库位于/core/func_ext.php,它在内核加载时首先被加载,对全系统有效。其中包含若干 php5 函数的 php4 模拟版本: ? ? ? ? ? ? file_put_contents json_encode json_decode ftp_chmod array_diff_key http_build_query这是一个结构图这里是前台的控制器,视图文件这里是后台的控制器,视图文件这里是后台的 smarty 插件文件这里是前后台公用的 smarty 插件文件 我们的逻辑是这样的。 控制器负责所有的变量的转换,包括对外界的变量转换。像胶水一样粘合各个业务 model,并在其中的数据交互过程中做一些数据转换过程。最终将变量抛到模板层。模板层负责 编译成 html 输出,这里我们创建了大量的 smarty 插件来减少开发者的重复工作量。 model 层负责所有的资源操作,包括数据库和文件系统以及读取网络等等。 业务模型层下面是 schema,这些是对数据库表结构的最底层的描述。 我们将从底向上的介绍这些层次4.1.1. 数据库结构定义文件在 485 之前,我们使用 powerdesigner 来管理这些表结构,但是在一些项目的版本管理过程中,有时需要维护多个版本。powerdesigner 的储存文件为一个单一的巨大的 xml 格式 pdm 文件。这在进行版本的合并分支时几乎无法处理。而在 485 里,我们使用 php 去描述表结构有了以下几个优势: ? 数据库定义具有版本管理特性 o o o ? ? ? ? ? ? ? ? 各分支开发互不干扰 协同更改时,可以进行合并操作 针对单表的版本还原与操作日志容易做自动化的表结构对比 更快速的 getInsertSQL/getUpdateSQL: 不需要 select * from xxx where 0=1 插件可以有自己的表定义文件 为 model::getColumns 自动化做准备 按照用途来定义字段类型,不会出现同一种数据类型而字段定义不一致的情况 简单的外键实现,方便的统计表的依赖关系,使得外键字段定义完全一致 更好的 mysql 版本兼容:type = MyISAM DEFAULT CHARACTER SET 语法 很方便的实现 gbk/utf8 多版本现在这些数据库定义文件放置在 core/schemas 下面,每个表一个 php 文件, 样例:&?php $db['table_name'] = array( 'columns'=&array( 'col_1'=&array('type'=&'int', 'pkey'=&true,'comment'=&'id 字段'), //主键 'col_p1'=&array('type'=&'int', 'pkey'=&true,'comment'=&'主键 2'), //联合主键 'col_33'=&array('type'=&'mediumint unsigned'), //当然也支持通常的 type 'col_2'=&array('type'=&'email', 'comment'=&'id 字段'), //email = varchar(255) 'col_3'=&array('type'=&'money', 'notnull'=&true,'default'=&3), //money = decimal(20,3), 非空字段,默认为 3.000 'col_4'=&array('type'=&'html', 'comment'=&'id 字段'), //html = text 'col_4'=&array('type'=&'bool', 'comment'=&'id 字段'), //bool = enum('true','false') 'table2_c1'=&array('type'=&'table_2:c1', 'comment'=&'表 table_2 的 c1 字段'), //类型和 table_2 的 c1 字段相同, 当外键处理,自动加索引 ), 'index'=&array( '...',//再定义 ) 'engine'=&'heap'//可不填,默认为 myisam 'option'=&''//其他扩展语法 );好了,现在一切的表结构都可以被系统精确控制了。利用这个东西,我们实现了 485 里的数据表结构比较功能,并且以这个为基础建立了新的升级机制。并且在未来,这将是 app 体系的一个基石, 关于 app 体系,我将在后来的章节讲解,这将是一个神奇的东西。 4.1.2. 网店对象在 model 里面,有一些特别特别的类是基于 shopObject 这个类的。 shopObject 用来表示一些有共性和意义的对象,比如商品,订单,会员。有一些抽象的共用方法。 每个 shopObject 都有一个绑定的表,并且标明了哪些字段是主键。因此我们可以做一些批量的东西。后台的订单列表,商品列表,会员列表等等。我们给他取名为 finder。在此 向 osx 致以敬意。函数名参数返回值说明is_highlight($row) 行数据 bool 用来判断是否将该行高亮因此如果你想修改这些默认行为,比如在列上加些自定义的字段,而这个字段可能完全不是数据库里,而存在于其他某外部系统中。那么很简单,你只需要重载对应的方法即可。 ? ? 你可以去思考将这个重载放在哪一层。如果希望所有调用这个数据的地方都变化,那么就重载 model。 如果只是希望后台的列表增加一个列,就重载他的控制器即可shopObject 还有一个特性,就是支持事件广播。他有一个特殊的方法:shopObject::fireEvent($eventName) 用来广播事件。其他对象采用观察者模式 listen 到感兴趣的对象 上。 当订单新建时,系统会调用相应的$orderModel-&firevent('create')方法,这时所有关注 order-create 的函数就全都被纷纷调用,有的负责发邮件通知用户,有的负责记录的数据库, 有的可能是插件写的:将这些事件广播道某 esb 系统里。 这时一条网店系统的数字神经,当订单新建,或者会员登录的时候。我们可以通过外挂的脚本做一些触发事件。这也是 485 网店机器人的基础。4.1.3. 业务模型(model)模型是前后台公用。完成业务逻辑,所有的数据库操作,文件等资源调用,都由此层实现 模块调用方法: $systme-&loadModel(path/to/a/model); 载入过程如图所示:
4.2. 运行过程ShopEx 前后台调度都分别通过各自目录下一个名为 index.php 的入口文件进行, 入口文件接受控制器、 方法等的输入参数, 调度给对应的控制器方法执行并输出结果。 index.php 会调用 kernel。 Kernel 基础类提供模型对象加载,插件入口,错误处理,设置管理,输入输出,第三方类库加载等基础服务。 前后台及安装入口程序在初始化时,都会初始化一个对应的内核类,这个类在前台是 shopCore.php,后台时是 adminCore.php。这两个文件都是继承 core/kernel.php 文件。该 内核类首先会形成一个名为 system 的指向自身的全局对象,然后根据传入参数调用对应的控制器方法运行。控制器层与模型层都会产生对该全局 system 对象的调用来使用基础 服务。 并且控制器和模型层在自身被实例化之后都可以使用$this-&system 来引用内核对象。 也就是说,构造函数中只能通过$GLOBALS['system']来访问。 4.2.1. 前台流程对于前台来说,会有缓存的介入。 为方便 rewrite,采用形如文件名的形式做为请求句柄,请求句柄包含了控制器名,控制器方法,类型及传入参数信息请求句柄语法:CTL[-ARG…][-METHOD].&html|json|xml&其中 CTL 为控制器 . ARG 部分为传入参数组 , 可省略 . METHOD 为控制器方法 , 可省略 , 默认为 index 为方便更改请求句柄的编码方式 , 请求句柄的编码与解析采取读取 system.seo.parselink 中定义的外挂函数(见插件小节外挂函数部分)处理,默认函数为 actmapper: 前台控制器位/core/shop/controller 于前台的入口文件为 index.php,该页面初始化 shopCore,初始化时运行父类 kernel 的构造方法设定 system 的指向自身的全局对象,最后构 造函数调用 shopCore-&run(),流程如下:说明入口程序 /index.php,判断 config.php 是否存在,不存在则转至安装目录重新设定超级全局变量$_COOKIE 为$_COOKIE[COOKIE_PFIX]的值;COOKIE_PFIX 用以区分同 一目录下安装的不同 ShopEX 实例。对传入 URL 进行处理,返回数组$this-&requestarray( //cache 是否公用,用于用户登录或转换货币后界面 'cache'=&$cache, //请求句柄 XXXX.html 'query'=&$query?$query:'index.html', //链接基地址(带?m/) 'base_url'=&$url_prefix.($domain?$domain.'/':''), 'url_prefix'=&$url_prefix, //链接基地址 'domain'=&$domain?$domain.'/':'', // m/或空 'member'=&$memberInfo, //用户信息数组 'cur'=&$cur, //货币 'lang'=&$lang //语言 );注:在会员登录后,链接将变为 index.php?/m/XXXX.html 判断传回的 request['cache']:if($request['cache']=='public' && !(defined('WITHOUT_CACHE') && WITHOUT_CACHE )){ //对公共 cache 进行处理 }else($request['cache']=='private') //对私有 cache 进行处理 }else{ 直接调用动态程序(流程 5) } 输出缓存或重新生成和输出 调 用 请 求 句 柄 解 析 方 法 进 行 处 理 if 请 求 句 柄 = ?index.html? 返 回 array('controller'=&'index','method'=&'home','args'=&array(),'type'=&'html') else 读 取 system.seo.parselink 中定义的外挂函数(见插件小节外挂函数部分)解析处理: 默认函数为 actmapper-&parse(处理逻辑见下节)4.2.2. 后台流程后台入口文件为/shopadmin/index.php 文件后台的文件链接形如http://host/shopadmin/index.php?#ctl=&控制器&&act=&方法&[&p[0]...]后台控制器位/core/admin/controller 于后台的入口文件为/shopadmin/index.php,该页面初始化 adminCore,初始化时运行父类 kernel 的构造方法设定 system 的指向自身的全局对 象,最后构造函数调用 adminCore-&run(),流程如下: 4.3. 配置信息的存储网店的配置信息分为两种。 1. 安装数据:存放在 config/config.php 里 通常存放软件安装配置,即当系统无法正常运行时也可以通过 ftp 进行修改的参数。安装配置文件在系统安装时依据 config.sample.php 模板文件自动生成。 秘诀: 你也可 以通过修改这个文件来覆盖系统中的一些常量。config.sample.php 内容如下: &?php /** * 网店配置模板 * * 版本 $Id: config.sample.php -12-03 09:28:28Z flaboy $ * 配置参数讨论专贴 /bbs/thread-.html */// ** 数据库配置 ** // define('DB_USER', 'usernamehere'); # 数据库用户名 define('DB_PASSWORD', 'yourpasswordhere'); # 数据库密码 define('DB_NAME', 'putyourdbnamehere'); # 数据库名 # 数据库服务器 -- 99% 的情况下您不需要修改此参数 define('DB_HOST', 'localhost'); //define('DB_PCONNECT',1); #是否启用数据库持续连接? define ('STORE_KEY', ''); #密钥 define('DB_PREFIX', 'sdb_'); define ('LANG', ''); define ('WITHOUT_CACHE',false); #启用触发器日志: home/logs/trigger.php //define ('TRIGGER_LOG',true); //define ('DISABLE_TRIGGER',true); #禁用触发器 /* 以下为调优参数 */ define('DB_CHARSET', 'utf8'); define('DB_COLLATE', ''); define('DEBUG_JS',false); define('BASE_DIR', realpath(dirname(__FILE__).'/../')); define('CORE_DIR', BASE_DIR.'/core'); //安全模式启用后将禁用插件 define('SAFE_MODE',false); #您可以更改这个目录的位置来获得更高的安全性 define('HOME_DIR', BASE_DIR.'/home'); define('PLUGIN_DIR', BASE_DIR.'/plugins'); define('THEME_DIR', BASE_DIR.'/themes'); define('MEDIA_DIR', BASE_DIR.'/images'); define('PUBLIC_DIR', BASE_DIR.'/public'); #同一主机共享文件 define('CERT_DIR', BASE_DIR.'/cert'); define('DEFAULT_LOCAL','mainland'); define('SECACHE_SIZE','15M'); #缓存大小,最大不能超过 1G //define('TEMPLATE_MODE','database'); define(&MAIL_LOG&,false); define('DEFAULT_INDEX',''); define('SERVER_TIMEZONE',8); #服务器时区 //define('APP_ROOT_PHP','index.php'); #iis 5 @ini_set('memory_limit','32M'); define('WITHOUT_GZIP',false); #前台禁 ip //define('BLACKLIST','10.0.0.0/24 192.168.0.1/24'); #数据库集群. //define('DB_SLAVE_NAME',DB_NAME); //define('DB_SLAVE_USER',DB_USER); //define('DB_SLAVE_PASSWORD',DB_PASSWORD); //define('DB_SLAVE_HOST',DB_HOST); #支持泛解的时候才可以用这个, 仅支持 fs_storager /* * define('HOST_MIRRORS', * ', * , * '); */ #使用 ftp 存放图片文件 //define('WITH_STORAGER','ftp_storager'); #确定服务器支持 htaccess 文件时,可以打开下面两个参数获得加速。 //define ('GZIP_CSS',true); //define ('GZIP_JS',true); #可以选择缓存方式 apc 或者 memcached //define('CACHE_METHOD','cacheApc'); //====================================== //define('CACHE_METHOD','memcached'); //====================================== #使用单个文件存放,稳定,但无法控制文件大小 //define('CACHE_METHOD','cachedir');/* 日志 */ //define('LOG_LEVEL',E_ERROR); #按日期分目录,每个 ip 一个日志文件。扩展名是 php 防止下载。 //define('LOG_FILE',HOME_DIR.'/logs/{date}/{ip}.php'); #log 文件头部放上 exit()保证无法下载。 //define('LOG_HEAD_TEXT','&'.'?php exit()?'.'&'); //define('LOG_FORMAT',&{gmt}\t{request}\t{code}&); //====================================== //define('WITH_MEMCACHE',true); //define('MEMCACHED_HOST','192.168.0.230'); //define('MEMCACHED_PORT','11211'); //====================================== #禁止运行安装 //define('DISABLE_SYS_CALL',1); #使用数据库存放改动过的模板 //define('THEME_STORAGE','db');运行时的默认值存放在 core/include/defined.php 中。 2. 业务数据:存放在系统的配置数据库里的 存放在数据库中,必须在系统可以正常运行时才能修改,大多是网店经营性质的配置。这个机制有点像 windows 的注册表,或者 firefox 地址栏里输入: about:config 看到 的东西。 ShopEx 通过参数表的方式存放业务环节中的常用 参数。参数表采用文件与数据库双重定义方式。默认值位于文件 /core/include/setting.php ,实际设定值通过 sdb_settings 表进行存储。对于每一个参数,存在一个存取用的 key,对应它的有类型、值、说明。类型分为: define('SET_T_STR',0); //text define('SET_T_INT',1); //number define('SET_T_ENUM',2); //select define('SET_T_BOOL',3); //bool define('SET_T_TXT',4); //textarea define('SET_T_FILE',5); //file系统方法 $system-&getConf() 负责取值,$system-&setConf()保存值。系统在取值时,首先在数据库中查找对应的 key,如果未找到,则在默认值文件中进行查找。4.4. 模板系统smarty 风格的模板引擎。语法参照 smarty 的文档:http://www.smarty.net/manual/en/ 前后台的公用的模板插件路径为:core/include/smartyplugins后台的专有模板插件路径为:core/admin/smartyplugin特别之处: 在 4.8.5 之后,我们重新编写了模板编译引擎。沿用一直以来的 smarty 语法。我们做了以下增强: ? 重写的正则表达式,编译时匹配效率更高 ? ? ? ? ? ? ? ?更严谨的字符串变量里的变量,避免语法模糊造成错误。 支持变量预绑定,我们把在很长时间内不变的变量,可以通过语法通知模板系统。使其直接输出目标值,而不是 php 代码。 if 等条件语句,会自动判断条件,如果其中的条件不包括可变变量(非预绑定的变量) ,则预先做条件判断。这几乎减少了一倍的目标代码量。 支持编译型的 modifier 插件 重新设计的简单实用的 errorhandler include 语法支持文件名后面加井号&#&,来为同一模板生成不同的编译缓存 大量目标 php 代码的优化 更改缓存文件名为 md5hash 格式,使其在将来有希望归并到 secache 体系。这个优化的原则就是把更多的插件改为编译时插件,然后通过精心设计的缓存控制系统去自动更新模板缓存. 这是一个完全重写的引擎。我们把这个类 smarty 的模板引擎取名为 tramsy。实际检测,同样的代码,我们的 tramsy 生成的代码运行效率提高了 50%以上。而如果用变量预绑 定的方式传入变量,则可以使目标代码减少 50%,运行效率提高 80%。 我们会在将来的版本中更多的利用变量预绑定机制来提高性能。4.5. 缓存机制缓存系统的设计,直接决定了系统的运行效能。系统的无数 bug,也可能由缓存而生。我们在此一起抽丝剥茧的看一下 shopex 的缓存设计方案。 shopex 有 3 层缓存结构,按顺序触发:层次 1 2 3缓存名称 基于 http 协议的浏览器缓存 前台全页缓存 模板缓存存放位置 用户浏览器本地 home/cache/cachedata.php home/cache/front_tmpl4.5.1. 基于 http 协议的浏览器缓存 浏览器都很聪明,他们懒的把同样的数据从网上下载两次。 如果用户访问过这个网站,那么我们会在系统的 header 头里放一个 Etag 标签。这个 Etag 数据是和页面的内容相关的,如果页面内容变了,Etag 也会不同。 第一次访问一个 shopex 页面,服务器的返回情况, 使用抓包工具可以看到 http 头如下所示。HTTP/1.1 200 OK Date: Tue, 24 Nov :27 GMT Server: Apache/2.0.59 (Win32) DAV/2 SVN/1.4.0 PHP/5.2.3 X-Powered-By: PHP/5.2.3 Cache-Control: private Expires: Mon, 26 Jul :00 GMT Content-Language: utf-8, zh-CN Etag: 4be41fcf3ebdaf4d3226其中的 Expires 设置为 1997 年是为了让浏览器每次都来判断 etag 是否过期,因为我们是电子商务站点,一些促销规则,商品上下架对时间比较敏感。 最后一行就是 Etag 数据:4be41fcf3ebdaf4d3226,当用户第二次访问这个页面的时候(访问,或者按 F5 刷新),浏览器会把 Etag 里的数据放在请求的 http 头中:GET /shop/current/src/ HTTP/1.1 Host: localhost If-None-Match: 4be41fcf3ebdaf4d3226 ...最后一行:浏览器会把上次的 etag 值放在 If-None-Match 里面。如果网店程序端检测到: 1. 存在这个页面的全页缓存 2. 该全页缓存的页面数据未过期 3. 全页缓存的 Etag 值和浏览器传过来的 If-None-Match 得相同 则发送给浏览器一个 304 的头信息,浏览器就将自己本地缓存的页面数据直接显示出来,避免了网络传输。HTTP/1.1 304 Not Modified Date: Tue, 24 Nov :36 GMT Server: Apache/2.0.59 (Win32) DAV/2 SVN/1.4.0 PHP/5.2.3 Connection: close Etag: 4be41fcf3ebdaf4d3226 Expires: Mon, 26 Jul :00 GMT Cache-Control: private此时,网络上传输的数据只有以上两次,并没有实际的内容传输,所以响应会非常快。 我们看一下详细过程。 ? ? ?一些比较高级的爬虫,比如 google,baidu 的,也会响应 etag 值,因此他们会主动的提交 if-None-Match。从而减少了传输量,也提高了被搜索引擎索引的概率。 推荐一个很不错 http sniffer: fiddler2&/& 如果你怀疑这个层次出问题了,ctrl+f5 可以强制忽略 etag,强迫重新获取最新的数据。 ? ?在 shopex 后台也应用了这个基于 etag 的缓存机制 这个一整套的 http 缓存机制是写在 RFC2616 文档中,感兴趣可以去查阅: http://tools.ietf.org/html/rfc26164.5.2. 前台全页缓存-控制器现在聚焦到上图中&生成页面内容...&这个环节中,此时系统并不是为每次生成页面内容的请求都重新运行一次,而是将页面的结果整体缓存下来,如果该页面所包含的数据都没有 更新,则是直接输出被缓存下来的内容。 这里比较复杂的是缓存的自动更新,下面来解释这个过程。 shopex 在数据库的操作底层设置了一个触发动作,当有任何表的更新,插入,删除操作时,将当时的时间和被操作的表明记录在一个特殊的表里: sdb_cachemgr。例如某时刻该表 的数据如下:表名 sdb_goods最后时间
16:20:26sdb_goods_cat
05:25:21 sdb_setting
19:40:13 sdb_member
08:36:23 sdb_order ...
20:46:42 ... sdb_payments
05:20:27实际上,真实系统里表的时间都是 unix 时间戳格式,那个数字的意思是
00:00:00 之后的秒数。在这里,为了方便大家理解,我们用实际时间表示。 在处理前台请求时,数据库底层会记录在这个过程中用到的数据表,包括页面挂件,流程插件,自动机器人,模块,以及各种子流程。同时会记录用到的表的最后修改时间,存到最 终生成的缓存条目头部。
假设过了 5 分钟, 又有人访问同样的网址, 系统发现存在针对这个 url 的缓存。 此时会读出这个缓存条目用到的表名列表: sdb_goods, sdb_goods_cat, sdb_setting 并到 sdb_cachemgr 中检查这些表当前的状态,如果发现有以上表里有任何一个在上次缓存保存之后被修改过了,则宣布该缓存作废,重新生成页面。这个过程是在 core/include/cachemgr 这个类管理 的。4.5.3. 前台全页缓存-存储器cachemgr 决定了哪些内容被缓存,缓存多久,如何被更新,怎样判别缓存过期。缓存存储器仅仅是负责缓存如何存放,如何读取。当缓存过多时如何被自动删除,删除哪一些。shopex 系统默认的缓存存储器是 secache。可以被替换为 apc 或者 memcache。secache 的特点如下: ? ? ? ? 使用 lru 算法自动清理过期内容 可以安全用于多进程并发 最大支持 1G 缓存文件,性能不受文件大小影响 使用 hash 定位,读取迅速secache 已经被我们开源: /p/secache/ 。版权采用的是最开放的 MIT Licence,大家可以随意的用在自己的系统里。用法样例require('../secache/secache.php'); $cache = $cache-&workat('cachedata'); $key = md5('test'); //必须自己做 hash,前 4 位是 16 进制 0-f,最长 32 位。 $value = '值数据'; //必须是字符串 $cache-&store($key,$value); if($cache-&fetch($key,$return)){ echo '&li&'.$key.'=&'.$return.'&/li&'; }else{ echo '&li&Data get failed! &b&'.$key.'&/b&&/li&'; }基于性能考虑,几点约束: ? ? 键需要自己做 hash 处理,最长 32 位. 值必须是字符串。如果要存对象,请自己 serialize下面详细说明 secache 的实现原理 secache 是一个采用拉链法的 hash 结构。整个文件分成 2 个主要部分。 1. 结构信息区 1. 保留空间 20 字节,放置一个&?php exit()?&防止文件被下载 2. 保留空间 20 字节,放置文件的版本信息,最大容量 3. 20 字节保留区域 4. 结构信息 16 种 slab 结构,每个需要 24 字节,占用空间:24*16=384 字节 5. 索引信息区 1. 索引计数器数据 40-44 2. 数据最大空间指针 44-48 3. 空闲链表入口地址 48-52 4. hash 索引入口地址 (16^4)*4 = 256k 2. 数据区(混杂) 1. 索引链表 2. 数据链表 整个结构如图所示 系统将要存储的数据最多可分为 16 中大小,然后分别创建数据空间。避免一条数据被拆分到多个数据块中的复杂度。我们一共预设了 13 组 slab 结构,预设的数据大小和预分配 的条目为:大小 条数 占用空间 512 3k 8k 20k 30k 50k 80k 96k 10 10 10 4 2 2 2 2 5k 30k 80k 80k 60k 100k 160k 192k 128k 224k 256k 512k 1M2 2 2 1 1256k 448k 512k 512k 1M因此 secache 要求数据空间最小为 10M。当超过这个值时,secache 会根据存放数据的频率动态增加各个 slab 的数据块数量,直到增长到配置好的最大数据量为止。当增长到极 限时,各 slab 的数据块分布将不再变动。如果想重建结构,需要删除缓存文件,重新生成。当无法申请到新的空间之后,将采用 lru 的策略删除相对不活跃的缓存条目,为新的缓 存请求腾出数据空间。 每个 slab 结构占用 24 个字节,组成为:类型大小 空闲指针 lru 头部指针 lru 尾部指针 缓存命中 未命中 4bytes 4bytes 4bytes 4bytes占用空间 4bytes 4bytes再看一下 hash 索引表的结构。所有进入 secache 的数据,key 的前 4 位必须是 16 进制数据,即 0000-ffff, 共 65536 种前缀, 每个前缀的索引占用 4 字节的入口, 所以索引入 口区占用空间为 k 空间。 可以看到,secache 的地址数据都是 4 字节,即最大支持 256^4=4G 的寻址空间,但是由于 PHP 在 32 位系统下的大数上限约为二十亿。所以保险起见,我们强制 secache 最 大仅支持 1G 空间。 数据区的数据有两种,一种是实际数据,一种是索引节点数据。实际数据空间占用情况依照 slab 不同而不同,索引节点的长度是定长:56Bytes。 索引节点结构:类型下个节点 上个节点 数据入口指针 实际长度 lru 右节点 lru 左节点 4bytes 4bytes 4bytes键名占用空间 4bytes 4bytes4bytes 32bytes4.5.4. 模板缓存 模板缓存比较简单,就是 smarty 的原则,每个 html 文件会被编译成一个 php 文件,每次执行该 php 文件之前去判断原始文件的最后修改时间。5. shopex 对外数据接口外部系统和 shopex 系统的交互主要有两个应用场景: ? 一种是外部系统需要调用 shopex,比如通知 shopex 创建订单,向 shopex 里面增加一个商品。更新一下库存量,修改某订单状态等等。(图中实线部分) ? 另一种是外部系统需要被 shopex 调用,例如当用人下订单时,需要通知财务系统有应收款项。 某些商品库存不足时,需要 shopex 对外发出警告。当有人通过网店注册 时,需要同步到 crm 系统等等(图中虚线部分)。以消息体系为根本,每一个 shopex 内发生的事件,均对外发出事件广播。关心该消息的外部系统,接到消息后后,可以通过 API 去获取详细的数据。 获取数据的方法有两种: ? 采用预设的 api 去获取 ? 利用 dav 接口获取,数据的结构是标准数据格式 (推荐使用) 这种做法也被称为观察者模式。并且我们要秉着&小消息,大运算&的原则。就是广播出的事件消息本身,数据量会尽可能的小。以便于在各种载体上广播,详细的变动数据,状态 结果。各系统要通过统一的接口去获取。 shopex 内部是通过消息体系驱动的。 具体在代码实现上, 就是 shopObject 这个类,他的所有子类通过 fireEvent 方法产生事件。 fireEvent 会调用 model:system/trigger 来将事件广播出去,并调用注册在这个事件上的系统内行为。6. 附录 6.1. setting条目 coupon.mc.use_times security.guest.enabled site.version site.dateFormat site.timeFormat site.coupon_order_limit site.decimal_digit site.decimal_type site.delivery_time site.show_mark_price site.login_valide site.login_type site.register_valide site.buy.target site.market_price site.market_rate site.save_price site.retail_member_price_display site.wholesale_member_price_display site.meta_desc site.meta_key_words site.order_storage 用途 优惠券可用次数 是否支持非会员购物 version 的最后修改时间 商店日期格式 商店日期时间格式 每张订单可用优惠券数量 订单金额取整位数 订单金额取整方式 默认备货时间 前台是否显示市场价 会员登录需输入验证码 顾客登录方式 会员注册需输入验证码 顾客点击商品购买按钮后 商品页是否显示市场价 请输入比例值或增额值 商品页是否显示节省金额 零售会员价显示设定 批发会员价显示设定 META_DESCRIPTION META_KEYWORDS 库存扣除方式 备注 - site.offline_pay site.shopex_certify site.tax_ratio site.trigger_tax site.copyright site.logo site.certtext site.cert site.thumbnail_pic_height site.thumbnail_pic_width site.homepage_title site.homepage_meta_key_words site.homepage_meta_desc site.goods_title site.goods_meta_key_words site.goods_meta_desc site.list_title site.list_meta_key_words site.list_meta_desc site.brand_index_title site.brand_index_meta_key_words site.brand_index_meta_desc site.brand_list_title site.brand_list_meta_key_words site.brand_list_meta_desc site.article_list_title支持线下支付方式 ShopEx Store 认证显示 税率 是否设置含税价格 版权信息 商店 Logo 备案号 备案证书 缩略图高度 缩略图宽度 TITLE(首页标题) META_KEYWORDS META_DESCRIPTION TITLE(首页标题) META_KEYWORDS META_DESCRIPTION TITLE(首页标题) META_KEYWORDS META_DESCRIPTION TITLE(首页标题) META_KEYWORDS META_DESCRIPTION TITLE(首页标题) META_KEYWORDS META_DESCRIPTION TITLE(首页标题)- site.article_list_meta_key_words site.article_list_meta_desc site.article_title site.article_meta_key_words site.article_meta_desc system.admin_verycode store.pany_name store.contact store.email store.mobile_phone store.shop_url store.telephone store.zip_code system.money.operation.decimals system.money.decimals system.money.operation.carryset system.category.showgoods system.product.alert.num system.shopname system.seo.emuStatic system.seo.noindex_catalog system.ui.webslice system.timezone.default site.index_title site.title_formatMETA_KEYWORDS META_DESCRIPTION TITLE(首页标题) META_KEYWORDS META_DESCRIPTION 管理员后台登陆启用验证码 联系地址 网站所有人 联系人 电子邮件 手机 商店网址 固定电话 邮政编码 前台价格精确到 订单金额显示位数 价格进位方式 商品分类列表页显示设置 商品库存报警数量 商店名称 商店页面启用伪静态 URL 通知搜索引擎不索引目录页 支持 ie8 的 webslice 特性 用户默认时区 TITLE(首页标题) 网站标题格式- site.stripHtml site.url.base site.url.themeres site.url.widgetsres goods.rate_nums gallery.default_view system.fast_delivery_as_progress system.auto_delivery system.auto_delivery_physical system.auto_use_advance search.show.range order.flow.payed order.flow.consign order.flow.refund order.flow.reship certificate.id certificate.token certificate.str certificate.formal certificate.kft.cid certificate.kft.style certificate.kft.action certificate.kft.enable certificate.channel.url certificate.channel.name certificate.channel.status是否压缩 html 主站访问地址 模板资源访问地址 版块资源访问地址 相关商品最大数量 商品列表默认展示方式 后台手工发货为&已发货& 用户到款则自动发货 用户到款自动发货时,实体商品如何处理(auto:发货为 ready,no:不发货,yes:发货为 progress) 自动使用预存款 搜索是否显示价格区间 订单付款流程 订单发货流程 订单退款流程 订单退货流程 ShopEx 证书编号 ShopEx 证书密钥 ShopEx 证书身份说明 ShopEx 证书身份 客服通公司 id 客服通风格号 客服通动作 客服通开关 渠道 url 渠道商名 渠道状态- certificate.channel.service certificate.distribute messenger.sms.config shopex.wss.username shopex.wss.password shopex.wss.enable shopex.wss.show shopex.wss.js system.area_depth comment.index.listnum comment.list.listnum comment.switch.ask comment.switch.discuss comment.switch.buy comment.display.ask comment.display.discuss comment.display.buy comment.power.ask comment.power.discuss comment.power.buy comment.null_notice.ask comment.null_notice.discuss comment.null_notice.buy comment.submit_display_notice.ask comment.submit_hidden_notice.ask comment.submit_display_notice.discuss渠道服务类型 是否开通分销模块 短信 sms 签名 合作统计用户名 合作统计密码 合作统计开关 合作统计前台开关 合作统计 js 地区级数 商品首页显示评论条数 评论列表页显示评论条数 商品询问开关 商品评论开关 商品经验评论开关 商品评论(询问),回复显示 商品评论(评论),回复显示 商品评论(经验),回复显示 商品评论(询问),发布权限 商品评论(评论),发布权限 商品评论(经验),发布权限 没有咨询记录,提示文字 商品评论(经验),发布权限 商品评论(经验),发布权限 没有咨询记录,提示文字 商品评论(经验),发布权限 商品评论(经验),发布权限- comment.submit_hidden_notice.discuss comment.submit_display_notice.buy comment.submit_hidden_notice.buy selllog.display.switch selllog.display.limit selllog.display.listnum goodsbn.display.switch storeplace.display.switch gallery.display.listnum gallery.display.grid.colnum plugin.passport.config.current_use system.message.open site.refer_timeout site.is_open_return_product spec.image.height spec.image.width spec.default.pic system.editortype system.upload.limit system.store.time system.guide goodsprop.display.switch store.site_owner store.mobile store.qq store.wangwang没有咨询记录,提示文字 商品评论(经验),发布权限 商品评论(经验),发布权限 是否显示销售记录 低于多少条不显示销售记录 显示条数 是否启用商品编号 是否使用商品货位 搜索列表显示条数 搜索橱窗页显示行数 当前使用的 passport 商店留言发布 推荐链接过期时间(天) 是否开启退货功能 规格图片宽度 规格图片高度 规格默认图片 HTML 编辑器设置 前台图片大小限定 库存预占触发时间 向导设置 是否启用商品属性链接 商店所有人 手机 qq 旺旺- 6.2. 数据库手册数据表:sdb_sfiles字段名称数据类型主键 必填 含义 说明 √ √ √ √ √ -file_id varchar(32) file_name varchar(32) usedby varchar(32) file_type varchar(32) file_size int(9) cdate time misc varchar(255)数据表:sdb_status字段名称数据类型主键 必填 含义 说明 √ √ √ √ √ √ -status_key varchar(20) date_affect date status_value varchar(100) last_update int unsigned缓存对象管理表:sdb_cachemgr字段名称数据类型主键 必填 含义 √ √ √ -说明 缓存名称 最后更新时间cname varchar(30) modified int unsigned 商店配送方式表:sdb_dly_type ? 结构说明: Array ( [0] =& 关闭 [1] =& 启用 )字段名称数据类型主键 必填 √ √ √ √ √ √ √ -含义 配送 ID 配送方式 物流保价 排序 货到付款 状态说明 -dt_id number dt_name varchar(50) dt_config longtext dt_expressions longtext detail longtext price longtext type intbool gateway number protect intbool protect_rate float(6,3) ordernum smallint(4) has_cod intbool minprice float(10,2) disabled bool corp_id time dt_status Array站点结构:sdb_sitemaps字段名称数据类型主键 必填 含义 说明 node_id number p_node_id number node_type varchar(30) depth tinyint unsigned path varchar(200) title varchar(100) action varchar(100) manual intbool item_id number p_order number hidden bool child_count mediumint(4)数据表:sdb_orders ? 结构说明:√ -√ √ √ √ √ √ √ √ ---Array ( [active] =& 活动订单 [dead] =& 死单 [finish] =& 已完成 ) Array ( [0] =& 未支付 [1] =& 已支付 [2] =& 处理中 [3] =& 部分付款 [4] =& 部 分退款 [5] =& 全额退款 ) Array ( [0] =& 未发货 [1] =& 已发货 [2] =& 部分发货 [3] =& 部分退货 [4] =& 已退货 ) Array ( [null] =& 无反馈 [payed] =& 已支付 [shipped] =& 已到收货 ) Array ( [true] =& [false] =& )字段名称 order_id member_id confirm status pay_status数据类型 bigint unsigned object:member/member tinybool Array Array主键 必填 √ √ √ √ √含义 订单号 会员用户名 确认状态 订单状态 付款状态说明 - ship_status user_status is_delivery shipping_id shipping shipping_area payment weight tostr itemnum acttime createtime refer_id refer_url ip ship_name ship_area ship_addr ship_zip ship_tel ship_email ship_time ship_mobile cost_item is_tax cost_taxArray Array tinybool smallint(4) unsigned varchar(100) varchar(50) int money longtext number time time varchar(50) varchar(200) varchar(15) varchar(50) region varchar(100) varchar(20) varchar(30) varchar(150) varchar(50) varchar(50) money bool money-√ √ √ √ √ √发货状态 用户反馈 配送方式 支付方式 更新时间 下单时间 推广来源 ID 推广来源 URL 收货人 收货地区 收货地址 收货人电话 收货人手机 -- tax_company cost_freight is_protect cost_protect cost_payment currency cur_rate score_u score_g score_e advance discount use_pmt total_amount final_amount pmt_amount payed markstar memo print_status mark_text disabled last_change_time use_registerinfo mark_type extendvarchar(255) money bool money money varchar(8) decimal(10,4) money money money money money varchar(30) money money money money tinybool longtext tinyint unsigned longtext bool int(11) bool varchar(2) varchar(255)-√ √ √ √ √ √ √ √ √ √ √ √ -配送费用 订单总额 打印 订单备注 订单备注图标 -- is_has_remote_pdtsArray-√--存放发给用户的款项记录:sdb_refunds ? 结构说明: Array ( [online] =& 在线支付 [offline] =& 线下支付 [deposit] =& 预存款支付 [recharge] =& 预存款充值 ) Array ( [ready] =& 准备中 [progress] =& 正在退款 [sent] =& 款项已退 [received] =& 用户收到退款 [cancel] =& 已取消 )字段名称数据类型主键 必填 √ √ √ √ √ √ -含义 退款单号 订单号 会员用户名 退款帐号 退款银行 退款人 货币 金额 支付类型 支付方式 单据创建时间 退款时间 状态 -说明 -refund_id bigint unsigned order_id object:trading/order member_id object:member/member account varchar(50) bank varchar(50) pay_account varchar(250) currency object:system/cur money money pay_type Array payment number paymethod varchar(100) ip varchar(20) t_ready time t_sent time t_received int unsigned status Array memo longtext title varchar(255) send_op_id object:admin/operator disabled bool数据表:sdb_triggers ? 结构说明:-√ √操作员 --Array ( [true] =& 启用 [false] =& 停用 )字段名称数据类型主键 必填 √ √ √ √ √ √ √ √含义 网店机器人 id 条件 动作 事件 备注 状态 -说明 -trigger_id int filter_str varchar(255) action_str varchar(255) trigger_event varchar(100) trigger_memo varchar(100) trigger_define text trigger_order tinyint active Array disabled bool商店会员表:sdb_members ? 结构说明:Array ( [0] =& 女 [1] =& 男 )字段名称数据类型主键 必填含义说明 member_id number member_lv_id object:member/level uname varchar(50) name varchar(50) lastname varchar(50) firstname varchar(50) password varchar(32) area region mobi

我要回帖

更多关于 如何清除浏览器缓存 的文章

 

随机推荐