こう、適当に正規表現をリテラルに書いちゃったりすると、結構脆弱性の温床になっちゃうじゃないですか。
対策はいろいろ思いつきますが、今回はおてがるに実行なやつから書いていきます。
汎用的なパターンをまとめる
- よいところ
- 似たようなパターンをリテラルでコピペされなくなる
- わるいところ
- 意図しない使われかたをされたり、うっかりパターンに手を入れて処理をぶっこわすことがありうる
クラスにまとめてみる
RegExpPattern.php
<?php
/**
* 汎用的な正規表現をこのクラスに記述する
*/
final class RegExpPattern
{
const DATETIME = '/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/';
const DATE = '/\d{4}-\d{2}-\d{2}/';
}
PHPUnitでテストしてみる
<?php
final class RegExpPatternTest extends TestCase
{
/**
* {@see RegExpPattern} に定義された定数が、最低限不正な表現ではないことを保障
*
* @dataProvider validRegExpProvider
*/
public function testValidRegEx($name, $pattern)
{
$actual = preg_match($pattern, '');
$this->assertNotFalse($actual, '不正な正規表現です');
// 空文字列とマッチするパターンは有り得るが、通常は想定外の挙動
$this->assertSame(0, $actual, 'このパターンは空文字列 "" とマッチします');
}
public function validRegExpProvider()
{
$ref = new \ReflectionClass(RegexPattern::class);
foreach ($ref->getConstants() as $name => $value) {
yield [$name, $value];
}
}
}
あとは、ReflectionClassConstantを活用すれば、さらにおもしろなDocTestに活用できておもしろいですよ(読者への課題とします)。このようなテスト方法についてはDocCommentでPHPのユニットテストの書きやすさを劇的に改善する手法 - pixiv inside [archive]に書きました。