解决ThinkPHP5 Redis::delete() is deprecated

背景

最近需要基于一个旧的php项目,构建一个架构为ARM的php-fpm镜像(客户的机器是ARM架构的),目前手头只有x86 64的镜像。找了一个同时支持x86 64和ARM架构的php-fpm7.1的基础镜像后,基于以前的项目的Dockerfile改了一下,准备构建ARM的镜像。构建成功后,发现网站的logout会报错:redis delete method is deprecated.

这个php的项目使用的是thinkPHP5.0.10,session的存储驱动是redis,logout会清理session,调用框架的底层代码,如下图所示:

解决

报错的字面意思是redis的delete方法已经过时了,被废弃了,现在删除key的方法是unlink或del。

疑问1:那为什么我们线上的x86 64架构的php-fpm镜像没有这个报错呢?

线上的php-fpm的版本号也是7.1,redis的版本号也是4.0.14。我们当前ARM架构部署的这套代码的php、redis版本号和线上是保持一致的!

那么造成一个报错,一个不报错,一定还有我没注意到的细节差异!

既然报错redis的delete命令已经过时,那么一定是在某个版本淘汰了这个命令,是不是我把redis版本降低到这个特定版本之前的一个版本,就能绕过这个问题呢?

可惜,google了一圈,redis的官网、github仓库都找不到delete是从哪个版本被废弃的。

其实,就算我们找到了这个版本,貌似也无法解答疑问1

此时,有同事提出直接修改tp5的框架源码,把delete方法改为del方法。其实,这个也能解决我们当下的问题,但是我们基于别人某个特定版本的框架代码,直接修改本地源码的做法,会不会有什么问题呢?诸如:以后维护的人在没有明确文档告知的情况下,看到这个框架的版本号,却发现自己使用官网的这个框架和我们项目的框架表现不一致,会不会觉得很奇怪。话说,还有什么说法?框架升级如果我们擅自改了以前旧框架的源码,升级会不会有问题?框架升级就是无脑的文件覆盖替换吗?纠结了一下,还是不想改框架的源码!

继续,找寻导致结果不同的原因:

FROM laradock/php-fpm:latest-7.1

COPY ./config/sources.list /etc/apt/

COPY ./config/php.ini /usr/local/etc/php

COPY ./config/phpredis-5.3.4 /tmp/phpredis-5.3.4

#添加源码
COPY ./be-code/ /var/www/html/api/

#额外覆盖源码app的配置文件
COPY ./config/app-config/ /var/www/html/api

#安装ps,vim,ping命令,用于日常运维
RUN apt-get update && \
	apt-get install -y procps && \
	apt-get install -y vim && \
    apt-get install -y iputils-ping

#安装redis扩展
WORKDIR /tmp/phpredis-5.3.4

RUN phpize && \
	./configure && \
	make && make install && \
	echo "extension=redis.so" | tee /usr/local/etc/php/conf.d/redis.ini

#修改目录权限
RUN mkdir /var/www/html/api/runtime && \
    chmod -R 777 /var/www/html/api

#进入容器后的默认工作目录
WORKDIR /var/www/html/api

以上这段Dockerfile是我们为ARM架构改写的一个Dockerfile,其中因为基础镜像php-fpm没有redis的扩展,所以我们自己装了个phpredis-5.3.4。

然后,我去到线上想看一下x86 64架构下的php-fpm的phpredis的扩展版本号是多少。得到的答案是:3.1.5

www-data@1e2f16b9f897:~/html/api$ php --ri redis

redis

Redis Support => enabled
Redis Version => 3.1.5
Available serializers => php

emmm,这就是差异嘛,那么现在的局面是:

x86 64架构下的php-fpm的镜像使用的redis的版本是4.0.14,phpredis的版本是3.1.5;

ARM架构下的php-fpm的镜像使用的redis版本也是4.0.14,phpredis的版本是5.3.4;

phpredis是php的一个操作redis的扩展,php借助这个扩展和redis进行交互。其实phpredis的版本号和redis的版本号有映射关系,想一下这个道理,redis版本升级,那么相应的也需要升级phpredis的版本号。

