CodeIgnitor 缓存驱动类的使用

最近在给 redis 驱动类添加新的方法时又陷入了疑惑中,理不清这里面的类关系,所以这次彻底梳理一下。

CodeIgnitor 中使用缓存是通过 Libaray 下的 CI_Cache 代理调用 drivers 下的缓存驱动实现类(Cache_redis)方式进行的。

  • 下面是一个调用 Apc cache 类的一个示例:
$this->load->driver('cache', array('adapter' => 'apc', 'backup' => 'file'));

if ( ! $foo = $this->cache->get('foo'))
{
        echo 'Saving to the cache!<br />';
        $foo = 'foobarbaz!';

        // Save into the cache for 5 minutes
        $this->cache->save('foo', $foo, 300);
}

echo $foo;
  • CI_Cache 类的基本定义如下:
class CI_Cache extends CI_Driver_Library {
    protected $valid_drivers;
    protected $_cache_path;
    protected $_adapter;
    protected $_backup_driver;
    public $key_prefix;

    public function __construct();
    public function get();
    public function save();
    public function delete();
    public function increment();
    public function decrement();
    public function clean();
    public function cache_info();
    public function get_metadata();
    public function is_supported();
}
  • 上面这些方法也可以不用通过加载adapter的方式,而是直接通过属性的方式进行调用:
$this->load->driver('cache');
$this->cache->apc->save('foo', 'bar', 10);

// 文件缓存
$this->load->driver('cache');
$this->cache->file->save('foo', 'bar', 10);

// memcache 缓存
$this->load->driver('cache');
$this->cache->memcached->save('foo', 'bar', 10);

// redis 缓存
$this->load->driver('cache');
$this->cache->redis->save('foo', 'bar', 10);
  • 每种缓存驱动都有它的特定配置或者注意点,这些注意点都是具体缓存驱动实现类中的内容。

  • CI 框架内置了 Cache_apcCache_fileCache_memecachedCache_redisCache_wincache 这5种缓存方式。这些缓存驱动是通过驱动实现类的方式支持的。相关类文件目录结构如下:

|- app
|- system
 |- libraries
  |- Driver.php
  |- Cache
   |- Cache.php
   |- drivers
    |- Cache_apc.php
    |- Cache_file.php
    |- Cache_memcache.php
    |- Cache_redis.php
    |- Cache_wincache.php
  • 如上目录结构所示,其实所有的驱动类基类都是 Driver.php 中的 CI_Driver_Library 类,这个类只提供了一个__get()方法用于获取实际的驱动实现类,在里面主要进行了load_driver()的操作。

  • 在这里,Cache.phpCI_Cache类就继承了 CI_Driver_Library,从而获取了通过属性名加载缓存驱动实现类的能力。所以说,CI_Cache 实际上是一个驱动代理类,通过它加载具体的驱动类。在 load_driver() 末尾有这么一行代码:

// ... some code
// Instantiate, decorate and add child
$obj = new $class_name();
$obj->decorate($this);
$this->$child = $obj;
return $this->$child;
  • 在这段代码之前的一系列操作是通过属性名获取实际实现类名,然后这里实例化该类,并调用实现类的 decorate($parent) 方法把当前类中的方法和属性添加到实现类中,然后设置为 CI_Cache 类的属性,并返回。下次再调用时就能直接找到该类,不用再次加载。

  • 而每个具体的缓存驱动实现类则继承了 Driver.php 中的 CI_Driver 类,在这个类中提供了上面提到的 decorate($parent) 方法,它的主要用途就是把父类中的方法名和属性名存储到子类中,然后通过子类调用这些子类不存在的方法时,退化为通过 __call() 调用父类的方法。这样的话如果在父类 CI_Cache 中定义了一些与adapter 无关的方法时,也能通过 $this->cache->redis 去调用。

至此,CI_Cache 的所有内置类的关系已经全部说明完毕。

项目扩展

  • 上面基本说明了如何使用 CI 中的 library 中的类以及 driver 类(以 Cache driver 为例,对其他类型也适用),并且还说明内部相关类之间的关系。

  • 但框架内置的缓存驱动类可能有的方法缺失,那么就需要我们在项目中进行扩展。CI 提供了对 Library 内的类的自定义扩展以及创建自己的 driver 类的机制。

  • 这里以我们项目中的实际案例为例,下面是项目中的实际目录:

|- app
 |- libraries
  |- Cache
   |- Che300_Cache.php
   |- drivers
    |- Cache_predis.php
    |- Che300_Cache_redis.php
class Che300_Cache extends CI_Cache
{
    public function __construct()
    {
        parent::__construct();
        $this->valid_drivers[] = 'predis';
    }
}
  • 继承 CI_Cache 并且把 predis 也加入到驱动类数组中,这相当于一种新的驱动方式,所以在 drivers 目录下又按照命名约定新建了一个 Cache_predis 驱动实现类。所以下面的调用可以实现:
