structure-filters.md 18.6 KB
Newer Older
1 2
フィルタ
========
3

4 5
フィルタは、[コントローラアクション](structure-controllers.md#actions) の前 および/または 後に走るオブジェクトです。
例えば、アクセスコントロールフィルタはアクションの前に走って、アクションが特定のエンドユーザだけにアクセスを許可するものであることを保証します。
6
また、コンテント圧縮フィルタはアクションの後に走って、レスポンスのコンテントをエンドユーザに送出する前に圧縮します。
7

8
一つのフィルタは、前フィルタ (アクションの *前* に適用されるフィルタのロジック) および/または 後フィルタ (アクションの *後* に適用されるロジック) から構成することが出来ます。
9 10


11
## フィルタを使用する <span id="using-filters"></span>
12

13 14 15
フィルタは、本質的には特別な種類の [ビヘイビア](concept-behaviors.md) です。
したがって、フィルタを使うことは [ビヘイビアを使う](concept-behaviors.md#attaching-behaviors) ことと同じです。
下記のように、[[yii\base\Controller::behaviors()|behaviors()]] メソッドをオーバーライドすることによって、コントローラの中でフィルタを宣言することが出来ます。
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

```php
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');
            },
        ],
    ];
}
```

33
デフォルトでは、コントローラクラスの中で宣言されたフィルタは、そのコントローラの *全て* のアクションに適用されます。
34 35
しかし、[[yii\base\ActionFilter::only|only]] プロパティを構成することによって、フィルタがどのアクションに適用されるべきかを明示的に指定することも出来ます。
上記の例では、 `HttpCache` フィルタは、`index``view` のアクションに対してのみ適用されています。
36
また、[[yii\base\ActionFilter::except|except]] プロパティを構成して、いくつかのアクションをフィルタされないように除外することも可能です。
37

38
コントローラのほかに、[モジュール](structure-modules.md) または [アプリケーション](structure-applications.md) でもフィルタを宣言することが出来ます。
39
そのようにした場合、[[yii\base\ActionFilter::only|only]] と [[yii\base\ActionFilter::except|except]] のプロパティを上で説明したように構成しない限り、そのフィルタは、モジュールまたはアプリケーションに属する *全て* のコントローラアクションに適用されます。
40

41
> Note|注意: モジュールやアプリケーションでフィルタを宣言する場合、[[yii\base\ActionFilter::only|only]] と [[yii\base\ActionFilter::except|except]] のプロパティでは、アクション ID ではなく、[ルート](structure-controllers.md#routes) を使わなければなりません。
42
なぜなら、モジュールやアプリケーションのスコープでは、アクション ID だけでは完全にアクションを指定することが出来ないからです。
43

44
一つのアクションに複数のフィルタが構成されている場合、フィルタは下記で説明されている規則に従って適用されます。
45

46 47 48 49 50 51 52 53 54 55
* 前フィルタ
    - アプリケーションで宣言されたフィルタを `behaviors()` にリストされた順に適用する。
    - モジュールで宣言されたフィルタを `behaviors()` にリストされた順に適用する。
    - コントローラで宣言されたフィルタを `behaviors()` にリストされた順に適用する。
    - フィルタのどれかがアクションをキャンセルすると、そのフィルタの後のフィルタ (前フィルタと後フィルタの両方) は適用されない。
* 前フィルタを通過したら、アクションを走らせる。
* 後フィルタ
    - コントローラで宣言されたフィルタを `behaviors()` にリストされた逆順で適用する。
    - モジュールで宣言されたフィルタを `behaviors()` にリストされた逆順で適用する。
    - アプリケーションで宣言されたフィルタを `behaviors()` にリストされた逆順で適用する。
56 57


58
## フィルタを作成する <span id="creating-filters"></span>
59

60
新しいアクションフィルタを作成するためには、[[yii\base\ActionFilter]] を拡張して、[[yii\base\ActionFilter::beforeAction()|beforeAction()]] および/または [[yii\base\ActionFilter::afterAction()|afterAction()]] メソッドをオーバーライドします。
61
前者はアクションが走る前に実行され、後者は走った後に実行されます。
62 63
[[yii\base\ActionFilter::beforeAction()|beforeAction()]] の返り値が、アクションが実行されるべきか否かを決定します。
返り値が false である場合、このフィルタの後に続くフィルタはスキップされ、アクションは実行を中止されます。
64

65
次の例は、アクションの実行時間をログに記録するフィルタを示すものです。
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

```php
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;
86
        Yii::trace("アクション '{$action->uniqueId}' は $time 秒を消費。");
87 88 89 90 91 92
        return parent::afterAction($action, $result);
    }
}
```


93
## コアのフィルタ <span id="core-filters"></span>
94

95 96
Yii はよく使われる一連のフィルタを提供しており、それらは、主として `yii\filters` 名前空間の下にあります。
以下では、それらのフィルタを簡単に紹介します。
97 98


99
### [[yii\filters\AccessControl|AccessControl]] <span id="access-control"></span>
100

101
AccessControl は、一組の [[yii\filters\AccessControl::rules|規則]] に基づいて、シンプルなアクセスコントロールを提供するものです。
102
具体的に言うと、アクションが実行される前に、AccessControl はリストされた規則を調べて、現在のコンテキスト変数 (例えば、ユーザの IP アドレスや、ユーザのログイン状態など) に最初に合致するものを見つけます。
103 104
そして、合致した規則によって、リクエストされたアクションの実行を許可するか拒否するかを決定します。
合致する規則がなかった場合は、アクセスは拒否されます。
105

106
次の例は、認証されたユーザに対しては `create``update` のアクションへのアクセスを許可し、その他のすべてのユーザにはこれら二つのアクションに対するアクセスを拒否する仕方を示すものです。
107 108 109 110 111 112 113 114 115 116 117

```php
use yii\filters\AccessControl;

public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'only' => ['create', 'update'],
            'rules' => [
118
                // 認証されたユーザに許可する
119 120 121 122
                [
                    'allow' => true,
                    'roles' => ['@'],
                ],
123
                // その他はすべてデフォルトにより拒否される
124 125 126 127 128 129
            ],
        ],
    ];
}
```

130
アクセスコントロール一般についての詳細は [権限](security-authorization.md) の節を参照してください。
131 132


133
### 認証メソッドフィルタ <span id="auth-method-filters"></span>
134

135 136 137
認証メソッドフィルタは、[HTTP Basic 認証](http://ja.wikipedia.org/wiki/Basic%E8%AA%8D%E8%A8%BC)
[OAuth 2](http://oauth.net/2/) など、様々なメソッドを使ってユーザを認証するために使われるものです。
これらのフィルタクラスはすべて `yii\filters\auth` 名前空間の下にあります。
138

139
次の例は、[[yii\filters\auth\HttpBasicAuth]] の使い方を示すもので、HTTP Basic 認証に基づくアクセストークンを使ってユーザを認証しています。
140
これを動作させるためには、あなたの [[yii\web\User::identityClass|ユーザアイデンティティクラス]]
141
[[yii\web\IdentityInterface::findIdentityByAccessToken()|findIdentityByAccessToken()]] メソッドを実装していなければならないことに注意してください。
142 143 144 145 146 147 148 149 150 151 152 153 154 155

```php
use yii\filters\auth\HttpBasicAuth;

public function behaviors()
{
    return [
        'basicAuth' => [
            'class' => HttpBasicAuth::className(),
        ],
    ];
}
```

156 157
認証メソッドフィルタは RESTful API を実装するときに使われるのが通例です。
詳細については、RESTful の [認証](rest-authentication.md) の節を参照してください。
158 159


160
### [[yii\filters\ContentNegotiator|ContentNegotiator]] <span id="content-negotiator"></span>
161

162
ContentNegotiator は、レスポンス形式のネゴシエーションとアプリケーション言語のネゴシエーションをサポートします。
163
このフィルタは `GET` パラメータと `Accept` HTTP ヘッダを調べることによって、レスポンス形式 および/または 言語を決定しようとします。
164

165
次の例では、ContentNegotiator はレスポンス形式として JSON と XML をサポートし、(合衆国の)英語とドイツ語を言語としてサポートするように構成されています。
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188

```php
use yii\filters\ContentNegotiator;
use yii\web\Response;

public function behaviors()
{
    return [
        [
            'class' => ContentNegotiator::className(),
            'formats' => [
                'application/json' => Response::FORMAT_JSON,
                'application/xml' => Response::FORMAT_XML,
            ],
            'languages' => [
                'en-US',
                'de',
            ],
        ],
    ];
}
```

189
レスポンス形式と言語は [アプリケーションのライフサイクル](structure-applications.md#application-lifecycle) のもっと早い段階で決定される必要があることがよくあります。
190 191
このため、ContentNegotiator はフィルタの他に、[ブートストラップコンポーネント](structure-applications.md#bootstrap) としても使うことができるように設計されています。
例えば、次のように、ContentNegotiator を [アプリケーションの構成情報](structure-applications.md#application-configurations) の中で構成することが出来ます。
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213

```php
use yii\filters\ContentNegotiator;
use yii\web\Response;

[
    'bootstrap' => [
        [
            'class' => ContentNegotiator::className(),
            'formats' => [
                'application/json' => Response::FORMAT_JSON,
                'application/xml' => Response::FORMAT_XML,
            ],
            'languages' => [
                'en-US',
                'de',
            ],
        ],
    ],
];
```

214
> Info|情報: 望ましいコンテントタイプと言語がリクエストから決定できない場合は、[[formats]] および [[languages]] に挙げられている最初の形式と言語が使用されます。
215 216 217



218
### [[yii\filters\HttpCache|HttpCache]] <span id="http-cache"></span>
219

220
HttpCache は `Last-Modified` および `Etag` の HTTP ヘッダを利用して、クライアント側のキャッシュを実装するものです。
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

```php
use yii\filters\HttpCache;

public function behaviors()
{
    return [
        [
            'class' => HttpCache::className(),
            'only' => ['index'],
            'lastModified' => function ($action, $params) {
                $q = new \yii\db\Query();
                return $q->from('user')->max('updated_at');
            },
        ],
    ];
}
```

240
HttpCache に関する詳細は [HTTP キャッシュ](caching-http.md) の節を参照してください。
241 242


243
### [[yii\filters\PageCache|PageCache]] <span id="page-cache"></span>
244

245
PageCache はサーバ側におけるページ全体のキャッシュを実装するものです。
246 247
次の例では、PageCache が `index` アクションに適用されて、最大 60 秒間、または、`post` テーブルのエントリ数が変化するまでの間、ページ全体をキャッシュしています。
さらに、このページキャッシュは、選択されたアプリケーションの言語に従って、違うバージョンのページを保存するようにしています。
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

```php
use yii\filters\PageCache;
use yii\caching\DbDependency;

public function behaviors()
{
    return [
        'pageCache' => [
            'class' => PageCache::className(),
            'only' => ['index'],
            'duration' => 60,
            'dependency' => [
                'class' => DbDependency::className(),
                'sql' => 'SELECT COUNT(*) FROM post',
            ],
            'variations' => [
                \Yii::$app->language,
            ]
        ],
    ];
}
```

272
PageCache の使用に関する詳細は [ページキャッシュ](caching-page.md) の節を参照してください。
273 274


275
### [[yii\filters\RateLimiter|RateLimiter]] <span id="rate-limiter"></span>
276

277 278
RateLimiter は [リーキーバケットアルゴリズム](http://ja.wikipedia.org/wiki/%E3%83%AA%E3%83%BC%E3%82%AD%E3%83%BC%E3%83%90%E3%82%B1%E3%83%83%E3%83%88) に基づいてレート制限のアルゴリズムを実装するものです。
主として RESTful API を実装するときに使用されます。
279
このフィルタの使用に関する詳細は [レート制限](rest-rate-limiting.md) の節を参照してください。
280 281


282
### [[yii\filters\VerbFilter|VerbFilter]] <span id="verb-filter"></span>
283

284
VerbFilter は、HTTP リクエストメソッド (HTTP 動詞) がリクエストされたアクションによって許可されているかどうかをチェックするものです。
285
許可されていない場合は、HTTP 405 例外を投げます。
286
次の例では、VerbFilter が宣言されて、CRUD アクションに対して許可されるメソッドの典型的なセットを指定しています。
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307

```php
use yii\filters\VerbFilter;

public function behaviors()
{
    return [
        'verbs' => [
            'class' => VerbFilter::className(),
            'actions' => [
                'index'  => ['get'],
                'view'   => ['get'],
                'create' => ['get', 'post'],
                'update' => ['get', 'put', 'post'],
                'delete' => ['post', 'delete'],
            ],
        ],
    ];
}
```

308
### [[yii\filters\Cors|Cors]] <span id="cors"></span>
309

310
クロスオリジンリソース共有 [CORS](https://developer.mozilla.org/ja/docs/HTTP_access_control) とは、ウェブページにおいて、さまざまなリソース (例えば、フォントや JavaScript など) を、それを生成するドメイン以外のドメインからリクエストすることを可能にするメカニズムです。
311
特に言えば、JavaScript の AJAX 呼出しが使用することが出来る XMLHttpRequest メカニズムです。
312
このような「クロスドメイン」のリクエストは、このメカニズムに拠らなければ、同一生成元のセキュリティポリシーによって、ウェブブラウザから禁止されるはずのものです。
313
CORS は、ブラウザとサーバが交信して、クロスドメインのリクエストを許可するか否かを決定する方法を定義するものです。
314

315
[[yii\filters\Cors|Cors フィルタ]] は、CORS ヘッダが常に送信されることを保証するために、Authentication / Authorization のフィルタよりも前に定義されなければなりません。
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330

```php
use yii\filters\Cors;
use yii\helpers\ArrayHelper;

public function behaviors()
{
    return ArrayHelper::merge([
        [
            'class' => Cors::className(),
        ],
    ], parent::behaviors());
}
```

331
Cors のフィルタリングは `cors` プロパティを使ってチューニングすることが出来ます。
332

333 334
* `cors['Origin']`: 許可される生成元を定義するのに使われる配列。
  `['*']` (すべて) または `['http://www.myserver.net'、'http://www.myotherserver.com']` などが設定可能。デフォルトは `['*']`
335
* `cors['Access-Control-Request-Method']`: 許可される HTTP 動詞の配列。
336 337 338
  たとえば、`['GET', 'OPTIONS', 'HEAD']`。デフォルトは `['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']`
* `cors['Access-Control-Request-Headers']`: 許可されるヘッダの配列。
  全てのヘッダを意味する `['*']` または特定のヘッダを示す `['X-Request-With']` が設定可能。デフォルトは `['*']`
339
* `cors['Access-Control-Allow-Credentials']`: 現在のリクエストをクレデンシャルを使ってすることが出来るかどうかを定義。
340
  `true``false` または `null` (設定なし) が設定可能。デフォルトは `null`
341
* `cors['Access-Control-Max-Age']`: プリフライトリクエストの寿命を定義。デフォルトは `86400`
342

343
次の例は、生成元 `http://www.myserver.net` に対する `GET``HEAD` および `OPTIONS` のメソッドによる CORS を許可するものです。
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362

```php
use yii\filters\Cors;
use yii\helpers\ArrayHelper;

public function behaviors()
{
    return ArrayHelper::merge([
        [
            'class' => Cors::className(),
            'cors' => [
                'Origin' => ['http://www.myserver.net'],
                'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
            ],
        ],
    ], parent::behaviors());
}
```

363
デフォルトのパラメータをアクション単位でオーバーライドして CORS ヘッダをチューニングすることも可能です。
364
例えば、`login` アクションに `Access-Control-Allow-Credentials` を追加することは、次のようにすれば出来ます。
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387

```php
use yii\filters\Cors;
use yii\helpers\ArrayHelper;

public function behaviors()
{
    return ArrayHelper::merge([
        [
            'class' => Cors::className(),
            'cors' => [
                'Origin' => ['http://www.myserver.net'],
                'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
            ],
            'actions' => [
                'login' => [
                    'Access-Control-Allow-Credentials' => true,
                ]
            ]
        ],
    ], parent::behaviors());
}
```