フィルターは、コントローラアクションの前または後、あるいはその両方で実行されるオブジェクトです。例えば、アクセス制御フィルターは、特定のエンドユーザーがアクセスすることを許可されているか確認するためにアクションの前に実行される場合があります。コンテンツ圧縮フィルターは、エンドユーザーに送信する前にレスポンスコンテンツを圧縮するためにアクションの後に実行される場合があります。
フィルターは、プリフィルター(アクション前に適用されるフィルタリングロジック)および/またはポストフィルター(アクション後に適用されるロジック)で構成される場合があります。
フィルターは基本的に特別な種類のビヘイビアです。したがって、フィルターの使用はビヘイビアの使用と同じです。次の例のように、コントローラクラスでbehaviors()メソッドをオーバーライドすることでフィルターを宣言できます。
public function behaviors()
{
return [
[
'class' => 'yii\filters\HttpCache',
'only' => ['index', 'view'],
'lastModified' => function ($action, $params) {
$q = new \yii\db\Query();
return $q->from('user')->max('updated_at');
},
],
];
}
デフォルトでは、コントローラクラスで宣言されたフィルターは、そのコントローラのすべてのアクションに適用されます。ただし、onlyプロパティを設定することで、フィルターを適用する必要があるアクションを明示的に指定できます。上記の例では、HttpCache
フィルターはindex
アクションとview
アクションにのみ適用されます。また、exceptプロパティを設定して、一部のアクションがフィルタリングされないようにすることもできます。
コントローラに加えて、モジュールまたはアプリケーションでフィルターを宣言することもできます。そうすると、フィルターのonlyプロパティとexceptプロパティを上記のように設定しない限り、フィルターは、そのモジュールまたはアプリケーションに属するすべてのコントローラアクションに適用されます。
注: モジュールまたはアプリケーションでフィルターを宣言する場合は、onlyプロパティとexceptプロパティでアクションIDの代わりにルートを使用する必要があります。これは、アクションIDだけでは、モジュールまたはアプリケーションの範囲内のアクションを完全に指定できないためです。
単一のアクションに対して複数のフィルターが設定されている場合、以下で説明するルールに従って適用されます。
behaviors()
にリストされている順序で適用します。behaviors()
にリストされている順序で適用します。behaviors()
にリストされている順序で適用します。behaviors()
にリストされている逆順で適用します。behaviors()
にリストされている逆順で適用します。behaviors()
にリストされている逆順で適用します。新しいアクションフィルターを作成するには、yii\base\ActionFilter を拡張し、beforeAction() メソッドや afterAction() メソッドをオーバーライドします。前者はアクションが実行される前に実行され、後者はアクションが実行された後に実行されます。beforeAction() の戻り値は、アクションを実行するかどうかを決定します。もし false
であれば、このフィルター以降のフィルターはスキップされ、アクションは実行されません。
次の例は、アクションの実行時間をログに記録するフィルターを示しています。
namespace app\components;
use Yii;
use yii\base\ActionFilter;
class ActionTimeFilter extends ActionFilter
{
private $_startTime;
public function beforeAction($action)
{
$this->_startTime = microtime(true);
return parent::beforeAction($action);
}
public function afterAction($action, $result)
{
$time = microtime(true) - $this->_startTime;
Yii::debug("Action '{$action->uniqueId}' spent $time second.");
return parent::afterAction($action, $result);
}
}
Yiiは、主に yii\filters
名前空間にある、よく使われるフィルターのセットを提供しています。以下では、これらのフィルターを簡単に紹介します。
AccessControlは、ルールのセットに基づいた簡単なアクセス制御を提供します。特に、アクションが実行される前に、AccessControlはリストされたルールを調べ、現在のコンテキスト変数(ユーザーIPアドレス、ユーザーログイン状態など)に一致する最初のルールを見つけます。一致するルールによって、要求されたアクションの実行を許可するか拒否するかが決まります。一致するルールがない場合は、アクセスは拒否されます。
次の例は、認証済みのユーザーに create
および update
アクションへのアクセスを許可し、他のすべてのユーザーがこれらの2つのアクションにアクセスすることを拒否する方法を示しています。
use yii\filters\AccessControl;
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'only' => ['create', 'update'],
'rules' => [
// allow authenticated users
[
'allow' => true,
'roles' => ['@'],
],
// everything else is denied by default
],
],
];
}
一般的なアクセス制御の詳細については、認証のセクションを参照してください。
認証メソッドフィルターは、HTTP Basic Auth、OAuth 2などのさまざまなメソッドを使用してユーザーを認証するために使用されます。これらのフィルタークラスはすべて、yii\filters\auth
名前空間にあります。
次の例は、HTTP Basic Authメソッドに基づいてアクセストークンを使用してユーザーを認証するために、yii\filters\auth\HttpBasicAuth をどのように使用できるかを示しています。これが機能するためには、ユーザーアイデンティティクラスがfindIdentityByAccessToken()メソッドを実装している必要があることに注意してください。
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
return [
'basicAuth' => [
'class' => HttpBasicAuth::class,
],
];
}
認証メソッドフィルターは、RESTful APIの実装でよく使用されます。詳細については、RESTfulの認証セクションを参照してください。
ContentNegotiatorは、レスポンスフォーマットのネゴシエーションとアプリケーション言語のネゴシエーションをサポートします。GET
パラメータと Accept
HTTPヘッダーを調べることにより、レスポンスフォーマットや言語を決定しようとします。
次の例では、ContentNegotiatorはJSONおよびXMLレスポンスフォーマット、および英語(米国)とドイツ語をサポートするように構成されています。
use yii\filters\ContentNegotiator;
use yii\web\Response;
public function behaviors()
{
return [
[
'class' => ContentNegotiator::class,
'formats' => [
'application/json' => Response::FORMAT_JSON,
'application/xml' => Response::FORMAT_XML,
],
'languages' => [
'en-US',
'de',
],
],
];
}
レスポンスフォーマットと言語は、アプリケーションライフサイクルの早い段階で決定する必要があることがよくあります。このため、ContentNegotiatorはフィルターとして使用できるだけでなく、ブートストラップコンポーネントとしても使用できるように設計されています。たとえば、次の例のように、アプリケーション構成で構成することができます。
use yii\filters\ContentNegotiator;
use yii\web\Response;
[
'bootstrap' => [
[
'class' => ContentNegotiator::class,
'formats' => [
'application/json' => Response::FORMAT_JSON,
'application/xml' => Response::FORMAT_XML,
],
'languages' => [
'en-US',
'de',
],
],
],
];
情報:リクエストから優先されるコンテンツタイプと言語を決定できない場合、formats と languages にリストされている最初のフォーマットと言語が使用されます。
HttpCacheは、Last-Modified
および Etag
HTTPヘッダーを利用して、クライアント側のキャッシュを実装します。たとえば、
use yii\filters\HttpCache;
public function behaviors()
{
return [
[
'class' => HttpCache::class,
'only' => ['index'],
'lastModified' => function ($action, $params) {
$q = new \yii\db\Query();
return $q->from('user')->max('updated_at');
},
],
];
}
HttpCacheの使用に関する詳細については、HTTPキャッシュセクションを参照してください。
PageCacheは、ページ全体のサーバーサイドキャッシングを実装します。次の例では、PageCacheは index
アクションに適用され、最大60秒間、または post
テーブルのエントリ数が変更されるまで、ページ全体をキャッシュします。また、選択されたアプリケーション言語に応じて、異なるバージョンのページを保存します。
use yii\filters\PageCache;
use yii\caching\DbDependency;
public function behaviors()
{
return [
'pageCache' => [
'class' => PageCache::class,
'only' => ['index'],
'duration' => 60,
'dependency' => [
'class' => DbDependency::class,
'sql' => 'SELECT COUNT(*) FROM post',
],
'variations' => [
\Yii::$app->language,
]
],
];
}
PageCacheの使用に関する詳細については、ページキャッシングセクションを参照してください。
RateLimiterは、リーキーバケットアルゴリズムに基づいてレート制限アルゴリズムを実装します。これは主に、RESTful APIの実装で使用されます。このフィルターの使用に関する詳細については、レート制限セクションを参照してください。
VerbFilterは、HTTPリクエストメソッドがリクエストされたアクションで許可されているかどうかを確認します。許可されていない場合は、HTTP 405例外をスローします。次の例では、VerbFilterは、CRUDアクションに対して許可される典型的なリクエストメソッドのセットを指定するために宣言されています。
use yii\filters\VerbFilter;
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
'index' => ['get'],
'view' => ['get'],
'create' => ['get', 'post'],
'update' => ['get', 'put', 'post'],
'delete' => ['post', 'delete'],
],
],
];
}
クロスオリジンリソース共有 CORS は、Webページ上の多くのリソース(フォント、JavaScriptなど)が、リソースの発信元ドメイン以外の別のドメインから要求できるようにするメカニズムです。特に、JavaScriptのAJAX呼び出しは、XMLHttpRequestメカニズムを使用できます。このような「クロスドメイン」リクエストは、同一オリジンセキュリティポリシーによってWebブラウザーで禁止されます。CORSは、ブラウザとサーバーがクロスオリジンリクエストを許可するかどうかを決定するために相互作用できる方法を定義します。
Corsフィルターは、CORSヘッダーが常に送信されるように、認証/認可フィルターの前に定義する必要があります。
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::class,
],
], parent::behaviors());
}
APIでyii\rest\ActiveControllerクラスにCORSフィルターを追加する場合は、RESTコントローラーに関するセクションも確認してください。
Corsフィルタリングは、$corsプロパティを使用して調整できます。
cors['Origin']
:許可されたオリジンを定義するために使用される配列。['*']
(すべて)または ['https://www.myserver.net', 'https://www.myotherserver.com']
にすることができます。デフォルトは ['*']
です。cors['Access-Control-Request-Method']
:['GET', 'OPTIONS', 'HEAD']
のような許可された動詞の配列。デフォルトは ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']
です。cors['Access-Control-Request-Headers']
:許可されたヘッダーの配列。['*']
すべてのヘッダー、または特定のヘッダー ['X-Request-With']
にすることができます。デフォルトは ['*']
です。cors['Access-Control-Allow-Credentials']
:現在のリクエストを資格情報を使用して行うことができるかどうかを定義します。true
、false
、またはnull
(設定されていない)にすることができます。デフォルトはnull
です。cors['Access-Control-Max-Age']
:プリフライトリクエストの有効期間を定義します。デフォルトは 86400
です。たとえば、オリジン https://www.myserver.net
でメソッド GET
、HEAD
、OPTIONS
でCORSを許可する場合。
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::class,
'cors' => [
'Origin' => ['https://www.myserver.net'],
'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
],
],
], parent::behaviors());
}
アクションごとにデフォルトのパラメータをオーバーライドして、CORSヘッダーを調整できます。たとえば、login
アクションに Access-Control-Allow-Credentials
を追加するには、次のようにします。
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::class,
'cors' => [
'Origin' => ['https://www.myserver.net'],
'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
],
'actions' => [
'login' => [
'Access-Control-Allow-Credentials' => true,
]
]
],
], parent::behaviors());
}
タイプミスを見つけたり、このページを改善する必要があると思われる場合は?
githubで編集 !
フィルターの作成セクションでは、afterAction()関数は次のようになると思います。
public function afterAction($action, $result)
{ $time = microtime(true) - $this->_startTime; **$result =** Yii::debug("Action '{$action->uniqueId}' spent **{$time}** second."); return parent::afterAction($action, $result); }
..それとも私が間違っていますか?
@Yannis Tambakis:いいえ、
Yii::debug()
は何も返しません。ロガーの設定方法に応じて、メッセージをファイルまたは他の場所にログに記録します。アクションの結果は同じままであり、このフィルターによって変更されることはありません。サインアップまたはログインしてコメントしてください。