惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Archives - TechRepublic
Security Archives - TechRepublic
Project Zero
Project Zero
K
Kaspersky official blog
G
Google Developers Blog
T
Threat Research - Cisco Blogs
T
The Blog of Author Tim Ferriss
Cyberwarzone
Cyberwarzone
Y
Y Combinator Blog
Recorded Future
Recorded Future
Blog — PlanetScale
Blog — PlanetScale
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cisco Talos Blog
Cisco Talos Blog
Latest news
Latest news
Microsoft Security Blog
Microsoft Security Blog
H
Help Net Security
S
Schneier on Security
P
Palo Alto Networks Blog
H
Hacker News: Front Page
N
News and Events Feed by Topic
N
Netflix TechBlog - Medium
博客园 - Franky
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
SecWiki News
SecWiki News
Cloudbric
Cloudbric
TaoSecurity Blog
TaoSecurity Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The Hacker News
The Hacker News
C
Check Point Blog
L
LangChain Blog
腾讯CDC
小众软件
小众软件
T
Tenable Blog
Google DeepMind News
Google DeepMind News
GbyAI
GbyAI
L
LINUX DO - 最新话题
A
About on SuperTechFans
Google Online Security Blog
Google Online Security Blog
C
Cisco Blogs
Recent Announcements
Recent Announcements
Hacker News: Ask HN
Hacker News: Ask HN
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Vercel News
Vercel News
雷峰网
雷峰网
美团技术团队
D
DataBreaches.Net
Martin Fowler
Martin Fowler
Help Net Security
Help Net Security
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
F
Full Disclosure
博客园_首页

博客园_首页