那么,如果我们把上面的Dockerfile改一下,降低phpredis的版本号到3.1.5,应该就能解决ARM架构下的logout的报错问题!

改写Dockerfile如下:

FROM laradock/php-fpm:latest-7.1

COPY ./config/sources.list /etc/apt/

COPY ./config/php.ini /usr/local/etc/php

COPY ./config/phpredis-3.1.5 /tmp/phpredis-3.1.5

#添加源码
COPY ./be-code/ /var/www/html/api/

#额外覆盖源码app的配置文件
COPY ./config/app-config/ /var/www/html/api

#安装ps,vim,ping命令,用于日常运维
RUN apt-get update && \
	apt-get install -y procps && \
	apt-get install -y vim && \
    apt-get install -y iputils-ping

#安装redis扩展
WORKDIR /tmp/phpredis-3.1.5

RUN phpize && \
	./configure && \
	make && make install && \
	echo "extension=redis.so" | tee /usr/local/etc/php/conf.d/redis.ini

#修改目录权限
RUN mkdir /var/www/html/api/runtime && \
    chmod -R 777 /var/www/html/api

#进入容器后的默认工作目录
WORKDIR /var/www/html/api

果然,问题解决了!!!

疑问2:

但是,还有个细节没被搞清楚,既然你redis的版本是4.0.14,且4.0.14的redis已经废弃了delete方法,下面这段linux交互结果可以佐证:

进入redis容器,设置test这个键,使用delete删除test时,报错了!

root@section9-2nd:/home/wangzhiping# docker exec -it ce4de98f0230 /bin/bash
root@ce4de98f0230:/data# redis-cli
127.0.0.1:6379> set test test
OK
127.0.0.1:6379> delete test
(error) ERR unknown command `delete`, with args beginning with: `test`,

为啥你使用一个phpredis的低版本3.1.5,却可以使用delete命令和redis4.0.14进行交互,切没有报错delete被废弃呢?!

答案是:

你会看到:

这里触及到知识盲区了,怎么你phpstorm作为一个IDE,你还要操作我的代码逻辑?考虑得这么细致,在当前环境redis的版本已经不支持delete方法时,会自动帮我转化为del方法! 

疑问3:

什么是phpstorm-stubs?

https://github.com/JetBrains/phpstorm-stubs

官网的简介:

PhpStorm 的 PHP 运行时和扩展头文件。

STUBS 是正常的、语法正确的 PHP 文件,包含所有内置 PHP 内容和大多数标准扩展的函数和类签名、常量定义等。反正给人的感觉是STUBS这个东西为了phpstorm这个IDE服务的,IDE又是为我们服务的,所以本质上还是为我们服务,有哪些服务呢?IDE可以根据这个STUBS的文件定义,来实现代码检查、类型推断、文档弹出。

这也就解释了,为啥IDE这么智能,能自动帮我们替换redis的delete为del方法!

不对,就算STUBS文件是可以影响PHP运行时的文件,但是我们线上环境是没有IDE的,我们的代码又不是跑在IDE里面的,那么应该是不会受STUBS这个redis命令替换逻辑的影响?!

疑问4:到底是谁帮我们替换了delete命令?

那么,唯一的可能就是低版本的phpredis在于高版本的redis服务器进行通信时,实际发送的就是del命令,delete命令被phpredis这个客户端替换了,那么代码应该是在phpredis扩展的代理里面?

下面这个是phpredis的一段源码:

 以下面是phpredis的仓库介绍,我们摘抄了一段del的说明:

大致意思是:

如果你的redis server的版本号(不是指你的phpredis的版本号)是>4的,那么可以用unlink来替代del。另外,delete是del的别名,以后高版本的phpredis会 直接移除delete方法,那么此时你直接使用delete就是delete,不存在delete是del的别名的说法了,例如:phpredis5.3.4使用redis的delete方法就是直接报错了!!!所以,phpredis的扩展的大版本号最好和redis server的大版本号保持一致,避免出些莫名其妙的问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值