#[\nodiscard] 是供静态分析工具识别的语义提示,php 解释器完全忽略;需 php 8.3+、工具版本达标(phpstan ≥1.10.3、psalm ≥5.15)、启用对应规则且函数有明确返回类型才能生效。
![php8.5#[nodiscard]怎么用_php8.5返回值必须使用特性示例](https://img.php.cn/upload/article/001/503/042/177294460733275.jpg)
PHP 8.5 的 #[\nodiscard] 不是强制检查机制
它只是给静态分析工具(比如 PHPStan、Psalm)和 IDE 提供语义提示,告诉它们“这个函数的返回值被忽略时,应该报警告”。PHP 解释器本身完全不干预——代码照常运行,不会报错、不会警告、也不会抛异常。
常见错误现象:#[\nodiscard] 加了但 IDE 没反应,或 PHPStan 完全不报错。原因通常是:没装对应扩展、没配规则、或者用了不支持该属性的旧版本工具。
- PHPStan 需要 v1.10.3+,且启用
checkReturnValues规则(默认开启) - Psalm 需要 v5.15+,并确保
checkForUnnecessaryVarAssignments或相关返回值检查未被禁用 - VS Code + intelephense 目前(v1.9.x)仍不识别该属性,别指望它标黄
怎么给函数加 #[\nodiscard] 才生效
必须加在函数声明前,且函数要有明确返回类型声明(: void 除外,但 void 本身就不该被忽略,所以一般不标)。
使用场景:你写的工具函数、构造器、链式调用起点、状态判断函数等——返回值一旦被忽略,大概率意味着逻辑遗漏。
立即学习“PHP免费学习笔记(深入)”;
#[\nodiscard]
function findUser(int $id): ?User
{
return User::findById($id);
}
// ✅ 正确用法:显式接收或使用返回值
$user = findUser(123);
if ($user !== null) { ... }
// ❌ 静态分析会警告:返回值被忽略
findUser(123); // Warning: Return value of findUser() is not used
- 不能加在方法内部、闭包、匿名函数上
- 不支持继承自动传递:父类方法标了,子类重写后需重新标注
- 如果函数可能返回
mixed或没写返回类型,大多数分析工具会直接跳过检查
#[\nodiscard] 和 void 的区别别搞混
void 表示“不该有返回值”,调用时加括号就完事;#[\nodiscard] 表示“有返回值,但你不该扔着不管”。两者语义相反,混用会误导协作者。
性能 / 兼容性影响:零影响。属性在运行时被忽略,不参与 opcode 生成,也不增加内存开销。
- 写
function foo(): void { ... }后再加#[\nodiscard]—— PHP 会报语法错误 - 返回
bool的校验函数(如isValidEmail())非常适合加该属性,避免写成isValidEmail($s);却没接结果 - 链式调用中返回
$this的方法(如 Laravel 的where())也适合标,防止漏掉最终get()或first()
为什么你的项目里加了却没效果
最常被忽略的是工具链配置和 PHP 版本边界。PHP 8.5 尚未发布(截至 2024 年中仍是开发中版本),目前所有 #[\nodiscard] 实际依赖的是 PHP 8.3+ 的自定义属性机制 + 工具端支持,不是 PHP 自身执行期特性。
容易踩的坑:
- 误以为
php -l或php --syntax-check会报#[\nodiscard]相关错误 —— 它们根本看不到这个属性 - 在 composer.json 里写了
"php": "^8.5",但本地实际是 8.2 —— 属性语法直接 parse error - 用了 PHPStan 的
baseline文件,把第一次的Return value is not used警告记进去了,后续新增的同类问题就被静默吞掉
真要落地,先确认 php -v 输出 ≥ 8.3,再跑 phpstan analyse 看是否真出警告。没警告?那就不是代码问题,是环境没对齐。











