PHPstan提示preg_match参数错误,请求解释与修复方案
解决PHPstan对自定义preg_match封装函数的类型警告
问题概述
自定义封装的my_preg_match函数可正常运行,但PHPstan抛出如下警告:
Parameter #4 $flags of function preg_match expects TFlags of 0|256|512|768, int given.
原函数代码:
function my_preg_match( string $pattern, string $subject, array &$matches = null, int $flags = 0, int $offset = 0): bool { $result = preg_match($pattern, $subject, $matches, $flags, $offset); if ($result === 1) { return true; } if ($result === 0) { return false; } throw new Exception(preg_last_error_msg()); }
错误原因
- PHP原生
preg_match的$flags参数并非接受任意整数,仅允许特定值:0(默认)、PREG_OFFSET_CAPTURE(256)、PREG_UNMATCHED_AS_NULL(512),以及这两个常量的组合值768。 - 自定义函数将
$flags声明为宽泛的int类型,PHPstan会判定传入值可能超出合法范围,因此抛出类型不匹配警告。
修复方案
方案1:添加PHPDoc类型约束+运行时校验
通过PHPDoc明确$flags的合法取值范围,同时在函数内添加运行时校验,既满足PHPStan的类型检测,又增强代码健壮性:
/** * @param string $pattern * @param string $subject * @param array|null $matches * @param 0|PREG_OFFSET_CAPTURE|PREG_UNMATCHED_AS_NULL|(PREG_OFFSET_CAPTURE|PREG_UNMATCHED_AS_NULL) $flags * @param int $offset * @return bool * @throws Exception * @throws InvalidArgumentException */ function my_preg_match( string $pattern, string $subject, array &$matches = null, int $flags = 0, int $offset = 0): bool { // 校验flags合法性 $allowedFlags = [ 0, PREG_OFFSET_CAPTURE, PREG_UNMATCHED_AS_NULL, PREG_OFFSET_CAPTURE | PREG_UNMATCHED_AS_NULL ]; if (!in_array($flags, $allowedFlags, true)) { throw new InvalidArgumentException('传入的preg_match flags参数非法'); } $result = preg_match($pattern, $subject, $matches, $flags, $offset); if ($result === 1) { return true; } if ($result === 0) { return false; } throw new Exception(preg_last_error_msg()); }
方案2:使用PHPStan的专用类型(需PHPStan支持)
如果项目已引入PHPStan的扩展类型定义,可直接将$flags的类型声明替换为TFlags:
function my_preg_match( string $pattern, string $subject, array &$matches = null, TFlags $flags = 0, int $offset = 0): bool { $result = preg_match($pattern, $subject, $matches, $flags, $offset); if ($result === 1) { return true; } if ($result === 0) { return false; } throw new Exception(preg_last_error_msg()); }
两种方案中,方案1无需依赖额外扩展,兼容性更强,同时添加的运行时校验能在实际执行时拦截非法参数,更安全。
内容的提问来源于stack exchange,提问作者Yevgeniy Afanasyev
相关产品推荐
相关产品推荐

