刚接触Ecmall的二次开发不久,接到一个任务。很常见的任务,主要是对数据库进行一些操作,其中查询的方法我写成这样:
01 |
function get_order_data( $goods_id ) |
03 |
include_once ( "gonndb/nmdb.php" ); |
04 |
include_once ( "gonndb/dbinfo.php" ); |
06 |
$connector = new nmdb( $host , $username , $password ); |
07 |
$connector -> select_db( $database ); |
09 |
$sql = "select a.buyer_name, a.add_time, a.status, b.phone_tel, b.phone_mob, c.price, c.quantity |
10 |
from shop_order a, shop_order_extm b, shop_order_goods c |
11 |
where a.order_id = b.order_id and b.order_id = c.order_id |
12 |
and c.goods_id = '".$goods_id."' |
13 |
order by a.add_time desc |
16 |
$result = $connector -> query( $sql ); |
19 |
while ( $myrow = $connector -> fetch_array( $result )) |
发现第一次查询的数据是对的,然后经过模板解析后的数据怎么都不正确。后来发现,Ecmall有这么一个机制。先是经过app进行数据库操作,操作完毕后会在 temp/compileed/ 下留下模板缓存,而且第一次数据库查询后会产生数据库缓存。这压根就说明,二次开发,最好不要用自己的数据库函数,用Ecmall自带的比较好。上面的方法改成:
01 |
function get_order_data( $goods_id ) |
05 |
$sql = "select a.buyer_name, a.add_time, a.status, b.phone_tel, b.phone_mob, c.price, c.quantity |
06 |
from shop_order a, shop_order_extm b, shop_order_goods c |
07 |
where a.order_id = b.order_id and b.order_id = c.order_id |
08 |
and c.goods_id = '".$goods_id."' |
09 |
order by a.add_time desc |
12 |
$result = $db -> query( $sql ); |
15 |
while ( $myrow = $db -> fetch_array( $result )) |
这个函数只是使用了Ecmall自带的数据库函数,还是没有产生数据库缓存。看一下别人写的,如何才能产生数据库缓存呢?
下面是一个公告挂件的程序:
06 |
* @param string $ad_image_url 广告图片地址 |
07 |
* @param string $ad_link_url 广告链接地址 |
10 |
class NotWidget extends BaseWidget |
19 |
$cache_server =& cache_server(); |
21 |
$key = $this ->_get_cache_id(); |
23 |
$data = $cache_server ->get( $key ); |
24 |
$data1 = $cache_server ->get( $key ); |
27 |
$acategory_mod =& m( 'acategory' ); |
28 |
$article_mod =& m( 'article' ); |
29 |
$data = $article_mod ->find( array ( |
30 |
'conditions' => 'cate_id=' . $acategory_mod ->get_ACC(ACC_NOTICE) . ' AND if_show = 1' , |
31 |
'order' => 'sort_order ASC, add_time DESC' , |
32 |
'fields' => 'article_id, title, add_time' , |
33 |
'limit' => $this ->_num, |
35 |
$cache_server ->set( $key , $data , $this ->_ttl); |
39 |
$acategory_mod1 =& m( 'acategory' ); |
40 |
$article_mod1 =& m( 'article' ); |
41 |
$data1 = $article_mod1 ->find( array ( |
42 |
'conditions' => 'cate_id=' . $acategory_mod1 ->get_ACC(ACC_HELP) . ' AND if_show = 1' , |
43 |
'order' => 'sort_order ASC, add_time DESC' , |
44 |
'fields' => 'article_id, title, add_time' , |
45 |
'limit' => $this ->_num, |
47 |
$cache_server ->set( $key , $data1 , $this ->_ttl); |
看了程序,我发现ECMALL的文章调用是这样的。定义一个data,一堆调用最后通过 ACC_NOTICE 来确定调用的分类的。最后通过
来对应一下。
谈谈写入数据查询缓存的步骤:
2 |
$cache_server =& cache_server(); |
4 |
$key = $this ->_get_cache_id(); |
6 |
$key = 'page_of_goods_' . $id ; |
8 |
$cache_server ->set( $key , $data , 1800); |
如果是缓存模板文件的话,那就算不使用内存来缓存从数据库读取的数据也没关系,因为最后会把模板文件连同数据一起缓存进一个文件,那后面读取时就只读取这个文件而不用再去缓存数据库,但与静态化有点不同,这个文件里面还有一点php信息,并不能用来直接输出,模板引擎会在去掉这点php信息后输出。
在使用ecmall2时也觉得有时反应不过来,相比来讲ecshop还快,经过观察,其实ecshop在display时是加了一个id的,就是用来缓存这次输出的。而我们现在要做的就是在ecmall2里面实现缓存模板输出,通俗点讲就是在$this->display()时给一个id这个id要唯一。
其实所有的东西ecmall2已经准备好了,只是不知道为什么没有使用,详细的原理不再介绍修改完后就可以使你的商城在运行方面的速度上一层楼,但是网络方面可不包哦。
我们以商品详细页为例:
- 修改app/goods.app.php的index方法的最后一行成这样{$this->display('goods.index.html','goods_detail_'.$id);}(不包括大括号,以下不再提示)。
- app/frontend.base.php文件里面的class StorebaseApp extends FrontendApp类的function _config_view()方法里的最后添加如下代码{$this->_view->cache_dir = ROOT_PATH . "/temp/html_cache/store/{$template_name}";}这里设置缓存的目录。
- 再找到app/frontend.base.php的class FrontendApp extends ECBaseApp类的function display($tpl)方法的方法名改成这样{function display($tpl,$cache_id="")}接着把方法里面的parent::display($tpl);改成{parent::display($tpl,$cache_id);}。
- 找到includes/ecapp.base.php里的function display($f)方法的方法名改成{function display($f,$cache_id="")},以及里面的parent::display($f);改成{parent::display($f,$cache_id);}。
- eccore/controller/app.base.php里面的function display($n)方法改成{function display($n,$cache_id='')},以及里面的$this->_view->display($n);改{$this->_view->display($n,$cache_id);}。
再修改eccore/view/template.php的function fetch($filename, $cache_id = '')方法如下。
01 |
function fetch( $filename , $cache_id = '' ) |
03 |
if (! $this ->_seterror) |
05 |
error_reporting (E_ALL ^ E_NOTICE); |
09 |
if ( strncmp ( $filename , 'str:' , 4) == 0) |
11 |
$out = $this ->_eval( $this ->fetch_str( substr ( $filename , 4))); |
15 |
if ( $this ->_checkfile) |
17 |
if (! is_file ( $filename )) |
19 |
$filename = $this ->template_dir . '/' . $filename ; |
24 |
$filename = $this ->template_dir . '/' . $filename ; |
27 |
if ( $this ->direct_output) |
29 |
$this ->_current_file = $filename ; |
30 |
$out = $this ->_eval( $this ->fetch_str( file_get_contents ( $filename ))); |
35 |
if ( $this ->is_cached( $filename , $cache_id )&& $cache_id && $this ->caching) |
37 |
$out = $this ->template_out; |
41 |
if (!in_array( $filename , $this ->template)) |
43 |
$this ->template[] = $filename ; |
46 |
$out = $this ->make_compiled( $filename ); |
50 |
if ( $this ->appoint_cache_id) |
52 |
$cachename = $cache_id ; |
56 |
$cachename = basename ( $filename , strrchr ( $filename , '.' )) . '_' . $cache_id ; |
58 |
$data = serialize( array ( 'template' => $this ->template, 'expires' => $this ->_nowtime + $this ->cache_lifetime, 'maketime' => $this ->_nowtime)); |
59 |
$out = str_replace ( "\r" , '' , $out ); |
61 |
while ( strpos ( $out , "\n\n" ) !== false) |
63 |
$out = str_replace ( "\n\n" , "\n" , $out ); |
66 |
if (! file_exists ( $this ->cache_dir)) |
68 |
ecm_mkdir( $this ->cache_dir); |
71 |
if ( file_put_contents ( $this ->cache_dir . '/' . $cachename . '.php' , '<?php exit;?>' . $data . $out , LOCK_EX) === false) |
73 |
trigger_error( 'can\'t write:' . $this ->cache_dir . '/' . $cachename . '.php' ); |
75 |
$this ->template = array (); |
82 |
if (! $this ->_seterror) |
84 |
error_reporting ( $this ->_errorlevel); |
87 |
return $out ; // 返回html数据 |
怎么样确定成功没有呢?你打开一个商品详细页面,多刷新几次,如果下面的执行时间不变就表示成功。其实用这个方法,你甚至可以给商城的商品分类、店铺的商品分类都缓存起来,条件是你要给$this->display()方法一个能确定唯一的id。
现在的问题:这些修改后好像是不会在固定时间后自动更新的缓存的,你可以去temp/html_cache/下面删除所有的东西,就会重新生成缓存了。
另外,我会继续研究,会有一个比较完善的生成静态的方案,但是应该是收费的(如果有资源的朋友可以过来互换啊,或者能成为核心交流人员的可以免费提供),但基本都是基于这些代码了。
- Hibernate 性能优化之查询缓存
查询缓存是建立在二级缓存基础之上的,所以与二级缓存特性相似,是共享的,适合修改不是很频繁的数据 查询缓存不是默认开启的,需要设置 1.在cfg文件中配置 <property name= ...
- thinkphp的静态缓存,数据缓存,快速缓存,查询缓存
// 静态缓存 // 'HTML_PATH' 缓存目录,这是个常量不是配置项,在入口文件中定义 // 'HTML_CACHE_ON' => true, // 开启静态缓存 'HTM ...
- 解决EFCore缓存机制导致的数据查询错误问题
如题,在对同一个Context连续进行相同条件的查询时,会触发EFCore的缓存机制,如果这个过程中数据发生了变化,则会出现错误. 例如:有两个Context实例,一个负责查询,一个负责增删改, A_ ...
- MVC实用架构设计(三)——EF-Code First(4):数据查询
前言 首先对大家表示抱歉,这个系列已经将近一个月没有更新了,相信大家等本篇更新都等得快失望了.实在没办法,由于本人水平有限,写篇博客基本上要大半天的时间,最近实在是抽不出这么长段的空闲时间来写.另外也 ...
- hibernate笔记--缓存机制之 二级缓存(sessionFactory)和查询缓存
二级缓存(sessionFactory): Hibernate的二级缓存由SessionFactory对象管理,是应用级别的缓存.它可以缓存整个应用的持久化对象,所以又称为“SessionFactor ...
- mybatis入门基础(八)-----查询缓存
一.什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存. 1.1. 一级缓存是sqlSession级别的缓存.在操作数据库时需要构造 ...
- mybatis中的查询缓存
一: 查询缓存 Mybatis提供查询缓存,用于减轻数据压力,提高数据库压力. Mybatis提供一级缓存和二级缓存. 在操作数据库时需要构造SqlSession对象,在对象中有一个数据结构(Hash ...
- 11g新特性-查询缓存(1)
众所周知,访问内存比访问硬盘快得多,除非硬盘体系发生革命性的改变.可以说缓存在Oracle里面无处不在,结果集缓存(Result Cache)是Oracle Database 11g新引入的功能,引入 ...
- 【Mybatis框架】查询缓存(二级缓存)
继上一篇博客,我们讲述了mybatis的一级缓存,接下来,我们来学习一下mybatis的二级缓存 博客链接地址: http://blog.csdn.NET/liweizhong193516/artic ...
随机推荐
- Android_Service
xml文件: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:t ...
- access应用分享
我最近开发了一个winform项目,用的是access数据库,当开发成功以后,有些电脑上就能正常运行,有些电脑就无法读取数据库文件,刚开始我以为是权限问题,后来我把安装程序卸载了,装在其它盘中(非C盘 ...
- LoadRunner安装包(性能测试工具分享)
今天在测试课指导老师朱香元的指导下,开始了测试软件的安装,下面我分享一下整个安装流程,最后我会附带安装包的 第一步:链接:http://pan.baidu.com/s/1pXqk2 密码:csjk , ...
- C#微信公众号开发 -- (七)自定义菜单事件之VIEW及网页(OAuth2.0)授权
通俗来讲VIEW其实就是我们在C#中常用的a标签,可以直接在自定义菜单URL的属性里面写上需要跳转的链接,也即为单纯的跳转. 但更多的情况下,我们是想通过VIEW来进入指定的页面并进行操作. 举一个简 ...
- 配置git DiffMerge工具
git的命令行貌似没有特别好用的UI工具,不管是Android Studio自带的还是其他的,完全代替命令行好像做不到.再加上对git来说没什么比diff和merge更正常不过的事情了.那就配置命令行 ...
- C++ 变量转换
atoi,atol,strtod,strtol,strtoul实现类型转换2006-02-13 版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明http://ivanvic.blogb ...
- 对比iOS中的四种数据存储
来自于大牛的文章给大家分享下 :http://www.infoq.com/cn/articles/data-storage-in-ios/
- 是么是 API 和 SDK
API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码 ...
- Ladder免费试用版
Ladder这款vpn软件最近在play中国区排名非常高,节节高升,可见大家还真需要这东西,软件做的不错,大家可以在试用版中升级到正式版. 下载地址
- java新手笔记12 单例
1.单例 package com.yfs.javase; public class Singleton { //private static final Singleton single = new ...