Linux实操--组管理、权限管理和定时任务 Java + EasyExcel 实现单个接口导出多个Excel Mem0 源码解析系列(二):提示词工程的深度剖析 Openclaw TaskFlow究竟是什么?和普通Skill技能有什么区别 博文阅读密码验证 - 博客园 嘉立创开源:应该是全网MicroPython教程最多的开发板 Hermes Agent 集成实践:从协议到生产 2026年AI编程工具横评:Cursor、Codex、Claude Code、Zed、Windsurf Java程序员必看的RAG入门教程 2026 AI效率神器:Superpowers + Claude Code 保姆级教程 本地大模型部署全攻略:从 0 到 1 玩转 Ollama 【从0到1构建一个ClaudeAgent】内存管理-上下文压缩 .NET 高级开发 | 设计、实现一个事件总线框架 电子小白入门之NE555 3. WorkBuddy:隐藏玩法,一键召唤专家,让 AI 以"专家身份"给你干活 和AI一起搞事情#3:Claude Teammate 游戏开发翻车实录 【OpenClaw】通过 Nanobot 源码学习架构---(7)Memory C# .NET 周刊|2026年3月3期 我在 Debian 11 上把 K8s 单机搭起来了,过程没你想的那么顺(/opt 目录版) 深度学习进阶(七)Data-efficient Image Transformer CLI+Skill搭建浏览器AI自动化框架,告别一切重复枯燥任务 告别Token账单无底洞:OpenClaw本地部署,重塑企业数据主权的唯一解 FastAPI+Vue:文件分片上传+秒传+断点续传,这坑我帮你踩平了! SBTI 爆火后,我做了个程序员版的 CBTI。。已开源 + 附开发过程 多模态检索开始进入工程期:用 Sentence Transformers 搭建可落地的 Multimodal RAG 100多行代码实现一个最简单的Agent(用ReAct) Claude Code 通关手册(八):推荐 5 个 Hooks,代码质量提升 3 倍 老板:“有人截图了!”。安全部门:“收到,马上查暗水印!” - why技术 技术之外,皆是人间 C#/.NET/.NET Core技术前沿周刊 | 第 69 期(2026年4.01-4.12) Snack JSONPath 项目架构分析 Claude Code Buddy 小析:一个非核心功能,如何体现产品的细节完成度 AI新时代下的图床管理方案-Cloudflare图床+MCP+Skills方案指南 化繁为简:顺丰速运App如何通过 HarmonyOS SDK实现专业级空间测量 从零实现富文本编辑器#13-React非编辑节点的内容渲染 AI开发-python-langchain框架(3-23-OpenAI Functions风格Tool Calling智能助手) .NET + AI 进阶实战:基于类的技能开发 - 打造可治理的 Agent 能力模块 【从0到1构建一个ClaudeAgent】规划与协调-技能 上周热点回顾(4.6-4.12) 电子小白的工具三件套:面包板、杜邦线、万能板 单表五亿数据的查询优化 | Mysql、StarRocks 2. WorkBuddy:从“我是谁”到“帮我干活” C# 如何减少代码运行时间:7 个实战技巧 基于HelixToolkit.SharpDX 渲染3D模型 - 笺上知微 从零开始的双臂具身VLA起源及现阶段发展综述 - SkyXZ 记对 xonsh shell 的使用, 脚本编写, 迁移及调优 - pluvium27 受够了Vibe Coding的失控?换个起点,让AI事半功倍 从开始配置漏洞环境到漏洞复现流程 - 難しい 关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法 - 虚无境 Any metadata 的内存布局 C# .NET 周刊|2026年3月2期 - InCerry 我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 Skill Discovery | 无监督技能发现的经典工作总结 - MoonOut PbootCMS 网站内容数量多导致访问慢?这些实用优化方案帮你提速! - 家兴网络技术工作室 上下文工程是什么?过时了么?一文讲明白! - 一枫说码 网站漏洞怎么发现并修复?一篇实用指南(附完整流程) - 家兴网络技术工作室 开了 TUN 模式还是直连?90% 的人都踩过这个坑 Github日报|2026年04月12日 - AI一族 AScript扩展多种脚本语言 - rockey627 AI 学习笔记:Agent 的记忆机制 你能被装进一个文件里吗?——7 万人把同事"蒸馏"成了 AI - 我没有三颗心脏 Claude Code 通关手册(七):给 AI 装上技能包——Skills 完全指南 - 暮色之狐 在浏览器中快速编辑代码:VSCode Web 集成实践 - Newbe36524 蒸馏自己 skill?基于 Deepseek 的蒸馏器,丐版蒸馏方式,简单便捷 - To_Carpe_Diem Spring AI Aliababa和AgentScope,哪个更好? - 苏三说技术 Etsy 把 1000 个 MySQL 分片迁进 Vitess:425TB 数据背后的真正问题不是性能,而是运维规模 MicroPython LVGL基础知识和概念:底层渲染与性能优化 - FreakStudio 数据库草图算法 Python 潮流周刊#146:CPython 引入 Rust 的进展 - 豌豆花下猫 最小生成树 - mofei1116 红日靶场七:从外网入口、容器逃逸到 AD 接管的完整利用链复盘 - YouDiscovered1t 分享四款开源且实用的 Kafka 管理工具 - 追逐时光者 vLLM 权重加载机制全解析:从挑战到理想架构 LCT 学习笔记 - ACehomoxue Avalonia UI 12.0.0 正式发布:架构演进和性能飞跃 - 张善友 当 AI Agent 把调用链拉长,延迟开始成为一门生意 conhost.exe 无法显示 U+2717 - 145a 太秀了,我把自己蒸馏成了 Skill!已开源 - 程序员鱼皮 ASP.NET Core 内存缓存实战:一篇搞懂该怎么配、怎么避坑 基于 Ghostty 带有分割标签页和为 Claude 编程设计的通知终端 - BugShare AI 焊死入口:教育的“操作系统级”重塑 - 郝hai 初级Java开发工程师使用sql脚本编写代码的过程是简单而且不糊涂 - CoderOilStation Claude Code通关手册(六):MCP协议完全指南 - 暮色之狐 边框灯光环绕动画特效实现指南 - Newbe36524 开源:子木蒸馏版的 SEO 审计工具 seo-audit-skill v1.0 我所理解的Python元模型 【从0到1构建一个ClaudeAgent】规划与协调-TodoWrite - 程序员Seven Claude 和 Codex 在审计 Skill 上性能差异探究 - ACai_sec AScript如何实现中文脚本引擎 - rockey627 【渗透测试】HTB Season10 Garfield 全过程wp - dynasty_chenzi Android 开发者为什么必须掌握 AI 能力?端侧视角下的技术变革 树状数组正确性证明 - AC-wyr 你的 AI 焦虑,可能比 AI 本身更危险——ATM 机没有消灭银行柜员,但恐慌消灭了你的判断力 - 我没有三颗心脏 一个拉胯的分库分表方案有多绝望?整个部门都在救火! - 冰河团队 动态规划入门必学之走方格问题 - Ofnoname PostgREST 与 PostgreSQL 角色权限配置全解析(生产级实践) - SheepDog1998 使用 UEFI 图形输出协议 GOP 在屏幕上显示图像的方法 - 阿源- Claude Code通关手册(五):组建你的AI专家团队,子代理系统 - 暮色之狐 一个程序员到架构师的催婚路之感悟(整整10年后的催婚相亲感悟) - MisterLip 用 Agent Skill 自动生成工作周报 - 赵康
PHP 泛型之殇 泛型 RFC 提案被拒绝
JaguarJack · 2026-06-19 · via 博客园_首页

