Categories
PHP

PHP 通过 Redis NX 特性实现独占锁

对于简单的业务,我们可以通过单实例的 Redis 实现一个全局独占锁。笔者以 PHP 为例,实现一个加锁类。 实现原理 对于 Redis 的 SET 命令,支持 NX 特性,官方解释为:Only set the key if it does not already exist。也就是,当 key 不存在时设置成功后,才会返回 OK,否则返回 nil。这样,当多个并发请求设置 key 时,只有一个会成功。 然后,结合 EX 过期时长,指定加锁时长,即过期后自动释放锁。再通过指定 key 的值为随机 Token,来保证当前操作不会错误的释放其它业务请求的锁。详见下文实例。 SET 用法如下: 具体实现 实例的完整源码,放到了:https://github.com/xingchaovv/php-example/tree/master/src/RedisLocker,请参考使用。源码基于 PHP 8。 方法 lock 实现 方法 unlock 实现 用法 (完) 扫码阅读和分享

Categories
PHP

PHP 8 新特性: Nullsafe 操作符(空安全)

PHP 8 新增了 Nullsafe 操作符(空安全):?->,顾名思义,以一种安全的方式操作可能为 null 的对象。以此可以简化对于 null 值的逻辑判断。 准备 我们先准备一些类和实例。如下: 以往实现 不严谨的程序员,想获取 user1 的 total 信息时,可能会直接取值。如下: 当然,程序会直接报错: 有点经验的程序员这么做(实际会经常这么做): 当然,实际中还需要对 fanInfo 等做一系列判断,也可能无法避免一些嵌套的判断。 Nullsafe 实现 现在有了 Nullsafe 操作符,我们可以直接这样用: 输出结果: 当然 user1 为 null 时,表达式直接返回了 null,且不再会调用属性 fanInfo 和后续操作。下面详细介绍求值策略。 短路求值策略 Nullsafe 操作符遵循的是完全短路(Full Short Circuiting)的求值策略。 举例说明: 当 a 为 null 时,方法 b 不会被调用,$foo 被赋值为 null。 当 a 为 null […]

Categories
PHP

PHP 8 函数 str_contains:检查是否包含子字符串

PHP 8 中新增了一个函数 str_contains,专门用于检查一个字符串是否包含了另外一个字符串。很大原因是 strpos 函数不够直观且容易出错。这里简单介绍下。 原型如下: 如果字符串 $haystack 中包了字符串 $needle,则返回 true,否则为 false。检查时大小写敏感。 看下例子: 输出为: 因为大小写敏感,第二行返回 false。 如同第三行,当目标字符串为空字符串时,结果总是为 true。 参考资料 str_contains 扫码阅读和分享

Categories
PHP

PHP 8 新特性:联合类型

定义 在 PHP 8 中,定义函数参数的类型时,可以指定多种类型;也就是允许它的值为这些类型中的一种;我们称这种类型为联合类型(Union Types)。 一般语法 联合类型的语法格式为: 举第一个例子 🌰: 上文中 int|float 指明了参数 $score 为联合类型,它可以是 int 类型 或 float 类型。 输出结果为: 上文中,因为传递了不允许的类型 string,直接抛出 TypeError 类型的错误。 ?Type 语法 我们可以指定类型为某个 Class 或者 null,比如 DateTime|null,简化写法为 ?Type。 另外,不支持单独使用类型 null。 举第二个例子 🌰: 输出为: 伪类型 false 可以在联合类型使用伪类型 false,比如 string|false。另外,不支持单独使用类型 false。暂不支持伪类型 true(保留关键字)。 参考资料 Type declarations 扫码阅读和分享

Categories
PHP

PHP 8 新特性:命名参数

PHP 8 新增了语言特性:命名参数(Named Arguments)。以往只能按照函数定义的顺序传递参数,现在可以指定参数名称自定义顺序。并且可以跳过带默认值的参数。 正文 我们举例说明。 我们先定义一个函数,接受三个参数。函数中直接将实际接收到的参数打印出来。代码如下: 在 PHP 7 中,我们调用函数时,不允许带参数名称。如下: 在 PHP 8 中,我们可以像下面这样。 指定默认顺序参数名,效果同上 参数一二顺序换位,不受影响 跳过带有默认值的参数 type。 无参数名和带参数名混合使用 话外 除了 PHP,还有哪些语言支持命名参数呢? Python:见《Expressions -> Calls》、《Python Keyword Arguments》 C# 4:见《命名实参和可选实参》 Swift:见《Functions -> Functions With Multiple Parameters》 参考资料: PHP RFC: Named Arguments (完) 扫码阅读和分享

Categories
PHP

PhpSpreadsheet(PHP Excel 类库)正确显示身份证号的解决办法

