7.2. Zend_Filter_Input

7.2.1. 導入

Zend_Filter_Input は、 構造化された厳格な入力フィルタリングを行うためのシンプルな機能を提供します。 さまざまな目的のために使用可能です。なぜなら、これは以下の 3 種類の異なるグループにとっての要求を満たすものだからです。

  • 開発者

    何もしないことに比べたら、 入力のフィルタリングが簡単なことであるはずがありません。 しかし開発者としては、 コードを不必要に複雑にすることなしにデータの完全性を保証する必要があります。 Zend_Filter_Input は、 一般的な使用法に耐えうるシンプルなメソッドを提供し、 特殊な例外にも対応できる拡張性を持ちます。また、 厳格な命名規則により、コードをわかりやすくします。

  • 管理者

    大規模な開発者グループを管理しなければならない管理者は、 Zend_Filter_Input を使用することにより、 生の入力データへのアクセスを制限/排除して、 入力フィルタリングのための構造化されたアプローチを実施することができます。

  • 監査者

    アプリケーションのコードを監査する際には、 開発者が生の入力データをそのまま使用していないかどうかを、 すばやく確実に調べる必要があります。 わかりやすいコードを書けるようになるという Zend_Filter_Input の特性により、もし通常とは異なるアプローチをとっていれば、 監査者はすぐにそれを識別できるようになるでしょう。

入力のフィルタリングにはさまざまな手法があり、 PHP 開発者が使用できる機能にもさまざまなものがあります。 ホワイトリストフィルタリング、ブラックリストフィルタリング、 正規表現、条件文、通常の PHP 関数、…これらは、 いろいろあるうちのほんの一部に過ぎません。 Zend_Filter_Input はこれらのすべての機能を単一の API にまとめ、一貫性のある振る舞いと厳格な命名規則を提供します。 すべてのメソッドは単純な規則にしたがいます。それは、 もしデータが有効ならそれをそのまま返し、有効でなければ FALSE を返すという、ごく単純な規則です。

7.2.1.1. ホワイトリストフィルタリング

ホワイトリスト方式のフィルタリングメソッドは test で始まります。例えば testAlpha()testEmail() などです。これらのメソッドは、 事前に定義された条件にそって入力内容を調べ、 条件を満たすデータのみを返します。条件を満たさない場合は FALSE が返されます。簡単な例を以下に示します。

    <?php
    
    $filterPost = new Zend_Filter_Input($_POST);
    
    if ($alphaName = $filterPost->testAlpha('name')) {
        /* $alphaName には英字しか含まれません。 */
    } else {
        /* $alphaName は FALSE と評価されました。*/
    }
    
    ?>
            

この手法は、返り値を論理型として評価する際に間違いが起こります。 PHP で FALSE と評価される値 (例えば整数の 0 や空の文字列など) を識別するには、 FALSE との厳格な比較を行います。

    <?php
    
    $filterPost = new Zend_Filter_Input($_POST);
    $alphaName = $filterPost->testAlpha('name');
    
    if ($alphaName !== FALSE) {
        /* $alphaName には英字しか含まれません。 */
    } else {
        /* $alphaName === FALSE */
    }
    
    ?>
            

7.2.1.2. ブラインドフィルタリング

ブラインドフィルタリングのメソッドは get で始まります。例えば getAlpha()getDigits() などです。これらのメソッドは、 入力内容を精査するのではなく入力内容のうち有効な部分のみを返します。 例えば getAlpha() は、 入力から英字のみを抜き出したものを返します (もし英字が存在しない場合は空の文字列となります)。 簡単な例を以下に示します。

    <?php
    
    /* $_POST['username'] = 'John123Doe'; */
    
    $filterPost = new Zend_Filter_Input($_POST);
    $alphaUsername = $filterPost->getAlpha('username');
    
    /* $alphaUsername = 'JohnDoe'; */
    
    ?>
            

7.2.1.3. ブラックリストフィルタリング

