Możesz łatwo sprawdzić błędy kompilacji regex w PHP, rejestrując swój własny moduł obsługi błędów. Napisałem tester regex PHP, który wykrywa błędy kompilacji regex i zgłasza je użytkownikowi bez wyświetlania poufnych informacji, takich jak nazwy plików i numery linii. Kluczową częścią jest to, że niestandardowy moduł obsługi błędów może pułapkować błędy kompilacji regex. Nie musisz wyrzucać wyjątku ani go łapać. Reszta to wygodna demonstracja.
Używam set_error_handler(), aby zarejestrować funkcję, która zgłasza wyjątek ErrorException. Przechwytuję wyjątek podczas uruchamiania preg_match(), a następnie używam informacji o śledzeniu do sprawdzenia, czy wyjątek został zgłoszony z tego samego pliku, linii i funkcji, z której uruchamiam preg_match() z (jeśli nie, błąd lub wyjątek został spowodowany przez coś inaczej jak inne wywołanie funkcji w tej samej linii lub brak pamięci w PHP). Następnie wysyłam tylko komunikat o błędzie do użytkownika.
Należy zauważyć, że ten skrypt faktycznie uruchamia funkcję regex za pomocą funkcji zmiennej. Wprowadź dane wejściowe, wyrażenie regularne bez przedniego i końcowego ukośnika oraz dowolne modyfikatory osobno.
Oto pełny kod:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<style type="text/css">
body {
font-family: monospace;
}
input[type=text], textarea {
letter-spacing: .25em;
font-weight: bold;
font-size: larger;
}
textarea {
width: 100%;
height: 25%;
}
fieldset {
display: inline;
}
.error {
color: red;
}
</style>
</head>
<body onload="document.getElementById('patterninput').focus();">
<?php
// Translate old-style PHP errors to OO approach
// http://www.php.net/manual/en/class.errorexception.php
function testRegexErrorHandler($errno, $errstr, $errfile, $errline, $errcontext) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
$pattern = isset($_REQUEST["pattern"]) ? $_REQUEST["pattern"] : "";
$mods = isset($_REQUEST["mods"]) ? $_REQUEST["mods"] : "";
$input = isset($_REQUEST["input"]) ? $_REQUEST["input"] : "";
$regex = "/$pattern/$mods";
$fns = array("match" => "preg_match", "matchall" => "preg_match_all");
$fnKey = isset($_REQUEST["function"]) ? $_REQUEST["function"] : "matchall";
$fn = isset($fns[$fnKey]) ? $fns[$fnKey] : "preg_match_all";
try {
set_error_handler("testRegexErrorHandler");
$result = $fn($regex, $input, $matches);
} catch (Exception $ex) {
// $ex is used later
}
restore_error_handler();
?>
<form action="" method="post">
<input type="text" size="100" id="patterninput" name="pattern" value="<?php echo htmlspecialchars($pattern); ?>" placeholder="Pattern" />
<input type="text" size="10" name="mods" value="<?php echo htmlspecialchars($mods); ?>" placeholder="Modifiers" />
<fieldset><legend>Function</legend>
<label for="fnmatch">preg_match()</label><input type="radio" name="function" value="match" id="fnmatch" <?php echo $fnKey == "match" ? "checked" : ""; ?> />
<label for="fnmatchall">preg_match_all()</label><input type="radio" name="function" value="matchall" id="fnmatchall" <?php echo $fnKey == "matchall" ? "checked" : ""; ?> />
</fieldset>
<input type="submit" name="submit" />
<textarea name="input" rows="10" placeholder="Input"><?php echo htmlspecialchars($input); ?></textarea>
</form>
<br/>
<?php
if(isset($ex)) {
$trace = $ex->getTrace();
if(is_array($trace) && isset($trace[1]) && is_array($trace[1])) {
$errFn = isset($trace[1]["function"]) ? $trace[1]["function"] : "";
$errLine = isset($trace[1]["line"]) ? $trace[1]["line"] : "";
$errFile = isset($trace[1]["file"]) ? $trace[1]["file"] : "";
if($errFn != "" && $errFn == $fn && $errLine != "" && $errLine == $ex->getLine() && $errFile != "" && $errFile == $ex->getFile() && get_class($ex) == "ErrorException") {
$regexErr = true;
}
}
if(empty($regexErr)) {
throw $ex;
} else {
echo "<p class=\"error\">The following error has occurred and is probably an error in your regex syntax:<br/>" .htmlspecialchars($ex->getMessage()) ."</p>\n\n";
}
}
// result will be unset if error or exception thrown by regex function
// such as if expression is syntactically invalid
if(isset($_REQUEST["submit"]) && isset($result)) {
echo "Result: $result<br/>\n";
echo "Matches:<pre>" .htmlspecialchars(print_r($matches, true)) ."</pre>\n\n";
}
?>
</body>
</html>
'error_get_last()' jest wystarczająco dobre :) – NullUserException