$this->load->driver('cache');
$this->cache->predis->set('key', 'value');
  • Che300_Cache_redis 也是创建了新的 redis 缓存驱动实现类,它继承了 CI_Cache_redis 类,实际上是对系统的默认 redis 类的覆盖。所以下面的调用实际返回的是 Che300_Cache_redis 驱动实现类:
$this->load->driver('cache');
$this->cache->redis->set('key', 'value');
2020/11/03 posted in  编程技术

php 序列化和反序列化

2020/09/29 posted in  日常折腾

网抑云辑评(二)

不知何时,网易云变成了网抑云,曾经的云村热评也变成了各种梗的发源地,云村的村民也都逐渐变成了网易云综合征患者,曾经的抖腿冠军也变成一个个的孤儿。这里也收集了一些广泛传播了网抑云的梗,为其推波助澜、煽风点火。

画重点

  • 我们究竟是活了365天,还是活了1天,重复了364遍。

  • 生而为人,我很抱歉

  • 你爱过一个人吗?从满心欢喜到满目疮痍

  • 有些人二十岁就死了,等到八十岁才被埋葬。

  • 温柔吗,拿命换的

Read more   2020/09/21 posted in  书影音游

音乐记忆

音乐是有记忆的,像是触发你大脑的一个机关。一旦音乐在耳边想起,立刻就穿越到过去某个场景、某个阶段。那时的感受全部回来了。

下面我由近及远分享一些能够触发我的大脑的机关:

All Falls Down - Alan Walker / Noah Cyrus X 义结筋澜 - 面筋哥 / 波澜哥

时间:2020年初

2020年初疫情期间,只能呆在家,看 B 站时看到这个「【面筋哥×波澜哥】我的烤面筋,融化你的心!」,然后循环了不知道多少遍。坐在床上,架着电脑桌,或在玩 lol,或者在工作,不断循环。后来找到了原唱,也很好听,更加地纯净,于是又循环了不知道多少遍。
如今只要一不小心随机到这首歌,就会想到疫情在家的那段日子,整天在床上玩电脑的日子。

Read more   2020/09/05 posted in  书影音游

PHP7.4 新特性

Typed properties

  • 现在类的属性支持类型声明了:

    class User {
        public int $id;
    public string $name;
    }
  • 注:设置属性 $id$name 的值时必须要指定类型,否则会报错:
    PHP Fatal error: Uncaught TypeError: Typed property User::$id must be int, string used

  • 注:访问属性之前必须要先初始化,否则会报错:

    • PHP Fatal error: Uncaught Error: Typed property User::$id must not be accessed before initialization
Read more   2020/09/02 posted in  编程技术

一次诡异的 SQL 数量统计查询不准的问题

一个统计数量(有连表)的 SQL,加上条件若干假设结果为 N1,然后再加条件详细统计细分数量,诡异的来了,假设加的条件分别是 T1.F1 = T2.F2 和 T1.F1 != T2.F2,这两个细分 SQL 的结果 N2 和 N3 加起来竟然不等于 N1,那么漏掉的这部分数据是啥,想不通。
(1)问了同事yz,他提了一个可能,F1 和 F2 在 where 语句中使用了之后(非 is null 语句),结果就肯定不会包含 F1 为 null 或 F2 为 null 的值
(2)对此我只能说——所有的诡异都是无知的反应。

2020/08/13 posted in  日常问题

知乎道理(1)

最近在知乎上看到了一些鸡汤,觉得很有道理,很符合当前的主流价值观,所以摘抄下来(虽然并无卵用)。
1、不要把努力的过程当做你炫耀的资本,如果你真的要炫耀,请直接上成果。
我不知道有多少次在朋友圈里看到“晨练打卡第一天”的照片,但奇怪的是,我朋友圈里到现在也没有出现过1个连续打卡超过10天的选手。
我不知道有多少次在朋友圈里看到在干净整洁的桌面上开着美颜看书的文艺照片,但奇怪的是,我朋友圈里很少有人看完一本书以后发表什么感慨和评论。
很多人会把这种开始努力的样子,当做一件可以炫耀的事情。
但是他们没明白,这种开始时的样子,任何人都可以毫不费力的做出来。
唯有坚持和结果,才是难得的。

Read more   2020/07/03 posted in  转载分享

帖子列表时如何查询包含我的帖子

场景

用户发帖之后,需要审核通过之后才能被别人看到,同时审核中的帖子自己也能够看到,通过一个列表接口如何实现?

分析

这个列表接口数据应包含:所有审核通过的帖子 + 自己的审核中的帖子

现有一个帖子表 post 定义如下:

Read more   2020/07/02 posted in  日常问题

《时蔬小话》——2020年第27周阅读笔记

一句话评价:有知识科普,有历史文化,有情感记忆,有生活细节,是一本值得读的好书!

百菜之祖