PhpSpreadsheet(原 PHPExcel)是 PHP 中最流行的电子表格软件(如 Excel)的处理类库,可以读取、写入 Excel 数据等,经常用于业务系统的报表导出等。 问题复现 在使用过程中,经常遇到的问题是,无法正常显示身份证号。我们看下实例: 源文件:sheet1.php 终端下执行下:% php sheet1.php,保存到了文件 users.xlsx,查看结果: 可见,莱德等小狗狗的身份证号,默认被当作了数字数据类型。 原因分析 这是因为在通过 fromArray 间接或 或直接使用 setCellValue 方法时,未指定数据类型。这时,PhpSpreadsheet 使用值绑定器(Value Binder)自动将传入的参数转换为合适的 Cell 数据类型。具体源码实现,见默认的值绑定器是 DefaultValueBinder。此处身份证号虽然是原生 string,但符合类对数字的定义,处理成了数字数据类型。 解决办法:使用 setCellValueExplicit 我们在设置值时使用 setCellValueExplicit 方法指定类型。 天天的身份证号已经正常显示。 若希望类似 fromArray 批量写入数据,可自行实现一个迭代处理。 解决办法:自定义值绑定器 另外一种办法是实现自定义的值绑定器类。 直接看实现源码: 结果 实现说明: 这里自定义了类 MyValueBinder,扩展了 DefaultValueBinder,“重写”了方法 dataTypeForValue。 参考资料 文档 Accessing cells (全文完) 扫码阅读和分享

Categories
PHP

PHP 函数 explode 用法详解

介绍 explode 函数可以通过一个字符串来分割原始字符串,返回一个存放结果的数组。比如将字符串 1001,1002,1003 通过字符 , 分割为数组 [1001, 1002, 1003] 。 函数原型 explode(string $delimiter, string $string[, int $limit ]) : array 第一个参数 $delimiter,类型为字符串,表示分隔符号。第二个参数 $string,类型为字符串,表示原始要分隔的字符串。第三个参数 $limit,类型为整型,可选。当参数为正数时,表示最多分隔的结果个数。超过此个数后,后续字符串不再分隔;当参数为负数时,表示从分隔结果的末尾忽略此数量的结果。 用法示例 分隔时,传递分隔符和原始字符串。 explode(“::”, “1001::1002::1003”); // 结果 array(3) { [0]=> string(4) “1001” [1]=> string(4) “1002” [2]=> string(4) “1003” } 分隔时,同时指定最多个数。 explode(“::”, “1001::1002::1003”, 2) // 结果 array(2) { [0]=> string(4) “1001” [1]=> string(10) “1002::1003” } […]

Categories
PHP

PHP 函数 substr 用法详解

介绍 substr 函数用来对一个字符串的内容进行截取,返回字符串的一部分内容。 函数原型如下: substr(string $string, int $start[, int $length]) : string 第一个参数为字符串 $string,必传,表示原始的字符串。第二个参数为整型 $start,必传,表示截取起始的位置(截取包含此字符),参数为非负数时表示位置从原字符串开头向右数(第一个字符位置为 0),参数为负数时表示位置从原字符串末尾向左数(原字符末尾的位置为 -1)。第三个参数为整型 $length,可选,表示截取字符的长度(即从截取起始的位置)。字符的截取方向从左向右。当未传此参数时,表示截取到末尾。参数为负数时表示省略末尾的此长度的字符(-1 表示省略 1 个字符)。返回值,成功时为截取后的字符串;失败时为 false。 用法 // 指定开始位置 substr(‘zhangxingchao’, 2); // 返回 angxingchao 经验 结果判断问题 当我们需要判断是否执行成功时,需要使用全等而不是等于。比如: // 截取失败时 if (substr(“1230”, -1, 0) == false)) { echo “fail”; } // 此例子中实际截取成功 中文乱码问题 在 UTF-8 编码中,一个中文至少占三个字节。substr 函数的长度单位为字节长度,截取时若按照中文字符个数传递截取长度,可能会截取半个中文字符,导致出现乱码问题。 比如: substr(“大神”, 0, […]

Categories
PHP

Composer 的基础用法

Composer 是一个 PHP 的依赖管理工具。通过本文,我介绍一下 Composer 的基础用法。想了解 Composer,可以先阅读 《Composer 介绍和安装指南》。 Monolog 是一个流行的 PHP 类库,用于在项目中记录日志,它实现了 PSR-3 规范。我们就以在项目中安装它为例,来看看如何使用 Composer。 扫码阅读和分享

Categories
PHP

Composer 介绍和安装指南

介绍 Composer 是一个 PHP 的依赖管理工具。它可以用来管理 PHP 项目依赖的类库,包括声明依赖的类库、安装和更新这些类库,将它们安装到项目的一个目录里,比如 vendor 目录。详见 官网、Github。 扫码阅读和分享