PHP 8 有一个本地函数来检索实际的错误消息,因此这些辅助函数不再需要。
https://php.net/preg_last_error_msg
<?php
preg_match('/(?:\D+|<\d+>)*[!?]/', 'foobar foobar foobar');
if (preg_last_error() !== PREG_NO_ERROR) {
echo preg_last_error_msg(); // 输出 "回溯限制耗尽"
}
?>
(PHP 5 >= 5.2.0, PHP 7, PHP 8)
preg_last_error — 返回最后一次 PCRE 正则表达式执行的错误代码
返回最后一次 PCRE 正则表达式执行的错误代码。
示例 #1 preg_last_error() 示例
<?php
preg_match('/(?:\D+|<\d+>)*[!?]/', 'foobar foobar foobar');
if (preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR) {
echo '回溯限制已耗尽!';
}
?>
以上示例将输出
Backtrack limit was exhausted!
此函数没有参数。
返回下列常量之一(在其自身页面上解释)
PHP 8 有一个本地函数来检索实际的错误消息,因此这些辅助函数不再需要。
https://php.net/preg_last_error_msg
<?php
preg_match('/(?:\D+|<\d+>)*[!?]/', 'foobar foobar foobar');
if (preg_last_error() !== PREG_NO_ERROR) {
echo preg_last_error_msg(); // 输出 "回溯限制耗尽"
}
?>
在 PHP 5.5 及以上版本中,获取错误消息很简单:
<?php
echo array_flip(get_defined_constants(true)['pcre'])[preg_last_error()];
这是一个更高级的函数,用于将错误代码转换为文本
<?php
function preg_errtxt($errcode)
{
static $errtext;
if (!isset($errtxt))
{
$errtext = array();
$constants = get_defined_constants(true);
foreach ($constants['pcre'] as $c => $n) if (preg_match('/_ERROR$/', $c)) $errtext[$n] = $c;
}
return array_key_exists($errcode, $errtext)? $errtext[$errcode] : NULL;
}
?>
这是对前面一个“获取错误消息”代码片段的更正。它过滤掉了非错误代码,从而阻止了由于 ["PCRE_JIT_SUPPORT"]=>bool(true) 而发出“警告:array_flip(): 只能翻转字符串和整数值!”。
<?php
echo array_flip(array_filter(get_defined_constants(true)['pcre'], function ($value) {
return substr($value, -6) === '_ERROR';
}, ARRAY_FILTER_USE_KEY))[preg_last_error()];
如果您使用 T-Regx 库,要获取最后一个常量,您可以使用
<?php
echo preg_last_error_constant(); // 'PREG_BAD_UTF8_ERROR'
上述函数 pcre_error_deocde [sic] 不正确 -并非所有使用的常量都是错误常量。例如,当错误实际上是 PREG_BAD_UTF8_ERROR 时,该函数会输出 PREG_SPLIT_OFFSET_CAPTURE 的文本。
在 PHP 7.3+ 中,以及取决于环境,可能存在其他不是整数的常量,这将导致 array_flip 出错。我选择使用 RegexException 和 gk 注释上的过滤器。
<?php
class RegexException extends \Exception {
public $errorCode;
public function __construct(
int $errorCode,
string $additionalMessage = null
) {
$this->errorCode = $errorCode;
$errorMessage = $this->getErrorString($errorCode) ?? '未知正则表达式错误';
$additionalMessage = $additionalMessage ? " $additionalMessage" : '';
parent::__construct("抛出正则表达式错误: $errorMessage." . $additionalMessage);
}
/**
* 获取 PCRE 错误代码的错误字符串(常量名)
*
* @param int $errorCode
*
* @return string|null
*/
private function getErrorString(int $errorCode): ?string
{
$pcreConstants = get_defined_constants(true)['pcre'] ?? [];
/*
* 注意:preg_last_error() 返回一个整数,但在 PHP 7.3+ 中,存在字符串、布尔值或其他类型的常量。我们可以安全地过滤掉非整数,以获取相应的错误常量名。
*/
$pcreConstants = array_filter($pcreConstants, function ($code) {
return is_int($code);
});
$errorStrings = array_flip($pcreConstants);
return $errorStrings[$errorCode] ?? null;
}
用法:
throw new RegexException(preg_last_error());
使用此函数前请注意。
我的 php --version
PHP 5.6.29 (cli) (built: 2016年12月8日 09:19:46)
版权所有 (c) 1997-2016 PHP 开发团队
Zend 引擎 v2.6.0,版权所有 (c) 1998-2016 Zend Technologies
在 Linux Fedora 23 4.8.13-100.fc23.x86_64 #1 SMP 2016年12月9日 14:51:40 UTC x86_64 x86_64 x86_64 GNU/Linux 上
<?php
// @see http://stackoverflow.com/questions/4440626/how-can-i-validate-regex
// 返回 true,因为闭合的 ")" 没有对应的开括号 "("
var_dump(preg_match('~InvalidRegular)Expression~', null) === false);
// 这应该与 0 不同,但是……
var_dump(preg_last_error());
?>
补充我之前的说明:在 Unicode 模式(使用 "u" 修饰符)下,PREG_BAD_UTF8_ERROR 仅反映主题字符串中的错误。如果模式本身包含无效字符,preg_match()(或 preg_match_all())将返回 false,但 preg_last_error() 将返回 0,表示 PREG_NO_ERROR。相反,php 会发出警告:“preg_match(): Compilation failed: invalid UTF-8 string at offset 0”
获取文本形式的错误(小更新)
<?php
echo array_flip(array_filter(get_defined_constants(true)['pcre'], function($v) { return is_integer($v); }))[preg_last_error()];