大白菜

  • 深秋清晨的薄雾,枯草上的白霜:

    霜降过后,清晨的冷空气已经可以让哈气变成凉凉的白雾。坐车经过乡下的园子,到处都是被犁头翻过、已积满白霜的土块。路边枯黄的草茎上,挂满了如碎雪一样的冰晶。

  • 炖大白菜

    初雪的冬天,母亲会从阳台上拎来父亲买来的大白菜,扒去干老的菜皮,摘下外层的菜叶垫在砂锅底,把中间白净带着银星的菜帮切成大片码在锅里,垫满半锅后,依次在白菜上垫好冻豆腐、烧肉、丸子、粉条,再盖上黄嫩的菜心。撒些调味的花椒、大料、姜片和切段的大葱,浇满汤汁搁在煤炉火上炖透。看着咕嘟嘟冒气的砂锅盖子,饱含汁水的菜香开始弥漫。初冬的大白菜原本味道就很清甜,经过如此煨煮之后的厚厚菜梗已经入口即化,淡淡的菜的甜味也融入到鲜美的汤汁中,于是我明摆,这顿又要多费几碗饭了。

Read more   2020/07/01 posted in  书影音游

blog 自动发布脚本

新的博客使用 mweb 生成静态文件,然后写了一个自动发布的脚本,当在 mweb 中写完内容,并生成网站之后,直接执行下面的脚本文件,就能在网站上看到效果了:

#! /bin/bash

cd /Users/feiffy/Sites/mweb

# 忽略 assets 文件, 0-忽略,1-不忽略
withAssets=0
if [ -n "$1" ]; then
    if [ "--with-assets" = $1 ]; then
        withAssets=1
    fi
fi

if [ ! -d "blog_deploy" ]; then
    mkdir "blog_deploy"
fi

# clean
rm -rf blog_deploy/*

# copy
cp ./blog/* blog_deploy/
if [ $withAssets -eq 1 ]; then
    cp -r ./blog/asset blog_deploy/
fi

# tar
tar -czf blog_deploy.tar.gz blog_deploy

echo 'uploading...'

# upload to server
scp blog_deploy.tar.gz <user>@<domain>:/var/www/upload

# deploy
ssh <user>@<domain> > /dev/null 2>&1 << eeooff
cd /var/www/upload
tar -xzf blog_deploy.tar.gz
rm blog_deploy.tar.gz

cp -r blog_deploy/* /var/www/html/
rm -rf blog_deploy

exit
eeooff

echo 'deploy succ'
2020/06/28 posted in  日常折腾

五一游南京

这是一篇回忆去年五一游览南京景点的文章。

最近疫情原因,几乎都在家,或家里公司两点一线。此时突然想到去年玩了好多地方,拍了很多照片,都没来得及回顾一下,正好现在有时间,就简单整理一下吧。

午朝门公园与明故宫遗址公园

这篇文章从去年五一的照片开始翻起。突然发现,原来去年的5.1我就已经记录了下午朝门公园的绣球花,只记得是去过午朝门看城墙的,但真不记得见过这绣球花的,记忆终究还是不可靠啊。

下午1点,从北面进入午朝门公园,迎面就是绣球花,再往前走,就是午朝门。

大概用了30分钟逛完了午朝门,折返回到北门,过马路对面就是明故宫遗址公园:

Read more   2020/06/09 posted in  书影音游

Message: Illegal string offset

示例

<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);

$a = '';

echo $a['k'];

// Warning: Illegal string offset 'k'

$a = [];

echo $a['k'];

// Notice: Undefined index: k

Read more   2020/05/27 posted in  日常问题

PHPStorm 格式化部分代码的技巧

如果是格式化一个方法内的代码,只需要将方法最后的右大括号删除,然后再加上,就能自动格式化方法大括号内的代码了。

如果是一个if或while结构内的代码,操作同上,删除最后的右大括号再加上即可。

2020/05/22 posted in  日常折腾

win10 搭建 php + apache 开发运行环境

我服了,作为一个4年的老 phper,当我想在 windows 上手动搭建环境还是遇到了好多问题,所以通过这篇记录下来,不要每次都是重新开始,每一次都要蹚一遍所有的坑!

php

在官网这个地址 https://windows.php.net/download/ 下载已编译好的php程序。里面同时提供了多个版本,当然选最新版的 php7.4,然后在 php7.4 里面又提供了4个版本,分别是:

  • VC15 x64 Non Thread Safe
  • VC15 x64 Thread Safe [√]
  • VC15 x86 Non Thread Safe
  • VC15 x86 Thread Safe

真是选择困难症啊,首先,win10是64位的,那肯定选x64,其次使用的是 apache,所以选择 thread safe 版本(原因请参考1),所以最终选择 VC15 x64 Thread Safe。如下图1所示,点击下载那个 zip 压缩文件。直接浏览器下载比较慢,所以我把地址复制到迅雷下载会快很多。

Read more   2020/05/17 posted in  日常折腾

几千万数据,更改 MySQL 表结构

数据量大、并发量高场景,如何在流量低峰期,平滑实施表结构变更?

  • 如果是减column,升级程序不使用即可
  • 如果是修改column,程序兼容性容易出问题

方案一:在线修改表结构

alter table add column
数据量大的情况下,锁表时间会较长,造成拒绝服务,一般不可行。
Read more   2020/05/11 posted in  编程技术