作为一个框架,我们还没有相应的缓存组件,下面我们就来构建我们的缓存组件。

先来定义一下接口,在 src 文件夹下创建 cache 文件夹,在cache文件夹下创建 CacheInterface.php 文件,其中定义 Cache 相应的接口,其内容如下:

<?php
namespace sf\cache;/*** CacheInterface* @author Harry Sun <sunguangjun@126.com>*/
interface CacheInterface
{/*** Builds a normalized cache key from a given key.*/public function buildKey($key);/*** Retrieves a value from cache with a specified key.*/public function get($key);/*** Checks whether a specified key exists in the cache.*/public function exists($key);/*** Retrieves multiple values from cache with the specified keys.*/public function mget($keys);/*** Stores a value identified by a key into cache.*/public function set($key, $value, $duration = 0);/*** Stores multiple items in cache. Each item contains a value identified by a key.*/public function mset($items, $duration = 0);/*** Stores a value identified by a key into cache if the cache does not contain this key.* Nothing will be done if the cache already contains the key.*/public function add($key, $value, $duration = 0);/*** Stores multiple items in cache. Each item contains a value identified by a key.* If the cache already contains such a key, the existing value and expiration time will be preserved.*/public function madd($items, $duration = 0);/*** Deletes a value with the specified key from cache*/public function delete($key);/*** Deletes all values from cache.*/public function flush();
}

定义了 buildKey/get/mget/set/mset/exists/add/madd/delete/flush接口,对应功能如下:

  • buildKey:构建真正的 key,避免特殊字符影响实现
  • get:根据 key 获取缓存的值
  • mget:根据 keys 数组获取多个缓存值
  • set:根据 key 设置缓存的值
  • mset:根据数组设置多个缓存值
  • exists:判断 key 是否存在
  • add:如果 key 不存在就设置缓存值,否则返回false
  • madd:根据数组,判断相应的 key 不存在就设置缓存值
  • delete:根据 key 删除一个缓存
  • flush:删除所有的缓存

实现缓存,可以使用很多方式,比如使用文件、数据库、memcache 以及 Redis 等。

我们今天先使用文件缓存来实现相应的接口。

其主要思想就是,每一个 key 都对应一个文件,缓存的内容序列化一下,存入到文件中,取出时再反序列化一下。剩下的基本都是相应的文件操作了。

在 src/cache 文件夹下创建 FileCache.php 文件,其内容如下:

