PHPStan 纯函数错误标识符 `pureFunction.parameterByRef` 全解析:引用参数与纯度契约冲突 开发工具代码质量静态分析【免费下载链接】phpstanPHP Static Analysis Tool - discover bugs in your code without running it!项目地址https://gitcode.com/gh_mirrors/ph/phpstan点击查看免费下载导读pureFunction.parameterByRef是 PHPStan 在 2.0 起全面强制执行phpstan-pure注解后新增的一类错误标识符当函数被声明为纯函数却带有按引用传递by-reference的参数时PHPStan 会报告此错误。本文以此错误标识符为核心先给出触发它的最小代码示例再从 PHP 语言语义与 PHPStan 纯度模型两个层面解释为什么引用参数与纯度天然冲突最后提供完整的修复路径——包括移除引用改返回值、移除纯度注解、在phpstan.neon中用ignoreErrors按标识符豁免等实战方案。读完本文你将能准确理解 PHPStan 的纯度分析模型并能独立排查和修复代码库中所有与pureFunction.parameterByRef以及同源的pureMethod.parameterByRef、purePropertyHook.parameterByRef相关的报错。错误标识符概览pureFunction.parameterByRef属于 PHPStan 1.11 引入的**错误标识符error identifiers**体系。这套标识符采用category.subtype的两段式命名用于给 PHPStan 报告的错误打上稳定、可检索的标签方便按类别忽略错误、在文档中索引错误以及在 CI 中做精细化的断言。该标识符的前缀pureFunction表示纯函数相关检查后缀parameterByRef指明具体违规点是参数按引用传递。从仓库的标识符映射表 errorsIdentifiers.json 可以看到pureFunction.parameterByRef并非由单一规则类产生而是由三个规则类共同报告PHPStan\Rules\Pure\PureFunctionRule函数PHPStan\Rules\Pure\PureMethodRule方法PHPStan\Rules\Pure\PurePropertyHookRule属性钩子这三个规则类底层共用同一处实现FunctionPurityCheck.php#L104位于phpstan/phpstan-src的src/Rules/Pure/目录。也就是说函数、方法、属性钩子三种声明位置对按引用参数的纯度检查逻辑是完全一致的本错误文档展示的函数示例同样适用于方法版本 pureMethod.parameterByRef.md。需要说明的是属性钩子property hooksPHP 8.4有一个特殊之处PHP 语言本身不允许钩子参数按引用传递声明会直接触发致命错误Parameter $value of set hook must not be pass-by-reference因此purePropertyHook.parameterByRef实际上不会被真实触发purePropertyHook.parameterByRef.md 明确说明该标识符仅为与函数、方法版本保持命名一致而存在。触发示例最小可复现代码以下代码是 pureFunction.parameterByRef.md 中的最小触发示例?php declare(strict_types 1); /** * phpstan-pure */ function increment(int $value): int // ERROR: Function increment() is marked as pure but parameter $value is passed by reference. { $value; return $value; }运行 PHPStan 后会得到类似如下的报告------ --------------------------------------------------------------- Line increment.php ------ --------------------------------------------------------------- 15 Function increment() is marked as pure but parameter $value is passed by reference. ------ ---------------------------------------------------------------方法版本的触发方式完全一致只是错误文案中的Function换成Method参见 pureMethod.parameterByRef.md?php declare(strict_types 1); class Calculator { /** * phpstan-pure */ public function increment(int $value): int // ERROR: Method Calculator::increment() is marked as pure but parameter $value is passed by reference. { $value; return $value; } }为什么会被报告引用参数意味着允许副作用PHP 语言语义按引用传递本身就是一种修改通道在 PHP 中$value形式的参数意味着调用方传入的是变量的引用而不是值的拷贝。函数内部对$value的任何修改都会直接反映到调用方持有的变量上。这是 PHP 语言层面允许的、影响函数外部状态的最直接通道之一。因此一个带按引用参数的函数即使函数体内部一行都没有写$value ...它也在契约层面上承诺了我有可能修改你的变量。调用方无法在不阅读函数全部实现的情况下确定函数是否真的会修改该变量——这正是副作用最危险的形式不可预测、不可组合。PHPStan 纯度模型契约检查而非行为检查PHPStan 的纯度分析基于声明契约而非逐行行为猜测。正如错误文档 pureFunction.parameterByRef.md 所强调的Even if the function does not actually modify the referenced parameter, the mere presence of a by-reference parameter signals that the functions contract allows mutation, which is incompatible with purity.即即使函数体实际上没有修改引用参数只要参数列表中出现就说明该函数的契约允许变更调用方状态这与纯度定义不兼容。这个设计原则可以在 PHPStan 2.0 的发布说明博客文章Checking truthiness ofphpstan-purewith impure points中找到呼应PHPStan 2.0 开始强制执行phpstan-pure注解任何与纯度相悖的代码结构都会被报告。对每一个语句和表达式PHPStan 都会判断其是否为不纯点impure point而按引用参数会被直接视为潜在的不纯点。纯度定义的三条铁律结合错误文档与 PHPStan 的纯度模型一个被phpstan-pure标记的函数必须同时满足无副作用不修改外部状态全局变量、静态属性、对象属性、引用参数、文件系统、网络等确定性相同输入永远返回相同结果不依赖随机数、时间、数据库等外部可变状态有返回值纯函数必须返回有意义的值void纯函数会触发另一个标识符 pureFunction.void.md。按引用参数直接违反第 1 条因此必然被报告。如何修复两条路径与实战取舍路径一移除引用参数改为返回值推荐如果函数本意就是计算并返回一个新值那么正确的做法是完全去掉让调用方通过返回值获得结果。原文档给出的 diff 修复如下?php declare(strict_types 1); /** * phpstan-pure */ -function increment(int $value): int function increment(int $value): int { - $value; - return $value; return $value 1; }修改后函数完全符合纯度契约不修改任何外部状态相同输入返回相同输出调用方通过$value increment($value);完成递增这一语义。路径二函数确实需要修改调用方变量——移除纯度注解如果业务逻辑确实要求就地修改调用方的变量例如排序、指针式累加、array_multisort风格的函数那么这个函数本质上就是有副作用的不应声称自己是纯函数。此时删除phpstan-pure注解即可?php declare(strict_types 1); -/** - * phpstan-pure - */ function increment(int $value): int { $value; return $value; }删除注解后 PHPStan 不会再针对纯度契约检查该函数。但要注意PHPStan 默认假定返回值非void的函数是纯函数详见后文纯度标签体系一节所以仅仅删除注解、函数仍带参数时PHPStan 的调用方分析仍可能因为引用修改而产生其他与纯度相关的推断差异。最稳妥的做法是如果该函数确实有副作用同时显式加上phpstan-impure注解来明确声明。路径三确认这是误报时用配置按标识符豁免pureFunction.parameterByRef在错误文档 frontmatter 中标明ignorable: true意味着它可以通过配置被忽略。对于函数确实带引用参数、但你确认调用约定安全的少数场景例如为了兼容既有 API 签名、或该引用参数实际上在调用约定中不会被修改可以在phpstan.neon中精确豁免parameters: ignoreErrors: - identifier: pureFunction.parameterByRef用identifier豁免比传统的正则匹配message更精准、更不易误伤这是 PHPStan 1.11 引入错误标识符体系的主要目的之一。若要只豁免指定路径可以配合path:参数限定范围。同类可豁免标识符还包括pureMethod.parameterByRef、pureFunction.void、impureFunction.pure等。提示错误文档规范website/errors/CLAUDE.md明确要求不要在 How to fix it 中直接建议忽略错误详情页已覆盖该话题本文在此给出配置方案仅作工程兜底参考对绝大多数情况优先选择路径一或路径二。关联标识符矩阵引用参数相关的纯度检查pureFunction.parameterByRef并不是引用参数 × 纯度这一组合的唯一检查点。PHPStan 的纯度分析会从多个角度盯住引用错误标识符触发场景对应文档pureFunction.parameterByRef纯函数带按引用参数pureFunction.parameterByRef.mdpureMethod.parameterByRef纯方法带按引用参数pureMethod.parameterByRef.mdpurePropertyHook.parameterByRef纯属性钩子带按引用参数PHP 语法上不可能仅作命名一致性保留purePropertyHook.parameterByRef.mdpossiblyImpure.propertyAssignByRef纯函数/方法体内$ref $this-property创建属性引用possiblyImpure.propertyAssignByRef.mdimpure.propertyAssignByRef同类问题的内部标识实际报告possiblyImpure变体impure.propertyAssignByRef.md其中possiblyImpure.propertyAssignByRef是一个值得注意的表亲它针对的是函数体内创建指向属性/对象成员的引用$ref $this-value;因为后续通过$ref的修改会绕过$this-value直接改动对象状态。其修复方式与本文主题一脉相承——要么去掉改为值拷贝要么移除纯度注解/** - * phpstan-pure */ public function getRef(): int { - $ref $this-value; $ref $this-value; return 1; }纯度标签体系phpstan-pure的完整上下文要真正用好pureFunction.parameterByRef需要理解它所在的纯度标签体系。PHPStan 的文档phpdocs-basics.md与配置参考config-reference.md给出了完整模型默认规则返回非 void 的函数被视为纯函数PHPStan 默认假定所有返回值的函数都是纯的。这带来一个特性在同一个作用域内第二次调用同一个函数时PHPStan 会认为它返回与第一次相同的收窄类型。对于 getter 这类确定性函数这是合理默认但对于依赖随机数、数据库、时间的函数就会产生误判public function getRandomNumber(): int { return rand(); } if ($this-getRandomNumber() 4) { echo $this-getRandomNumber(); // PHPStan 会认为这里也是 4 }显式标签phpstan-pure与phpstan-impurephpstan-impure声明函数有副作用、每次调用结果可能不同。用于纠正上述默认假设例如rand()包装函数。phpstan-pure声明函数无副作用且确定性。在默认假设下这个标签主要用于两类场景一是你设置了rememberPossiblyImpureFunctionValues: false后需要用它恢复纯度声明二是让 PHPStan强制校验纯度契约——这正是本文pureFunction.parameterByRef的检查来源。PHPStan 2.0 起phpstan-pure从声明升级为强制执行函数体内任何不纯点I/O、属性赋值、全局状态访问、调用不纯函数、引用参数等都会被报告。除了pureFunction.parameterByRef同族标识符还包括impure.functionCall/impure.methodCall纯函数调用了不纯的函数/方法impure.echo/impure.print/impure.exit纯函数中产生输出或终止进程impure.global/impure.staticPropertyAccess纯函数访问全局变量或静态属性impure.propertyAssign纯函数修改属性pureFunction.void纯函数返回void无副作用又无返回值调用无意义;impureFunction.pure标记为phpstan-impure但实际没有任何副作用——反向的冗余声明。类级与条件性纯度的扩展标签phpstan-all-methods-impure/phpstan-all-methods-purePHPStan 2.1.39类级声明所有方法默认纯度单个方法可用phpstan-pure/phpstan-impure覆盖pure-unless-callable-is-impurePHPStan 2.2高阶函数纯度取决于传入 callable 的纯度类似array_map的语义。若被标记的 callable 参数本身已是pure-callable类型该标签就变得冗余会触发 pureFunction.redundantUnlessCallable.md。相关配置rememberPossiblyImpureFunctionValues配置项rememberPossiblyImpureFunctionValues默认true控制是否记住可能不纯函数的返回值。如果代码库中有大量未标记的不纯函数可以全局关闭该记忆行为parameters: rememberPossiblyImpureFunctionValues: false关闭后PHPStan 不再对未标记函数做第二次调用返回相同结果的假设此时如果需要为真正的纯函数恢复该优化就依赖phpstan-pure注解——于是phpstan-pure上的纯度校验含pureFunction.parameterByRef也就变得更加重要。源码级佐证这个错误从哪里来本文基于的仓库是 PHPStan 的镜像仓库含 website/ 官网源码与 e2e/ 端到端测试。关于本错误的实现事实如下标识符到规则类的映射定义在 errorsIdentifiers.json明确列出PureFunctionRule、PureMethodRule、PurePropertyHookRule三个规则类三个规则类共同指向的检查实现位于phpstan/phpstan-src仓库的src/Rules/Pure/FunctionPurityCheck.php#L104镜像仓库中未包含phpstan-src源码仅记录了该引用错误文档的生成规范记录在 website/errors/CLAUDE.md每个.md文件由 GitHub Actions 工作流读取errorsIdentifiers.json、再研究对应规则源码与测试夹具后自动生成因此本文档中的示例代码与修复建议有测试代码作支撑错误标识符体系本身的设计初衷记录在 phpstan-1-11-errors-identifiers-phpstan-pro-reboot.mdcategory.subtype两段式命名便于按类别忽略、按规则分组检索phpstan-pure强制执行策略的引入记录在 phpstan-2-0-released-level-10-elephpants.md。小结pureFunction.parameterByRef是 PHPStan 纯度分析在参数传递方式上的关键检查点。它的核心判断依据是契约而非行为只要phpstan-pure函数的签名里出现就破坏了纯度契约无论函数体是否真的修改参数。修复时优先去引用、改返回值其次才是承认副作用、移除注解确属特殊场景时也可用ignoreErrors的identifier键做精确豁免。理解这一标识符也就理解了 PHPStan 从 1.11 的错误标识符体系到 2.0 的纯度强制执行之间一脉相承的分析哲学用可检索、可索引、可配置的错误分类把函数是否纯这一程序性质变成可机械验证的工程约束。赞分享开发工具代码质量静态分析【免费下载链接】phpstanPHP Static Analysis Tool - discover bugs in your code without running it!项目地址https://gitcode.com/gh_mirrors/ph/phpstan点击查看免费下载相关推荐PHPStan 错误标识符 impure.propertyAssignByRef 深度解析按引用赋值如何破坏纯函数纯度契约PHPStan 错误标识符 impure.propertyAssignByRef 深度解析按引用赋值如何破坏纯函数纯度契约 本篇技术指南围绕 PHPStan开发工具代码质量静态分析LibreChat 在 DocumentDB 5.0 以下静默建不了唯一索引OAuth 唯一性失效怎么发现和处理LibreChat 在 DocumentDB 5.0 以下静默建不了唯一索引OAuth 唯一性失效怎么发现和处理 如果你的 LibreChat 部署把 M开发工具代码质量静态分析PHPStan 错误标识符 impure.yield 深度解析纯函数中的生成器与 yield 冲突排查指南PHPStan 错误标识符 impure.yield 深度解析纯函数中的生成器与 yield 冲突排查指南 导读 impure.yield 是 PHPStan开发工具代码质量静态分析上一篇LFM2-1.2B-RAG边缘设备的智能问答革命1.2B参数开启轻量化AI新纪元下一篇EmberFire安全规则配置保护你的Firebase数据不被未授权访问创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考