PHP 泛型之殇 泛型 RFC 提案被拒绝

PHP 开发者眼中的泛型现实

PHP 很可能不会迎来泛型。这并非什么新鲜事。一些核心开发者撰写了详尽的技术博客,阐述为什么运行时擦除式泛型不是个好主意,以及他们为何对当前的 RFC 投下反对票。

然而,PHP 社区中还有另一群人,他们非常支持这个 RFC,也希望表达自己的观点。有些人没有合适的平台来发声,因此本文想给另一方一个讲述自己故事的机会。以下内容来自那些在日常开发中实际使用泛型、并将静态分析作为 PHP 核心实践之一的开发者们。他们想分享自己的真实想法。

来自 Symfony 核心维护者 Nicolas Grekas

关于 PHP 泛型已有大量详尽的前期研究。结论十分明确:PHP 引擎无法高效实现泛型(挑战包括类型推导不能破坏开发者体验、性能不能增加运行成本等众多方面)。唯一可行的方案是提前静态分析。梦想在 PHP 自身内核中内置一个用 C 编写的静态分析器固然美好,但并不现实:PHP 静态分析工具之所以用 PHP 开发,自有其道理。这种方式允许快速迭代,由精通该语言的人来推进。将这种经验迁移到引擎侧,将会把那些真正让 PHP 静态分析成为现实的人排斥在外,这对社区来说将是一个巨大的损失。

提案中的擦除式泛型正是这条道路的延续,而这条路已被证明是可行且有用的。得益于 IDE,PHP 静态分析的用户基础远比 phpstan、psalm 等工具的活跃用户广泛得多。在 LLM 生成代码的时代,PHP 拥有更强验证环节的必要性更加凸显。静态分析工具如今已成为开发流程中不可或缺的一部分。多年来,社区一直在等待和憧憬泛型的一点一点推进,甚至连泛型数组都曾因过于困难而被否决。等待的时间已经足够长,足以得出一个结论:擦除式泛型是唯一现实的进步方向。当然,如果事实证明判断有误,那也会是一件令人高兴的事。几年之后(如果那时人们和 LLM 还在写 PHP 的话)再看分晓。

来自 Tempest 核心开发者、全职 PHP 开发者 Márk Magyar

首先,需要坦诚地说:如果这个 RFC 未能通过,他会感到极度失望。但先从最没有争议的地方说起——多年来,他一直在 PHP 中使用泛型,事实上大多数 PHP 开发者也是如此。

如果曾经打开过任何一个 Laravel、Doctrine、Symfony、PHPUnit 或 PSL 类,就一定会看到 @template 注解。它在 GitHub 上出现在超过 20.2 万个文件中。这是生态系统中每一个严肃的集合、仓库和结果类型的自我描述方式。社区使用擦除式泛型——即静态分析器检查而引擎忽略的类型——已经将近十年。因此,当有人把这个 RFC 说得像某种新奇的外来事物时,会让人感到有些困惑。Bound-Erased Generic Types RFC 实际上唯一做的事情,就是不再让开发者把这些泛型写在注释里,假装它们不算数。