<?php
namespace sf\cache;/*** CacheInterface* @author Harry Sun <sunguangjun@126.com>*/
class FileCache implements CacheInterface
{/*** @var string the directory to store cache files.* 缓存文件的地址,例如/Users/jun/projects/www/simple-framework/runtime/cache/*/public $cachePath;/*** Builds a normalized cache key from a given key.*/public function buildKey($key){if (!is_string($key)) {// 不是字符串就json_encode一把,转成字符串,也可以用其他方法$key = json_encode($key);}return md5($key);}/*** Retrieves a value from cache with a specified key.*/public function get($key){$key = $this->buildKey($key);$cacheFile = $this->cachePath . $key;// filemtime用来获取文件的修改时间if (@filemtime($cacheFile) > time()) {// file_get_contents用来获取文件内容,unserialize用来反序列化文件内容return unserialize(@file_get_contents($cacheFile));} else {return false;}}/*** Checks whether a specified key exists in the cache.*/public function exists($key){$key = $this->buildKey($key);$cacheFile = $this->cachePath . $key;// 用修改时间标记过期时间,存入时会做相应的处理return @filemtime($cacheFile) > time();}/*** Retrieves multiple values from cache with the specified keys.*/public function mget($keys){$results = [];foreach ($keys as $key) {$results[$key] = $this->get($key);}return $results;}/*** Stores a value identified by a key into cache.*/public function set($key, $value, $duration = 0){$key = $this->buildKey($key);$cacheFile = $this->cachePath . $key;// serialize用来序列化缓存内容$value = serialize($value);// file_put_contents用来将序列化之后的内容写入文件,LOCK_EX表示写入时会对文件加锁if (@file_put_contents($cacheFile, $value, LOCK_EX) !== false) {if ($duration <= 0) {// 不设置过期时间,设置为一年,这是因为用文件的修改时间来做过期时间造成的// redis/memcache 等都不会有这个问题$duration = 31536000; // 1 year}// touch用来设置修改时间,过期时间为当前时间加上$durationreturn touch($cacheFile, $duration + time());} else {return false;}}/*** Stores multiple items in cache. Each item contains a value identified by a key.*/public function mset($items, $duration = 0){$failedKeys = [];foreach ($items as $key => $value) {if ($this->set($key, $value, $duration) === false) {$failedKeys[] = $key;}}return $failedKeys;}/*** Stores a value identified by a key into cache if the cache does not contain this key.*/public function add($key, $value, $duration = 0){//  key不存在,就设置缓存if (!$this->exists($key)) {return $this->set($key, $value, $duration);} else {return false;}}/*** Stores multiple items in cache. Each item contains a value identified by a key.*/public function madd($items, $duration = 0){$failedKeys = [];foreach ($items as $key => $value) {if ($this->add($key, $value, $duration) === false) {$failedKeys[] = $key;}}return $failedKeys;}/*** Deletes a value with the specified key from cache*/public function delete($key){$key = $this->buildKey($key);$cacheFile = $this->cachePath . $key;// unlink用来删除文件return unlink($cacheFile);}/*** Deletes all values from cache.* Be careful of performing this operation if the cache is shared among multiple applications.* @return boolean whether the flush operation was successful.*/public function flush(){// 打开cache文件所在目录$dir = @dir($this->cachePath);// 列出目录中的所有文件while (($file = $dir->read()) !== false) {if ($file !== '.' && $file !== '..') {unlink($this->cachePath . $file);}}// 关闭目录$dir->close();}
}

相关实现的解释都直接写在code中的注释里了。

然后我们来测试一下我们的缓存组件,首先我们需要添加一下配置文件,在 config 文件夹下创建 cache.php 文件,配置如下内容:

<?php
return ['class' => '\sf\cache\FileCache','cachePath' => SF_PATH . '/runtime/cache/'
];

然后在 SiteController.php 中简单使用如下:

    public function actionCache(){$cache = Sf::createObject('cache');$cache->set('test', '我就是测试一下缓存组件');$result = $cache->get('test');$cache->flush();echo $result;}

访问 http://localhost/simple-framework/public/index.php?r=site/cache 路径,得到结果如下:

我就是测试一下缓存组件

这样我们完成了使用文件的缓存组件。

好了,今天就先到这里。项目内容和博客内容也都会放到Github上,欢迎大家提建议。

code:https://github.com/CraryPrimitiveMan/simple-framework/tree/0.9

blog project:https://github.com/CraryPrimitiveMan/create-your-own-php-framework

转载于:https://www.cnblogs.com/CraryPrimitiveMan/p/5428224.html

构建自己的PHP框架--构建缓存组件(1)相关推荐

  1. 构建自己的PHP框架--构建缓存组件(2)

    上一篇博客中使用文件实现了缓存组件,这一篇我们就使用Redis来实现一下,剩下的如何使用memcache.mysql等去实现缓存我就不一一去做了. 首先我们需要安装一下 redis 和 phpredi ...

  2. 教你十分钟构建好 SpringBoot + SSM 框架

    来源:Howie_Y https://juejin.im/post/5b53f677f265da0f8f203914 目前最主流的 java web 框架应该是 SSM,而 SSM 框架由于更轻便与灵 ...

  3. 构建你的第一个Vue.js组件

    我记得当时我拿起CakePHP,我很喜欢,开始使用它是多么容易.这些文档不仅结构合理,详尽无遗,而且用户友好.多年以后,这正是我在Vue.js中感受到的.然而,与Cake相比,Vue文档仍然缺少一件事 ...

  4. 录制完脚本怎么做接口自动化测试_快速构建轻量级接口自动化框架

    随着移动互联网和微服务的迅速发展,大部分企业都采用接口的方式实现客户端和服务端的交互,传统的PC端也逐渐趋向于前后端分离架构.为了应对此种架构下的业务迭代,很多QA团队开始推广接口自动化,甚至是自研接 ...

  5. 基于ForkJoin构建一个简单易用的并发组件

    2019独角兽企业重金招聘Python工程师标准>>> 基于ForkJoin构建一个简单易用的并发组件 在实际的业务开发中,需要用到并发编程的知识,实际使用线程池来异步执行任务的场景 ...

  6. mezzanine-一个功能强大且易于扩展性的Django框架构建的内容管理平台

    mezzanine是一个功能强大且灵活的内容管理平台. Mezzanine使用Django框架构建,提供了一个简单但高度可扩展的体系结构,我们鼓励您深入研究和修改代码.Mezzanine是BSD许可的 ...

  7. Vue.js构建用户界面的渐进式框架(前端学习笔记1.0)

    文章目录 前言 一.Vue是什么? 二.前端核心分析 1.1.概述 1.2.前端三要素 1.3.结构层(HTML) 1.4.表现层(CSS) 1.5.行为层(JavaScript) 二.前端发展史 2 ...

  8. 基于Spring4+SpringMVC4+Mybatis3+Hibernate4+Junit4框架构建高性能企业级的部标1077视频监控平台...

    开发企业级的部标GPS监控平台,投入的开发力量很大,开发周期也很长,选择主流的开发语言以及成熟的开源技术框架来构建基础平台,是最恰当不过的事情,在设计之初就避免掉了技术选型的风险,避免以后在开发过程中 ...

  9. 构建Java并发模型框架

    2002 年 2 月 22 日 Java的多线程特性为构建高性能的应用提供了极大的方便,但是也带来了不少的麻烦.线程间同步.数据一致性等烦琐的问题需要细心的考虑,一不小心就会出现一些微妙的,难以调试的 ...

最新文章

  1. linux root权限_深入了解 Linux 权限
  2. 高频小功率三极管-S9018
  3. ABAP 向上取整和向下取整 CEIL FLOOR
  4. pandas 按字符串肚脐眼 读取数据_十分钟学习pandas! pandas常用操作总结!
  5. thinkphp3.1迁移php7,ThinkPHP3.1迁移到PHP7的注意事项
  6. pb怎么打开服务器上的文件夹,前台PB客户端怎么连接服务器上的SQL后台数据库...
  7. 如何通过 反射 调用某个对象的私有方法?
  8. 干货 | 大牛谈嵌入式C语言的高级用法
  9. 高并发服务设计——缓存(转载)
  10. jstl中c:foreach下的表格实现异步刷新
  11. 蓝牙耳机哪款适合玩枪战类手游?低延迟听声辨位五款蓝牙耳机推荐
  12. 电子科技大学《图论及其应用》复习总结--第一章 图的基本概念
  13. 元月元日是哪一天_元宵节的农历日期是哪一天 - 中国万年历
  14. 代码规范(Sonar, P3C)
  15. Linux查看文件夹大小
  16. Python爬虫获取PPT模板
  17. 网站横幅切换jquery 插件
  18. JS-变量提升与暂时性死区概念
  19. 将电脑调成护眼色不一定起到护眼的功能
  20. SSL单向认证和双向认证交互流程

热门文章

  1. 【实验楼】python简明教程
  2. C++ 笔记(36)—— std::cout 输出保留小数位数
  3. Python+OpenCV 图像处理系列(9)—— 图像的翻转和缩放插值
  4. Python+OpenCV 图像处理系列(1)— Ubuntu OpenCV安装、图片加载、显示和保存
  5. c语言和c++字符串操作对比
  6. 关于C语言中的数组指针、指针数组以及二级指针
  7. nvGRAPH API参考分析(一)
  8. 自动驾驶平台,阵营, 主要传感器与场景联系
  9. 地面标识检测与识别算法
  10. 客快物流大数据项目(十七):自定义镜像mycentos