资讯动态

psr/cache 版本演进全解析:PSR-6 缓存接口标准从 1.0 到 3.0 的强类型化改造

发布时间:2026/10/15 1:53:56 来源:尧图企业网站定制
后端【免费下载链接】cache项目地址https://gitcode.com/gh_mirrors/cac/cache点击查看免费下载本文以仓库根目录的 CHANGELOG.md 为脉络逐版本梳理 psr/cache——PHP-FIG 官方维护的 PSR-6 缓存接口标准包——从 2015 年 1.0.0 到 2021 年 3.0.0 的演进历程并结合 src/ 下的接口源码与 composer.json 配置逐条验证每一次破坏性变更的落地形态。读完你将掌握该包在缓存生态中的定位、四个接口的完整契约、2.0.0 与 3.0.0 两次强类型化改造的具体内容以及面向「实现方」与「调用方」的升级注意事项。一、项目定位一个「只定义接口」的标准包在深入版本历史之前先明确这个仓库的性质。根目录 README.md 开宗明义本仓库持有与 PSR-6Caching Interface相关的全部接口它本身不是一个缓存实现仅仅是描述缓存机制各组件的接口契约。也就是说psr/cache 回答的是「缓存库之间如何互通」的问题而不是「怎么把数据存进 Redis / Memcached」的问题。从 composer.json 可以进一步确认包的基本信息包名psr/cache描述为「Common interface for caching libraries」缓存库通用接口关键词psr、psr-6、cache许可证MIT作者PHP-FIG最低 PHP 版本 8.0.0PSR-4 自动加载Psr\Cache\命名空间映射到src/目录分支别名dev-master对应3.0.x-dev。当前 src/ 目录下恰好是 4 个接口文件它们共同构成 PSR-6 的全部契约接口文件职责CacheItemInterface.php单个缓存条目Item的读写与过期语义CacheItemPoolInterface.php缓存池Pool条目获取、批量操作、持久化CacheException.php实现方抛出的所有异常的基接口InvalidArgumentException.php非法参数异常接口继承自 CacheException下文将按 CHANGELOG 记录的版本顺序逐一拆解这套契约是如何从 1.0.0 的「规范定型」演进到 3.0.0 的「全方法强类型化」的。二、版本演进总览CHANGELOG.md 开头明确本项目所有重要变更按发布时间倒序记录reverse chronological order by release。因此3.0.0 排在最前1.0.0 在最后。四个版本的演进全貌如下版本发布日期变更类型核心内容3.0.02021-02-04破坏性变更所有方法均声明返回类型2.0.02021-02-04破坏性变更所有方法类型化参数expiresAt()参数类型声明为DateTimeInterfaceCacheException继承Throwable最低 PHP 版本提升至 8.01.0.12016-08-06修复phpdoc 注释间距、语法修正getItems()/deleteItems()参数类型细化为string[]明确expiresAt()/expiresAfter()的null参数合法性1.0.02015-12-11初始稳定版反映已接受的 PSR-6 规范两个值得注意的细节其一2.0.0 与 3.0.0 的发布日期完全相同2021-02-04从 CHANGELOG 的日期看这意味着两次破坏性升级是同一时间窗口内连续推出的其二从 1.0.12016到 2.0.02021间隔近五年期间主要工作是文档层面的打磨直到 PHP 8.0 发布后才顺势完成了类型系统上的彻底升级。三、1.0.02015-12-11初始稳定版与 PSR-6 接口骨架CHANGELOG 对 1.0.0 的描述只有一句「Initial stable release; reflects accepted PSR-6 specification」初始稳定版反映已通过的 PSR-6 规范。这一版的全部技术含量实际上都沉淀在当时定型的接口语义里而这些语义至今仍完整保留在 src/ 的 docblock 中Pool 侧的关键契约CacheItemPoolInterface.phpgetItem(string $key)必须始终返回一个 CacheItemInterface 对象即使在缓存未命中miss时也不得返回 null——调用方永远不需要判空只需通过条目的isHit()判断是否命中getItems(array $keys [])返回以缓存键为键的iterable未命中的键也会返回对应的条目对象当传入空数组时必须返回一个空的可遍历集合hasItem(string $key)出于性能考虑可以避免读取实际值因此与get()之间可能存在竞态规范建议用isHit()替代所有以$key/$keys为参数的入口遇到非法键时必须抛出实现了Psr\Cache\InvalidArgumentException的异常。Item 侧的关键契约CacheItemInterface.php条目对象只能通过 Pool 的getItem()获取调用库不得自行new实例化且不应假设一个实现库创建的条目能与另一个实现库的 Pool 兼容get()在isHit()返回false时必须返回null但由于null本身是合法缓存值调用方必须用isHit()来区分「命中了一个 null」与「未命中」isHit()与get()之间不得存在竞态条件MUST NOT have a race conditionset()存储的值必须是 PHP 可以序列化的任意类型序列化方式由实现库自行决定过期时间支持两种设置方式expiresAt()指定绝对时间点expiresAfter()指定相对时长整数秒或DateInterval两者都允许显式传入null此时可使用实现库的默认值若不设置则「永久存储或按实现允许的最长时限存储」。异常接口CacheException.php、InvalidArgumentException.php实现库抛出的所有缓存相关异常都必须实现CacheException任何非法参数都必须抛出实现了InvalidArgumentException的异常类。四、1.0.12016-08-06把 phpdoc 打磨到规范级1.0.1 是一次纯粹的「修复」版本CHANGELOG 记录了四条全部围绕文档注释phpdoc / docblock的修正注释间距一致化统一 phpdoc 注解中的空格风格对应 php-fig/cache#9贡献者 chalasr语法修正修正 phpdoc 注解中的语法问题php-fig/cache#10chalasr参数类型细化为string[]getItems()与deleteItems()的 docblock 从宽泛的array明确为「字符串数组string[]」php-fig/cache#8GrahamCampbellnull参数合法性说明为expiresAt()与expiresAfter()补充 docblock明确null与DateTimeInterface实现同样都是合法参数php-fig/cache#7GrahamCampbell。这一版的本质意义在于把「规范允许什么」在文档层面讲清楚。其中第 3、4 条尤其重要——string[]的精确化后来在 2.0.0 中被升级为真正的array $keys参数类型声明而null与DateTimeInterface的合法性说明也直接预告了 2.0.0 中?\DateTimeInterface参数类型的出现。可以说1.0.1 是 2.0.0 强类型化改造的「文档先行版」。五、2.0.02021-02-04PHP 8 强类型化一次彻底的破坏性升级2.0.0 被标记为BREAKING破坏性变更共四条变更条条都直接改写接口签名①expiresAt()的$expiration参数类型声明为DateTimeInterfaceCHANGELOG 注明这一改动的依据是 PSR-6 规范元文档Meta Document第 82 节关于「类型补充type additions」的讨论。落到源码上即 CacheItemInterface.php 中的签名public function expiresAt(?\DateTimeInterface $expiration): static;参数从无类型变为?\DateTimeInterface同时保留null的合法语义?前缀即可空联合。这一约束把「绝对过期时间必须是时间对象」从口头约定变成了编译器强制。② 所有方法都拥有类型化参数typed parameters这是对整个接口族的系统改造。对照当前源码可以看到每个参数都有了明确的标量/对象类型Pool 侧getItem(string $key)、getItems(array $keys [])、hasItem(string $key)、deleteItem(string $key)、deleteItems(array $keys)、save(CacheItemInterface $item)、saveDeferred(CacheItemInterface $item)Item 侧set(mixed $value)、expiresAt(?\DateTimeInterface $expiration)、expiresAfter(int|\DateInterval|null $time)。其中int|\DateInterval|null是典型的 PHP 8.0 联合类型union type用法——整数按秒解释为相对时长DateInterval按实际时间跨度解释null则回退到默认值。这也解释了为什么 2.0.0 必须把最低 PHP 版本抬到 8.0。③Psr\Cache\CacheException继承Throwable源码中 CacheException.php 的声明是interface CacheException extends \Throwable { }在此之前缓存异常接口并不直接挂在 PHP 的异常体系根上。继承Throwable之后所有实现了CacheException的异常都成为Throwable家族的一员调用方可以用catch (\Throwable $e)统一兜底捕获或对缓存异常做专门的catch (CacheException $e)处理错误处理的确定性大幅提升。④ 最低 PHP 版本提升到 8.0.0与 composer.json 中的php: 8.0.0一致。前三条变更联合类型、可空类型声明、mixed类型恰好都依赖 PHP 8.0 的类型系统新特性版本门槛的提升是水到渠成的结果。六、3.0.02021-02-04返回类型全覆盖3.0.0 与 2.0.0 同日发布变更同样标记为BREAKING内容只有一条但覆盖面极广所有方法均声明返回类型All methods have return types。这意味着在 2.0.0 完成参数类型化之后3.0.0 又把返回值一侧全部补全。对照当前源码全部 15 个方法的返回类型如下Item 侧CacheItemInterface.phpgetKey(): string、get(): mixed、isHit(): bool、set(mixed $value): static、expiresAt(?\DateTimeInterface $expiration): static、expiresAfter(int|\DateInterval|null $time): staticPool 侧CacheItemPoolInterface.phpgetItem(string $key): CacheItemInterface、getItems(array $keys []): iterable、hasItem(string $key): bool、clear(): bool、deleteItem(string $key): bool、deleteItems(array $keys): bool、save(CacheItemInterface $item): bool、saveDeferred(CacheItemInterface $item): bool、commit(): bool。其中两个返回类型尤其值得展开static返回类型set()、expiresAt()、expiresAfter()声明返回static意味着实现库必须返回「自身类型的实例」这让链式调用成为接口层面的正式承诺例如$item-set($value)-expiresAfter(300)iterablestring, CacheItemInterfacegetItems()的返回类型是键为字符串、值为条目的可遍历集合这既允许实现方返回数组也允许返回生成器generator给实现留下了充分的灵活空间。至此接口签名实现了「参数类型 返回类型」的全覆盖PHP 8.0 的类型系统能力被完整应用到了这套 2015 年定型的契约之上。七、从变更日志到源码验证演进终态把 CHANGELOG 的三次版本变更映射到当前源码可以完整还原演进终态。下表汇总了 src/ 下全部接口在 3.0.0 形态下的签名与语义要点同时也是本文所有结论的直接证据CacheItemInterface缓存条目6 个方法方法签名语义要点getKey(): string返回条目关联的缓存键get(): mixed返回缓存值isHit()为false时返回nullisHit(): bool区分「命中 null 值」与「未命中」与get()无竞态set(mixed $value): static存储可序列化值返回自身支持链式调用expiresAt(?\DateTimeInterface $expiration): static设置绝对过期时间点null走默认值expiresAfter(int|\DateInterval|null $time): static设置相对过期时长整数按秒计CacheItemPoolInterface缓存池9 个方法方法签名语义要点getItem(string $key): CacheItemInterface永远返回条目对象miss 也不返回nullgetItems(array $keys []): iterable按键返回条目集合空数组返回空集合hasItem(string $key): bool检查存在性允许跳过值读取clear(): bool清空整个池deleteItem(string $key): bool删除单个条目deleteItems(array $keys): bool批量删除save(CacheItemInterface $item): bool立即持久化条目saveDeferred(CacheItemInterface $item): bool将条目放入延迟持久化队列commit(): bool一次性提交所有延迟条目异常接口2 个CacheException extends \Throwable实现方所有异常的总接口InvalidArgumentException extends CacheException非法参数专用Pool 的各键参数方法遇到非法键时必须抛出实现它的异常。八、面向实现方与调用方的升级指南综合 CHANGELOG 与源码可以得出对两类使用者的明确指引。如果你是实现方Implementing Library最低环境要求PHP 8.0.0见 composer.json必须实现全部 15 个方法并严格遵循 2.0.0 / 3.0.0 规定的参数类型与返回类型例如set()必须返回static、expiresAfter()必须接受int|\DateInterval|null所有抛出的异常必须实现CacheException非法键必须抛InvalidArgumentException你的包应在composer.json中声明provide: {psr/cache-implementation: ...}以便调用方通过 Packagist 的提供者列表发现你README 中提到的实现列表即位于 Packagist破坏性变更提醒若你的实现基于 1.x 编写get()的返回值、expiresAt()的参数等签名都必须按新接口重写。如果你是调用方Calling Library通过 Composer 安装接口包composer require psr/cache面向接口编程只依赖CacheItemPoolInterface由容器或工厂注入任意符合 PSR-6 的实现遵循契约使用避免踩坑。一个符合全部接口语义的典型读写流程如下use Psr\Cache\CacheItemPoolInterface; function fetchUser(CacheItemPoolInterface $pool, int $id): array { $key user. . $id; $item $pool-getItem($key); // 未命中时也返回条目对象不会返回 null if (!$item-isHit()) { // 用 isHit() 区分「未命中」与「命中 null」 $value loadFromDb($id); $item-set($value)-expiresAfter(300); // 链式调用set 返回 static $pool-save($item); return $value; } return $item-get(); }代码中的三个关键点——getItem()永不返回 null、用isHit()判断命中、set()返回static支持链式——分别对应 1.0.0 定型的语义、3.0.0 返回类型和 2.0.0/3.0.0 的类型化改造是整个版本演进成果在应用层的直接体现。九、总结回顾 psr/cache 的版本轨迹可以看到一条清晰的演进主线1.0.0 完成契约定型1.0.1 完成文档打磨2.0.0 借 PHP 8.0 完成参数强类型化3.0.0 补齐返回类型实现签名全覆盖。CHANGELOG 中每次标注 BREAKING 的变更都能在 src/ 的接口签名中找到对应证据而expiresAt()的参数类型、CacheException extends \Throwable、static返回类型等细节则是调用方与实现方都必须严格遵守的兼容性边界。对于今天的 PHP 8 项目而言理解这份变更日志就等于理解了 PSR-6 缓存接口的全部权威约束。赞分享后端【免费下载链接】cache项目地址https://gitcode.com/gh_mirrors/cac/cache点击查看免费下载相关推荐深入解读 PSR-6 缓存接口标准ShowDoc 中的 psr/cache 包源码解析深入解读 PSR 6 缓存接口标准ShowDoc 中的 psr/cache 包源码解析 PSR 6PHP Standards Recommendation文档知识库后端前端Moodle 内置 PSR-6 缓存接口解析psr/cache 1.0.x 变更记录、接口规范与仓库集成实践Moodle 内置 PSR 6 缓存接口解析psr/cache 1.0.x 变更记录、接口规范与仓库集成实践 本文围绕 Moodle 仓库内置的第三方库 ps教育后端前端Symfony Cache 组件解析从 PSR-6 到 PSR-16 与标签缓存的生产级实践指南Symfony Cache 组件解析从 PSR 6 到 PSR 16 与标签缓存的生产级实践指南 导读 Symfony Cache 组件是 Symfony 官后端Web框架上一篇OpenCore Legacy Patcher为旧款Mac带来新生的终极指南下一篇ES8389三步集成xiaozhi-esp32创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