PHPStan提示Cannot access property on mixed,已验证仍报错求助
PHPStan 报错:无法访问 mixed 类型的属性(已通过自定义函数验证)
代码示例
主逻辑代码
$decodedCredentials = json_decode($credentials, false); if (!$this->isValidCredentials($decodedCredentials)) { return null; } $credential = new Credential(); $credential->username = $decodedCredentials->username; $credential->password = $decodedCredentials->password; $credential->line = $decodedCredentials->line;
验证函数代码
private function isValidCredentials(mixed $credentials): bool { if (!is_object($credentials)) { return false; } return is_object($credentials) && property_exists($credentials, 'username') && property_exists($credentials, 'password') && property_exists($credentials, 'line'); }
PHPStan 报错信息
------ -------------------------------------------- Line Authentication.php ------ -------------------------------------------- :146 Cannot access property $username on mixed. :147 Cannot access property $password on mixed. :148 Cannot access property $line on mixed. ------ --------------------------------------------
问题说明
代码逻辑上已经通过isValidCredentials验证了$decodedCredentials是包含指定属性的对象,但PHPStan仍报错。不想把校验逻辑移到当前函数,询问是否遗漏了配置或这是PHPStan的Bug。
原因与解决方案
这不是PHPStan的Bug,而是静态分析的局限性:PHPStan无法自动追踪自定义函数的返回值与输入参数之间的类型关联,它不知道isValidCredentials返回true时,输入的$credentials一定是包含指定属性的对象。
解决方法是通过类型断言注解明确告知PHPStan验证通过后参数的类型结构:
方案1:给验证函数加注解
修改验证函数的注释,使用PHPStan的断言注解:
/** * @phpstan-assert object{username: mixed, password: mixed, line: mixed} $credentials */ private function isValidCredentials(mixed $credentials): bool { if (!is_object($credentials)) { return false; } return is_object($credentials) && property_exists($credentials, 'username') && property_exists($credentials, 'password') && property_exists($credentials, 'line'); }
方案2:在验证后添加局部类型断言
如果不想修改验证函数,可以在验证通过后,给$decodedCredentials添加局部类型注解:
if (!$this->isValidCredentials($decodedCredentials)) { return null; } /** @var object{username: mixed, password: mixed, line: mixed} $decodedCredentials */ $credential = new Credential(); $credential->username = $decodedCredentials->username; // ... 其他属性赋值
若$username/$password/$line有明确类型(如string),可将mixed替换为对应类型,让类型检查更严格。
内容的提问来源于stack exchange,提问作者CoderJoe
相关产品推荐
相关产品推荐

