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

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

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


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

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

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

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


60
## フィルタを作成する <a name="creating-filters"></a>
61

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

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

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


96
## コアのフィルタ <a name="core-filters"></a>
97

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


### [[yii\filters\AccessControl|AccessControl]] <a name="access-control"></a>

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

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

```php
use yii\filters\AccessControl;

public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'only' => ['create', 'update'],
            'rules' => [
123
                // 認証されたユーザに許可する
124 125 126 127
                [
                    'allow' => true,
                    'roles' => ['@'],
                ],
128
                // その他は、既定により拒否される
129 130 131 132 133 134
            ],
        ],
    ];
}
```

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


138
### 認証メソッドフィルタ <a name="auth-method-filters"></a>
139

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

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

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

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

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


### [[yii\filters\ContentNegotiator|ContentNegotiator]] <a name="content-negotiator"></a>

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

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

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

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

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

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



### [[yii\filters\HttpCache|HttpCache]] <a name="http-cache"></a>

228
HttpCache は `Last-Modified` および `Etag` の HTTP ヘッダを利用して、クライアントサイドのキャッシュを実装するものです。
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247

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

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


### [[yii\filters\PageCache|PageCache]] <a name="page-cache"></a>

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

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

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


### [[yii\filters\RateLimiter|RateLimiter]] <a name="rate-limiter"></a>

285
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)
286 287
に基づいてレート制限のアルゴリズムを実装するものです。主として RESTful API を実装するときに使用されます。
このフィルタの使用に関する詳細は [レート制限](rest-rate-limiting.md) の節を参照してください。
288 289 290 291


### [[yii\filters\VerbFilter|VerbFilter]] <a name="verb-filter"></a>

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

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

### [[yii\filters\Cors|Cors]] <a name="cors"></a>

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

324
[[yii\filters\Cors|Cors フィルタ]] は、CORS ヘッダが常に送信されることを保証するために、Authentication / Authorization のフィルタよりも前に定義されなければなりません。
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339

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

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

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

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

352
次の例は、生成元 `http://www.myserver.net` に対する `GET``HEAD` および `OPTIONS` のメソッドによる CORS を許可するものです。
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371

```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());
}
```

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

```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());
}
```