ブラックリスト方式のフィルタリングメソッドは no で始まります。例えば noTags()noPath() などです。 これらのメソッドはブラインドフィルタリング用のメソッドと似ていますが、 条件として「何が有効なのか」ではなく「何が無効なのか」を設定する点が違います。 無効なデータは取り除かれ、残った部分 (有効だと考えられる部分) が返されます。簡単な例を以下に示します。

    <?php
    
    /* $_POST['comment'] = '<b>I love PHP!</b>'; */
    
    $filterPost = new Zend_Filter_Input($_POST);
    $taglessComment = $filterPost->noTags('comment');
    
    /* $taglessComment = 'I love PHP!'; */
    
    ?>
            

7.2.2. 動作の原理

Zend_Filter_Input は、 入力フィルタリングのためのいくつかの異なる機能を単一の API にまとめ、一貫性のある振る舞いと厳格な命名規則を提供します。 (項7.2.1. 「導入」 を参照ください)。 これらの特性により、Zend_Filter_Input は既存のソリューションと同等のものとなりますが、 これだけでは、より構造化された厳格な方式をサポートすることにはなりません。 そのため、デフォルトで Zend_Filter_Input は入力値へのアクセス制御を行うようにしています。

二種類の構文がサポートされています。デフォルトの (厳格な) 方式は、コンストラクタに引数をひとつだけ渡します。 この引数は、フィルタリング対象となるデータです。

    <?php
    
    $filterPost = new Zend_Filter_Input($_POST);
    $email = $filterPost->testEmail('email');
    
    ?>
        

Zend_Filter_Input は、渡された配列 ($_POST) を NULL に設定し、 元の値に直接アクセスできないようにします (元のデータへのアクセスは、 getRaw() メソッドを通してのみ可能となります。 これで、元の値へのアクセスを管理するのはかなり楽になります)。

オプションの (厳格でない) 方式を使用するには、 コンストラクタへの 2 番目の引数として FALSE を渡します。

    <?php
    
    $filterPost = new Zend_Filter_Input($_POST, FALSE);
    $email = $filterPost->testEmail('email');
    
    ?>
        

フィルタの使用法はまったく同じですが、 Zend_Filter_Input が元の配列 ($_POST) を NULL にすることはありません。 そのため、開発者が元の配列に直接アクセスすることができてしまいます。 この方式は推奨されず、厳格な方式をとることが推奨されています。

Zend_Filter_Input は、配列を扱うことを考えて設計されています。 たいていの入力源は PHP のスーパーグローバル配列 ($_GET$_POST$_COOKIE など) で網羅されており、 その他の入力についても、一般的には配列形式で保存されています。 もしスカラー値をフィルタリングしたい場合は、 章 7. Zend_Filter を参照ください。

7.2.3. 使用例

厳格なホワイトリストフィルタリング (推奨)

    <?php
    
    $filterPost = new Zend_Filter_Input($_POST);
    
    if ($email = $filterPost->testEmail('email')) {
        /* $email は email 形式として有効です。 */
    } else {
        /* $email は email 形式ではありません。 */
    }
    
    ?>
        

厳格なブラインドフィルタリング

    <?php
    
    $filterPost = new Zend_Filter_Input($_POST);
    $alphaName = $filterPost->getAlpha('name');
    
    ?>
        

厳格なブラックリストフィルタリング

    <?php
    
    $filterPost = new Zend_Filter_Input($_POST);
    $taglessComment = $filterPost->noTags('comment');
    
    ?>
        

厳格でないホワイトリストフィルタリング

    <?php
    
    $filterPost = new Zend_Filter_Input($_POST, FALSE);
    
    if ($email = $filterPost->testEmail('email')) {
        /* $email は email 形式として有効です。 */
    } else {
        /* $email は email 形式ではありません。 */
    }
    
    ?>
        

厳格でないブラインドフィルタリング

    <?php
    
    $filterPost = new Zend_Filter_Input($_POST, FALSE);
    $name = $filterPost->getAlpha('name');
    
    ?>
        

厳格でないブラックリストフィルタリング

    <?php
    
    $filterPost = new Zend_Filter_Input($_POST, FALSE);
    $comment = $filterPost->noTags('comment');
    
    ?>