这种注释开销是真实存在的。想想看,一个泛型 Laravel 类今天长什么样。它同时用两种语言编写:签名里的 PHP 类型,以及紧随其上的 docblock 中的 PHPDoc 类型。解析器验证前者,却默默信任后者。重构时重命名一个属性,注释就悄悄过时了。ReflectionClass::getName() 返回的是 Collection,而不是 Collection<TKey, TModel>。PHPStan、Psalm 和 Mago 对复杂情况的解读各有一些差异,因为根本不存在一个它们可以参照的实际语言标准。

这个 RFC 以零运行时成本解决了所有这些问题。然而在撰写本文时,它的投票结果是 4 票赞成 / 12 票反对 / 3 票弃权。想谈谈这背后的原因,因为这才是真正的悲剧所在,而且比"核心团队讨厌泛型"更令人沮丧。事实并非如此。真正的原因比这更糟糕。

"但原生语法不应该撒谎"

反对这个 RFC 的最强论点并不愚蠢,因此不会试图硬碰硬。Rowan Tommins 在邮件列表中说得最好:

但目前,PHP 的原生语法不会撒谎——标记为 "private" 的属性确实是私有的,返回类型标记为 "int" 的确实总是整型……这个提案将从根本上改变这一点——它将引入一种看起来像是标准强制类型系统一部分的语法,但在很多情况下却完全不起作用。

Derick Rethans 从经验出发表示赞同,称用户"在发现这些类型不会被强制检查时,几乎无一例外地感到困惑"。Tim Düsterhus 进一步指出:静态分析器"只能证明错误的存在,无法证明错误的不存在"——他说的没错,不实际运行 PHP 程序就无法对其做完整的类型检查。

面对这个论点思考了良久,因为它听起来无懈可击。但是——总有一个但是——这是一个关于纯正性的论点,而 PHP 的类型系统从来就不纯正。运行时已经不会检查数组的元素类型、iterable 的内容、callable 的参数或返回签名,以及 mixed 内部任何类型。PHPStan 的作者、也是第一个在 PHP 中引入 docblock 泛型的人 Ondřej Mirtes,在同一个邮件线程中指出,在已发布的 PHP 版本中,已经存在一些角落——写了原生类型语法却默默地永远不会被强制检查。所以"原生语法绝对不能撒谎"这条规则,PHP 很久以前就已经打破了,而大家依然愉快地继续写 PHP。Attribute 就是最干净的例子:一个原本只存在于 docblock 中的概念,获得了真正的语法但除了反射之外没有运行时效果,而社区非常喜爱它们。

"用户会感到困惑"这个担忧其实根本站不住脚,因为十年时间足以让这个担忧成为现实,但它并没有。Azjezz 的回应是值得被铭记的一段话:

其核心前提是可以用经验测试的,而这个测试已经运行过了:PHP 在 docblock 中使用泛型已经十年,并被所有主流框架所采用……你所描述的那种失败模式,在当前系统下本应是最容易发生的,但它并没有发生。

而这背后的原因简单到几乎乏味。那些在乎到会写 Collection<User> 的人,正是那些会运行静态分析工具的人。"使用泛型"和"不运行任何检查工具"之间的重叠,在实践中几乎为零。当然,Gina Banyard 质疑乐观的"90% 项目使用静态分析"的说法是有道理的——JetBrains 的调查显示这个数字接近 44%——不打算否认这一点。但这 44% 恰恰就是那些会使用泛型的人群。没有人会在整个代码库中手写 <TKey, TModel> 注解,然后什么工具都不运行。

他们在等待一套行不通的运行时泛型

那么,如果反对意见实际上站不住脚,为什么会有 12 张反对票?因为大多数反对者仍然在等待具象化泛型——在运行时检查的类型——他们宁愿什么都没有,也不愿现在接受擦除式泛型。

