共用サーバのPHP5.2.17で、Smarty3.1.34がエラー

正規表現のコンパイルエラー

ローカルの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 96Code 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 名前つきサブパターンの使用法

$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);

https://www.php.net/manual/ja/function.preg-match.php

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-08ed2b7f13.1.30
2016-01-28193163bPなし名前つきサブパターンのpreg_matchがコミットされた
2015-12-2135480f13.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の最新バージョンでも動くのかしら?

タイトルとURLをコピーしました