正規表現のコンパイルエラー
ローカルのdockerでPHP5.2.17環境を用意し、動くことを確認。共用サーバのステージングサイトにデプロイしました。ところがエラーです。
Warning: preg_match() [function.preg-match]: Compilation failed: unrecognized character after (?< at offset 4 in /xxx/yyy/smarty-3.1.34/libs/Smarty.class.php on line 1126
Fatal error: Uncaught --> Smarty: Unable to load config 'file:zzz.conf' <-- thrown in /xxx/yyy/smarty-3.1.34/libs/sysplugins/smarty_template_compiled.php on line 96
Code language: plaintext (plaintext)
調べると、Smarty.class.phpの1122行目で、preg_matchの正規表現の「?<root>」でコンパイルエラーです。名前つきサブパターンを使っていて、一致すると、$parts['root']
や$parts['path']
に入ってきます。
preg_match(
'%^(?<root>(?:[[:alpha:]]:[\\\\/]|/|[\\\\]{2}[[:alpha:]]+|[[:print:]]{2,}:[/]{2}|[\\\\])?)(?<path>(.*))$%u',
$path,
$parts
);
Code language: PHP (php)
ローカルのdockerのPHP5.2.17で動いているので、なぜだろう?
preg_matchの名前つきサブパターン
preg_matchのマニュアルを見ると、
例4 名前つきサブパターンの使用法
https://www.php.net/manual/ja/function.preg-match.php$str = 'foobar: 2008';
preg_match('/(?P<name>\w+): (?P<digit>\d+)/', $str, $matches);
/* PHP 5.2.2 (PCRE 7.0) 以降ではこの形式でも動作しますが、
* 過去との互換性を考慮して上の形式のほうを推奨します */
// preg_match('/(?<name>\w+): (?<digit>\d+)/', $str, $matches);
Pなしの名前つきサブパターンは、PHP 5.2.2 (PCRE 7.0) 以降とあります。
dockerのPHP 5.2.17のphpinfoを確認すると、PCRE Librrary Versionは 8.02.2010-03-19。
共用サーバのPHP 5.2.17のphpinfoを確認すると、PCRE Librrary Versionは 6.6.06-Feb-2006。これが原因ですね。Pなしの名前付きサブパターンの要件 PCRE 7.0以降を満たしていません。
Smarty 3.1.29で動いた
Smarty3のgithubのコミットログを調べました。2016-01-28に該当箇所がコミットされていました。
その前後のリリースを古い順に並べると、3.1.29のリリース、2016-01-28に該当箇所のコミット、そして3.1.30のリリース。
日付 | SHA1 ID | タグ | コメント |
---|---|---|---|
2016-08-08 | ed2b7f1 | 3.1.30 | |
2016-01-28 | 193163b | Pなし名前つきサブパターンのpreg_matchがコミットされた | |
2015-12-21 | 35480f1 | 3.1.29 |
Smarty 3.1.29は、Pなし名前付きサブパターンを使っていないので、今回の共用サーバでも動く可能性が高いと考えました。
Smarty 3.1.29 をダウンロードして、プロジェクトに追加しました。まず、Selenium IDEのテストに合格しました。
次に、共用サーバのステージングサイトにデプロイしたら、動きました。
PHPバージョンだけでなく、(PCREなどの)ライブラリバージョンも重要なことがある、という教訓でした。
PHP 5.3に切り替えたら、Smarty3.1.34も動いたよ
PHP 5.3なら、Smartyの最新バージョンでも動くのかしら?