在这一点上与大多数人意见不同:不想要运行时检查的泛型。不是作为将来的目标,也不是作为擦除式泛型暂时代替的"真正版本"。擦除式就是实际想要的那个模型,因为它零成本,并且和生态系统已有的工作方式一致。不过,先放下个人偏好不谈,因为即使从反对者自己的立场来看,这种坚持也没有道理。PHP 尝试构建运行时泛型已经十年了,却总在同一条路上撞上同一堵墙。Nikita Popov 早在 2020 年就做过原型,并详细阐述了为什么单态化在动态引擎里"行不通"。PHP 基金会在 2024 年重新捡起这项工作,结果当泛型遇到联合类型时,立即遇到了超线性类型检查的问题。到 2025 年,官方路线已经全面退缩到"仅编译时"泛型,new Repository<BlogPost>()、联合类型和类型推导全部被明确标记为"真的真的很难™、真的真的很慢™,或者两者兼有"。而当 Rob Landers 在大约一周内将具象化实现挂载到这个分支上时,测试数据表明泛型密集的代码慢了 30% 到 50%,最坏情况下接近 2 倍。这种开销会通过依赖图向下游传导——任何仅仅依赖某个使用了泛型的库的应用,都要承担这个代价。

这就是灌木丛中的那只鸟。而反对票正在放手手中的那只,只为继续盯着它。他们真正要求的标——在考虑擦除式之前必须先证明具象化泛型不可能——是一个永远无法满足的标准。对于一台没有人有时间、资金或授权去重写的引擎,无法证明一个否定命题。

真正会使用它的人没有投票权

到了某个时刻,这不再像是一个技术裁决,而更像是一个流程失败。讨论由静态分析领域的人主导,他们绝大多数表示支持。投票者则主要是运行时引擎开发者。正如 Psalm 的作者 Matthew Brown 所说,"这两类人之间的重叠并不多"。那些每天都会使用这个特性的人没有投票权;那些永远不会写 Collection<User> 的人却有。

Brown 不仅在 Reddit 上说过。在 internals 邮件列表的讨论中,他告诉开发者们"2004 年做出的决定不应该主导今天的决策":运行时检查在当年没有更好方案时有意义,但如今静态分析能比运行时发现更多错误,更早、更快。这个人编写了整个生态系统所依赖的两个工具之一,而他的名字却不在投票名单里。一个被开发者们期盼了十年的特性正在消亡,因为会用的人不是做决定的人。就连劝说 Azjezz 推迟投票的 Larry Garfield 也是因为这个原因——用他的话说,"核心团队否决泛型,对每一个关心 PHP 的人来说,都是最糟糕的结果"。他说得对。而这件事很可能还是会照常发生。

也应当给反对派应有的评价,因为并不认为这个 RFC 是完美无缺的。它并不是一个完全干净的擦除模型。它确实存在编译时和链接时的执行缺口,而且担心它的发布可能会给未来的具象化设计带来更棘手的破坏性变化——这个担忧是合理的,不是 FUD。但投赞成票的 Nicolas Grekas 指出了真正重要的事情:docblock 泛型之所以可被采纳,正是因为它们对引擎不可见;而原生的 <T> 可以遵循同样的渐进路径——PHP 在返回类型、可空参数以及其他所有特性上已经走过了这条路。

所以,并不对投票失败感到惊讶。只是对这种局面感到厌倦。PHP 本可以拥有泛型。它每天都在运行泛型,依托于每一个我们所依赖的框架。而它恰恰正在拒绝这些泛型,只为等待一个它花了十年证明自己无法构建的版本。这才是悲剧。不是灌木丛中的鸟难以捕捉,而是我们一再放手手中的那只,只为站在那里盯着它看。说实话,这真的很可悲。

来自 RFC 作者 Azjezz

作为 RFC 的作者,询问 Azjezz 是否愿意发表意见。他表示没有时间撰写一篇措辞优美的博文,但确实想参与,并允许从他在 Reddit 上的一篇近期评论中引用内容。在那篇评论中,他解释了为什么在投票很可能失败的情况下仍然开启了投票。Azjezz 解释说,讨论的焦点已经从 RFC 本身(关于运行时忽略泛型)转向了另一种诉求——人们想要具象化(运行时检查)泛型。他解释道:

第二类情况值得坦诚面对。原则上不反对具象化泛型。如果它们在今天的 PHP 中可行,也更愿意选择它们。没有将 RFC 转向具象化的原因是,"设计得更好"并不是问题所在。Rob Landers 在大约一周内在这个分支上实现了具象化泛型,测试数据表明泛型密集的代码慢了 30%–50%,最坏情况下接近 2 倍。

