コントローラフィルタ

コントローラフィルタはで、コントローラ実行の前後にアクションを実行します。フック とは異なり、実行対象の URI をとてもシンプルに選択することができます。入力フィルタは Request を編集することができ、事後フィルタは Response も編集することができます。大きな柔軟性とパワーを持っています。フィルタが処理すべき一般的なタスク例をいくつか示します:

  • リクエスト受付時のCSRF 攻撃への防御
  • ユーザのロールに基づいたサイト表示制限
  • 特定エンドポイントのリクエスト制限
  • "ただいまメンテナンス中です" ページの表示
  • コンテントネゴシエーションの自動処理
  • などなど……

フィルタの作成

フィルタは CodeIgniter\Filters\FilterInterface を実装するシンプルなクラスです。これには2つのメソッドがあります: before()``after()``です。それぞれコントローラの前後に実行されます。あなたのクラスには両方を実装しなければなりませんが、不要ならメソッドの中身を空にしておくとよいです。フィルタクラスのスケルトンは次のようになります:

<?php namespace App\Filters;

use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;

class MyFilter implements FilterInterface
{
    public function before(RequestInterface $request)
    {
        // ここで何かをする
    }

    //--------------------------------------------------------------------

    public function after(RequestInterface $request, ResponseInterface $response)
    {
        // ここで何かをする
    }
}

事前フィルタ

どのフィルタでも $request オブジェクトを return することができ、現在の Request と差し替えられます。これによってコントローラの実行時に起きることを変更できます。

事前フィルタはコントローラの実行前に優先して実行されるので、コントローラが実行される前に処理を止めることもできます。そうするにはリクエストオブジェクト以外の何かを返してください。 これは典型的にはリダイレクトになりますが、例としてこのようになります:

public function before(RequestInterface $request)
{
    $auth = service('auth');

    if (!$auth->isLoggedIn())
    {
        return redirect('login');
    }
}

Response インスタンスが返されると、Response がクライアントに返送されスクリプトの実行は停止されます。 これは API の実行制限に有用です。例として application/Filters/Throttle.php をご覧ください。

事後フィルタ

事後フィルタは事前フィルタと似たようなものですが、$response オブジェクトしか返せないのと、スクリプトの停止ができない点が異なります。これは最終出力を編集することができます。言い換えると、単に最終出力を何かするだけです。便利にできることは、セキュリティヘッダが正しく設定されていることを確認すること、もしくは最終出力をキャッシュすること、あるいは最終出力に NG ワードフィルタをすることです。

Configuring Filters

フィルタを作ったなら、実行するには設定が必要です。application/Config/Filters.php でできます。 このファイルには、フィルタを実行する設定として4つのプロパティを持ちます。

$aliases

$aliases 配列は、実行するフィルタを1つ以上、クラス名を完全な形で記述した連想配列です:

public $aliases = [
    'csrf' => \App\Filters\CSRF::class
];

エイリアスは必須です。完全なクラス名をこのあとで使おうとすれば、システムはエラーを投げます。この方法で定義すれば、使用クラスを切り替えるのが単純になります。認証システムを別のものに変えようと判断したときにはすばらしいもので、フィルタクラスを別のものにすればおしまいになります。

複数のフィルタをひとつのエイリアスにつなげることも可能で、複雑なフィルタセットもシンプルにすることができます:

public $aliases = [
    'apiPrep' => [
        \App\Filters\Negotiate::class,
        \App\Filters\ApiAuth::class
    ]
];

必要な数のエイリアスを定義する必要があります。

$globals

2つ目のセクションでは、すべてのリクエストで有効になるフィルタを定義できます。 どれだけここに使うかは気をつける必要があります。毎回のリクエストで多くを実行しすぎれば、パフォーマンスに影響を与えるからです。before または after 配列にエイリアスを加えることでフィルタを指定できます:

public $globals = [
            'before' => [
                    'csrf'
            ],
            'after'  => []
    ];

ほぼ毎回のリクエストで実行したいけれども、わずかだけ実行したくないということがあります。 一般的な例として、サードパーティのサイトから特定の1つ2つの URI を叩けるようにするため、CSRF 攻撃保護フィルタの例外とし、残りは保護したままとする必要があるとします。これをするには、'except' キーと URI 検索文字列を、エイリアスの値側の配列に加えます:

public $globals = [
            'before' => [
                    'csrf' => ['except' => 'api/*']
            ],
            'after'  => []
    ];

フィルタ設定の URI の使える箇所ではどこでも、正規表現、もしくはこの例のようにアスタリスクをワイルドカードとしてその後の文字全部に一致するものとして使用できます。この例では api/ で始まる URL は CSRF 攻撃保護の対象外となりますが、サイトのフォームはすべて保護の対象となります。複数の URI を指定する必要があるなら、URI パターンを配列で指定できます:

public $globals = [
            'before' => [
                    'csrf' => ['except' => ['foo/*', 'bar/*']]
            ],
            'after'  => []
    ];

$methods

フィルタには一定の HTTP メソッド、つまりPOST、GET、PUTなどのようなものを適用することができます。この配列では、メソッド名は小文字で指定します。この値はフィルタを実行したいものの配列です。$globals や他の $filters プロパティとは異なり、事前フィルタとしてのみ動作します:

public $methods = [
    'post' => ['foo', 'bar'],
    'get'  => ['baz']
]

標準的な HTTP メソッドに加え、次の特殊な2つをサポートします: 'cli' と 'ajax'です。見ての通りではありますが説明しますと、'cli' はコマンドラインからのリクエストで動作し、'ajax' はすべての AJAX リクエストに適用されます。

$filters

このプロパティはフィルタエイリアスの配列です。それぞれのエイリアスは、適用されるべき URI のパターンのリストを持つ before と after の配列を指定します:

public filters = [
    'foo' => ['before' => ['admin/*'], 'after' => ['users/*']],
    'bar' => ['before' => ['api/*', 'admin/*']]
];

Provided Filters

未定。