这种开销会通过依赖图不断累积。如果 Psl(或 Symfony、PHPUnit、Laravel、Doctrine 等)在具象化模型下发布了原生泛型,每一个下游应用都要为此买单,即使那些从未声明过自己的泛型的应用也无法幸免。把这个成本放到 CI 上,10 分钟的构建会变成 15 到 20 分钟,蔓延到整个生态系统。这样的数据,人们同样不会投赞成票。

关于为什么 Azjezz 在未进一步探索在 RFC 之上添加具象化泛型的可能性就提前开启投票,他这样回答:

老实说:不会把时间花在具象化泛型上,因为在他看来,它们不会发生。不是因为不想要它们——他确实想要。要使它们在 PHP 中达到可以正式发布的性能水平,需要对引擎进行结构性改造,而他既没有时间、自由,也没有这个授权去做。他只是一个利用业余时间、在各项事务间隙中工作的个人。要求他重写 PHP 引擎以使具象化泛型可行,并在这个过程中破坏现有功能,这并不是一个现实的请求。而在没有这种重写的情况下发布具象化 RFC,只会让现状走到 Rob 的分支已经到达的地方:一个可以工作但性能表现令社区无法接受的实现。

如果具象化泛型有一天在 PHP 中变得可行,那一定是因为某个有时间、有资源、有引擎层面授权的人开辟了那条道路。一旦这种情况发生,也会很乐意支持后续的 RFC。在那之前,"静态分析收敛性是否值得发布边界擦除式泛型"才是选票上真正的问题。

来自 Laravel 高级软件工程师 Nuno Maduro

自 PHPStan 问世以来,Nuno 几乎在其所有代码中通过 PHPStan 使用泛型。到了今天,这感觉像是任何现代语言的必备特性。如果 PHP 想继续朝着这个方向前进,它需要泛型。

来自 JetBrains PHP 开发者倡导者 Brent Roose

信不信由你,但 Brent 对最近的 RFC 正在失败这件事并没有那么在意。他也希望它能通过,但泛型在大局上并不会带来本质区别。那个"大局"要重要得多,如果说有什么意义的话,泛型 RFC 反而凸显了 PHP 在这个方面的失败。

无论人们是否愿意接受,PHP 不仅仅是解释器,也不仅仅是语法。PHP 之所以有今天的地位,不是因为语言本身有多优美,而是因为它拥有丰富的生态系统。PHP 不仅仅是一门编程语言,如果没有框架、包和工具构成的生态系统,它很可能早已不复存在。

与此同时,大约 100 人组成的一个群体正在决定这门语言的未来(严格来说,大约有 2000 人有资格投票,但大多数人已经不再参与了——这本身就很令人震惊)。没有领导者或实体来设定愿景,而这个群体内部严重分裂——例如,他们会花费数周争论是否应该从官网上移除一个 X 链接。

有人说,缺乏统一的愿景和方向正是 PHP 的伟大之处,但 Brent 认为这正在严重拖累 PHP。那些还没有使用 PHP 的公司,为什么会选择一门设计权不属于任何人的语言?在这个体系中,唯一的受薪实体随时可能因为一小群人的反对而被阻止前进?而这个群体几乎没有任何来自真正驱动 PHP 发展的最大生态系统——如 Laravel、Symfony、WordPress 或 Packagist——的代表。

在 Brent 看来,这就是泛型 RFC 以及在此之前许多 RFC 所揭示的失败。过去曾有人试图改变这个体系,但徒劳无功。委员会似乎对现状感到满意,并不希望流程发生改变。

不过,Brent 仍然抱有希望。PHP 在过去也曾经历过同样缺乏方向和愿景的阶段。之后也出现过语言大步向前的时期——比如早期的 Zend 时代;然后是 PHP 7.0 重写时 Hack 语言步步紧逼;再后来是 Nikita 在 7.x 后期和 8.x 初期推动语言向前发展。最近似乎再次失去了方向,但 Brent 也乐观地认为,合适的人或实体最终会出现。

如果这意味着暂时无法拥有泛型,那也没关系。优秀的开发者们会继续使用 PHP,在没有泛型的情况下构建出出色的产品。