Yii 2.0 決定版ガイドとぴぴば〺〯〯ぷぷぷ〮べどどてひちねづぷはひに〮っはね〯つはっ〯でふどつづ

Qiang Xue,
Alexander Makarov,
Carsten Brandt,
Klimov Paul,andmany contributors from the Yii community
日本語 translation provided by:
Kazunari Hoshina, @crifff,
Tomoki Morit,a, @jamband,
Atsuhi Sakurai @mocapapa,
Nobuo Kihara, @softark,
Hisateru Tanaka, @tanakahisateru

ごとどび ぴふぴはひどちぬ どび ひづぬづちびづつ ふのつづひ ぴとづ ごづひねび はて すどど いはっふねづのぴちぴどはの〮ぃはばべひどでとぴ 〲〰〱〴 すどど こはてぴぷちひづ ががぃ〮 ぁぬぬ げどでとぴび げづびづひぶづつ〮

Contents〱 導入〱〮〱 すどど とは何か 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮〱〮〲 バージョン 〱〮〱 からアップグレードする 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮〱〱〳〲 始めよう〱〵〲〮〱 何を知っている必要があるか 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〱〵〲〮〲 すどど をインストールする 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〱〶〲〮〳 アプリケーションを走らせる 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〵〲〮〴 こんにちは、と言う 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〳〰
〲〮〵 フォームを扱う 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〳〴〲〮〶 データベースを扱う 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〱〲〮〷 ぇどど でコードを生成する 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〷〲〮〸 先を見通す 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〵〳 アプリケーションの構造〵〷〳〮〱 概要 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〷〳〮〲 エントリ・スクリプト 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〸〳〮〳 アプリケーション 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〶〰
〳〮〴 アプリケーション・コンポーネント 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〷〴〳〮〵 コントローラ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〷〷〳〮〶 モデル 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〸〷〳〮〷 ビュー 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〹〹〳〮〸 モジュール 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〱〱〵〳〮〹 フィルタ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〱〲〲〳〮〱〰 ウィジェット 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〱〳〱〳〮〱〱 アセット 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〱〳〶〳〮〱〲 エクステンション 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〱〵〸〴 リクエストの処理〱〷〳〴〮〱 概要 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〱〷〳〴〮〲 ブートストラップ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〱〷〴〴〮〳 ルーティングと さげが 生成 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〱〷〵〴〮〴 リクエスト 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〱〹〲
どどど

どぶ

ぃくぎごぅぎごこ
〴〮〵
〴〮〶
〴〮〷
〴〮〸

レスポンス 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〱〹〷
セッションとクッキー 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〰〳エラー処理 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〱〲ロギング 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〱〷〵 鍵となる概念〲〲〷〵〮〱 コンポーネント 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〲〷〵〮〲 プロパティ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〲〹〵〮〳 イベント 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〳〱〵〮〴 ビヘイビア 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〴〰
〵〮〵 構成情報 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〴〷〵〮〶 エイリアス 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〵〳〵〮〷 クラスのオートローディング 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〵〶〵〮〸 サービス・ロケータ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〵〹〵〮〹 依存注入コンテナ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〶〲〶 データベースの取り扱い〲〷〵〶〮〱 データベース・アクセス・オブジェクト 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〷〵〶〮〲 クエリ・ビルダ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〲〹〰
〶〮〳 アクティブ・レコード 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〳〱〱〶〮〴 データベース・マイグレーション 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〳〴〹〷 ユーザからのデータ取得〳〷〳〷〮〱 フォームを作成する 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〳〷〳〷〮〲 入力を検証する 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〳〷〹〷〮〳 ファイルをアップロードする 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〳〹〷〷〮〴 表形式インプットでデータを収集する 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〰〲〷〮〵 複数のモデルのデータを取得する 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〰〴〷〮〶 クライアント・サイドで ぁっぴどぶづうはひね を拡張する 〮 〮 〮 〮 〮 〮 〮 〴〰〶〸 データの表示〴〱〱〸〮〱 データのフォーマット 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〱〱〸〮〲 ページネーション 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〱〷〸〮〳 並べ替え 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〱〹〸〮〴 データ・プロバイダ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〲〱〸〮〵 データ・ウィジェット 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〲〹〸〮〶 クライアント・スクリプトを扱う 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〴〴〸〮〷 テーマ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〴〹〹 セキュリティ〴〵〳〹〮〱 セキュリティ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〵〳〹〮〲 認証 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〵〳〹〮〳 権限付与 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〵〸〹〮〴 パスワードを扱う 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〷〶ぃくぎごぅぎごこ
〹〮〵
〹〮〶

ぶ

暗号化 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〷〷セキュリティのベスト・プラクティス 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〷〹〱〰 キャッシュ〴〸〹〱〰〮〱 キャッシュ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〸〹〱〰〮〲 データ・キャッシュ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〴〸〹〱〰〮〳 フラグメント・キャッシュ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〰〰
〱〰〮〴 ページ・キャッシュ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〰〴〱〰〮〵 えごごぐ キャッシュ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〰〴〱〱 げぅこごてふぬ ウェブ・サービス〵〰〹〱〱〮〱 クイック・スタート 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〰〹〱〱〮〲 リソース 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〱〴〱〱〮〳 コントローラ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〱〹〱〱〮〴 ルーティング 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〲〳〱〱〮〵 レスポンス形式の設定 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〲〶〱〱〮〶 認証 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〳〰
〱〱〮〷 レート制限 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〳〳〱〱〮〸 バージョン管理 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〳〴〱〱〮〹 エラー処理 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〳〷〱〲 開発ツール〵〴〱〱〳 テスト〵〴〳〱〳〮〱 テスト 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〴〳〱〳〮〲 テスト環境の構築 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〴〵〱〳〮〳 単体テスト 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〴〵〱〳〮〴 機能テスト 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〴〶〱〳〮〵 受入テスト 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〴〷〱〳〮〶 フィクスチャ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〴〷〱〴 スペシャル・トピック〵〵〷〱〴〮〱 あなた自身のアプリケーション構造を作成する 〮 〮 〮 〮 〮 〮 〮 〮 〵〵〷〱〴〮〲 コンソール・アプリケーション 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〵〹〱〴〮〳 コア・バリデータ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〶〶〱〴〮〴 国際化 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〵〸〴〱〴〮〵 メール送信 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〶〰〲〱〴〮〶 パフォーマンス・チューニング 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〶〰〷〱〴〮〷 共有ホスティング環境 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〶〱〳〱〴〮〸 テンプレートエンジンを使う 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〶〱〵〱〴〮〹 サードパーティのコードを扱う 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〶〱〶〱〴〮〱〰すどど をマイクロ・フレームワークとして使う 〮 〮 〮 〮 〮 〮 〮 〮 〮 〶〲〰
〱〵 ウィジェット

〶〲〷

ぶど

ぃくぎごぅぎごこ〱〶 ヘルパ〶〲〹〱〶〮〱 ヘルパ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〶〲〹〱〶〮〲 配列ヘルパ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〶〳〱〱〶〮〳 えぴねぬ ヘルパ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〶〴〰
〱〶〮〴 さひぬ ヘルパ 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〮 〶〴〸Chapter 1

導入
1.1

Yii とは何か

すどど は現代的なウェブ・アプリケーションを迅速に開発するための、高性
能な、コンポーネント・ベースの ぐえぐ フレームワークです。 すどど という名前 〨イー すなわち [ji:] と発音します〩 は、中国語では「易」であり、「シンプルかつ進化的」であることを意味します。 また すづび ぉぴ ぉび のア
クロニム 〨頭字語〩 であると考えることも出来ます。

1.1.1

Yii は何に適しているか

すどど は汎用的なウェブ・プログラミング・フレームワークです。 つまり、あらゆる種類のウェブ・アプリケーションを ぐえぐ を使って開発するときに、すどど を使用することが出来ます。 コンポーネント・ベースのアー
キテクチャと洗練されたキャッシュ・サポートを有しているため、すどどは大規模なアプリケーション、 たとえば、ポータル、フォーラム、コンテント・マネージメント・システム 〨ぃきこ〩、電子商取引プロジェク
ト、げぅこごてふぬ ウェブ・サービス、等々を開発するのに特に適していま
す。

1.1.2

Yii を他のフレームワークと比べるとあなたが既に他のフレームワークに親しんでいる場合は、すどど を比較するとどうなのかを知りたいでしょう。
• ほとんどの ぐえぐ フレームワーク同様、すどど は きざぃ 〨きはつづぬ〭ざどづぷ〭
ぃはのぴひはぬぬづひ〩 アーキテクチャ・パターンを実装し、 このパターンに基づいたコードの編成を推進しています。
• すどど は、コードはシンプルかつエレガントに書かれるべきである、という哲学を採用しています。 何らかのデザイン・パターンの厳密な遵守を主目的とする凝りすぎた設計は、すどど が決して試みようとしないものです。
〱

〲

ぃえぁぐごぅげ 〱〮 導入• すどど はフル装備のフレームワークです。 クエリ・ビルダ、リレー
ショナル・データベースと ぎはこけが データベース双方のためのアク
ティブ・レコード、げぅこごてふぬ ぁぐぉ 開発サポート、多層構成のキャッ
シュ・サポート、 等々、検証済みで直ちに使える多数の機能を提供します。
• すどど は極めて拡張性の高いフレームワークです。あなたはコアのコードのほとんど全ての要素をカスタマイズしたり置き換えたりす
ることが出来ます。 また、すどど の堅固なエクステンション・アーキ
テクチャを利用して、再配布可能なエクステンションを使用したり開発したりすることも出来ます。
• 高性能であることは常に すどど の主たる目標です。
すどど はワンマン・ショーではありません。すどど は 強力なコア開発チーム1
および すどど 開発に間断なく貢献してくれるプロフェッショナルの大きなコミュニティーに支えられたプロジェクトです。 すどど 開発チームは、最新のウェブ開発の潮流と、他のフレームワークやプロジェクトに見出される最善のプラクティスと機能を、注意深く見守り続けています。 他のところで見出された最善のプラクティスと機能で最も適切なものは、定期的にコア・フレームワークに組み込まれ、 シンプルかつエレガントなインタフェイスを通じて公開されます。

1.1.3

Yii のバージョン

すどど は現在、利用可能な二つのメジャー・バージョン、すなわち 〱〮〱 と〲〮〰 を持っています。バージョン 〱〮〱 は古い世代のもので、現在はメンテ
ナンス・モードにあります。 バージョン 〲〮〰 は、最新のテクノロジーとプロトコル、例えば、ぃはねばはびづひ、ぐこげ、名前空間、トレイトなどを採用
して、すどど を完全に書き直したものです。 バージョン 〲〮〰 がこのフレームワークの現世代を表すものであり、今後数年間にわたって主要な開発努力の対象となるものです。 このガイドは主としてバージョン 〲〮〰 について述べます。

1.1.4

必要条件と前提条件

すどど 〲〮〰 は ぐえぐ 〵〮〴〮〰 以上を必要とし、ぐえぐ の最新バージョンで最高の力を発揮します。 個々の機能に対する詳細な必要条件は、全ての すどど リ
リースに含まれている必要条件チェッカを走らせることによって知ることが出来ます。
すどど を使うためには、オブジェクト指向プログラミング 〨くくぐ〩 の基
本的な知識が必要です。 なぜなら、すどど は純粋な くくぐ ベースのフレームワークだからです。 また、すどど 〲〮〰 は 名前空間2 や トレイト3 のようhttps://www.yiiframework.com/team/https://www.php.net/manual/ja/language.namespaces.php
3
https://www.php.net/manual/ja/language.oop5.traits.php
12〱〮〲〮 バージョン 〱〮〱 からアップグレードする〳な ぐえぐ の最新の機能を利用しています。 これらの概念を理解することは、すどど 〲〮〰 を採用することを一層容易にするでしょう。

1.2

バージョン 1.1 からアップグレードする

すどど フレームワークは 〲〮〰 のために完全に書き直されたため、バージョン〱〮〱 と 〲〮〰 の間には数多くの違いがあります。 結果として、バージョン〱〮〱 からのアップグレードは、マイナー・バージョン間でのアップグレー
ドのような些細な仕事ではなくなりました。 このセクションでは、二つのバージョン間の主要な違いを説明します。
もしあなたが以前に すどど 〱〮〱 を使ったことがなければ、このガイドを飛ばして直接に 【始めよう【 に進んでも、問題はありません。
すどど 〲〮〰 はこの要約でカバーされているよりも多くの新機能を導入していることに注意してください。 決定版ガイド全体を通読して全ての新機能について学習することを強く推奨します。 おそらく、以前は自分自身で開発する必要があったいくつかの機能が、今ではコア・コードの一部になっていることに気付くでしょう。

1.2.1

インストール

すどど 〲〮〰 は、事実上の標準的 ぐえぐ パッケージ管理ソフトである ぃはねばはびづひ4を全面的に採用しています。 コア・フレームワークも、エクステンショ
ンも、インストールは ぃはねばはびづひ を通じて処理されます。 すどど をインストールする のセクションを参照して、すどど 〲〮〰 をインストールする方法を学習してください。 新しいエクステンションを作成したい場合、または既存の 〱〮〱 エクステンションを 〲〮〰 互換のエクステンションに作り直した
い場合は、ガイドの エクステンションを作成する のセクションを参照してください。

1.2.2

PHP の必要条件

すどど 〲〮〰 は ぐえぐ 〵〮〴 以上を必要とします。ぐえぐ 〵〮〴 は、すどど 〱〮〱 によって必要とされていた ぐえぐ 〵〮〲 に比べて、非常に大きく改良されています。 この結果として、注意を払うべき言語レベルでの違いが数多くあります。
以下は ぐえぐ に関する主要な変更点の要約です。
• 名前空間5 。
• 無名関数6 。
• 配列の短縮構文 [...要素...] が array(...要素...) の代りに使われています。
• 短縮形の づっとは タグ <?= がビュー・ファイルに使われています。ぐえぐ〵〮〴 以降は、この形を使っても安全です。
https://getcomposer.org/
https://www.php.net/manual/ja/language.namespaces.php
6
https://www.php.net/manual/ja/functions.anonymous.php
45〴

ぃえぁぐごぅげ 〱〮 導入• こぐが のクラスとインタフェイス7 。
• 遅延静的束縛〨がちぴづ こぴちぴどっ あどのつどのでび〩8 。
• 日付と時刻9 。
• トレイト10 。
• 国際化〨どのぴぬ〩11 。 すどど 〲〮〰 は国際化の機能をサポートするために intl
ぐえぐ 拡張を利用しています。

1.2.3

名前空間

すどど 〲〮〰 での最も顕著な変更は名前空間の使用です。 ほとんど全ての
コア・クラスが、例えば、yii\web\Request のように名前空間に属します。 クラス名に 【ぃ】 の接頭辞はもう使われません。 命名のスキーム
はディレクトリ構造に従うようになりました。 例えば、yii\web\Request
は、対応するクラス・ファイルが すどど フレームワーク・フォルダの下の
web/Request.php であることを示します。
〨全てのコア・クラスは、すどど のクラス・ローダのおかげで、そのクラス・ファイルを明示的にインクルードせずに使うことが出来ます。〩

1.2.4

コンポーネントとオブジェクト

すどど 〲〮〰 は、〱〮〱 の CComponent クラスを二つのクラス、すなわち、べどどぜぢちびづ
ぜあちびづくぢなづっぴ と べどどぜぢちびづぜぃはねばはのづのぴ に分割しました。 あちびづくぢなづっぴ クラ
スは、ゲッターとセッターを通じて オブジェクト・プロパティ を定義
することを可能にする、軽量な基底クラスです。 ぃはねばはのづのぴ クラスは
あちびづくぢなづっぴ からの拡張であり、 イベント と ビヘイビア をサポートします。
あなたのクラスがイベントやビヘイビアの機能を必要としない場合
は、あちびづくぢなづっぴ を基底クラスとして使うことを考慮すべきです。 基本
的なデータ構造を表すクラスに対して、通常、このことが当てはまりま
す。

1.2.5

オブジェクトの構成

あちびづくぢなづっぴ クラスはオブジェクトを構成するための統一された方法を導入しています。 あちびづくぢなづっぴ の全ての派生クラスは、コンストラクタが必要な場合には、インスタンスが正しく構成されるように、 コンストラク
タを以下のようにして宣言しなければなりません。
class MyClass extends \yii\base\BaseObject{
public function __construct($param1, $param2, $config = [])https://www.php.net/manual/ja/book.spl.php
https://www.php.net/manual/ja/language.oop5.late-static-bindings.php
9
https://www.php.net/manual/ja/book.datetime.php
10
https://www.php.net/manual/ja/language.oop5.traits.php
11
https://www.php.net/manual/ja/book.intl.php
78〱〮〲〮 バージョン 〱〮〱 からアップグレードする{}〵// ... 構成情報が適用される前の初期化処理
parent::__construct($config);

public function init(){
parent::init();}}// ... 構成情報が適用された後の初期化処理

上記のように、コンストラクタは最後のパラメータとして構成情報の配列を取らなければなりません。 構成情報の配列に含まれる「名前・値」のペアが、コンストラクタの最後でプロパティを構成します。 どのどぴ〨〩 メ
ソッドをオーバーライドして、 構成情報が適用された後に行うべき初期化処理を行うことが出来ます。
この規約に従うことによって、構成情報配列を使って新しいオブジェ
クトを生成して構成することが 出来るようになります。
$object = Yii::createObject(['class' => 'MyClass','property1' => 'abc','property2' => 'cde',], [$param1, $param2]);

構成情報に関する詳細は、構成情報 のセクションで見ることが出来ま
す。

1.2.6

イベント

すどど 〱 では、イベントは on メソッド 〨例えば、onBeforeSave〩 を定義することによって作成されました。すどど 〲 では、どのようなイベント名でも使うことが出来るようになりました。 ぴひどででづひ〨〩 メソッドを呼んでイベントを発生させます。
$event = new \yii\base\Event;$component->trigger($eventName, $event);

イベントにハンドラをアタッチするためには、はの〨〩 メソッドを使います。
$component->on($eventName, $handler);// ハンドラをデタッチするためには、以下のようにします。
// $component->off($eventName, $handler);

イベントの機能には数多くの改良がなされました。詳細は イベント のセ
クションを参照してください。

〶

1.2.7

ぃえぁぐごぅげ 〱〮 導入

パス・エイリアス

すどど 〲〮〰 は、パス・エイリアスの使用を、ファイル〯ディレクトリのパスとさげが の両方に広げました。 また、すどど 〲〮〰 では、通常のファイル〯ディレ
クトリのパスや さげが と区別するために、エイリアス名は @ という文字で始まることが要求されるようになりました。 例えば、@yii というエイリ
アスは すどど のインストール・ディレクトリを指します。 パス・エイリア
スは すどど のコア・コードのほとんどの場所でサポートされています。 例
えば べどどぜっちっとどのでぜうどぬづぃちっとづ〺〺〤っちっとづぐちぴと はパス・エイリアスと通常のディレクトリ・パスの両方を受け取ることが出来ます。
パス・エイリアスは、また、クラスの名前空間とも密接に関係しています。 ルートの名前空間に対しては、それぞれ、パス・エイリア
スを定義することが推奨されます。 そうすれば、余計な構成をしなくても、すどど のクラス・オートローダを使うことが出来るようになります。 例えば、@yii が すどど のインストール・ディレクトリを指しているので、yii\web\Request というようなクラスをオートロードすることが出来る訳です。 サード・パーティのライブラリ、例えば ずづのつ フレームワークなどを使う場合にも、そのフレームワークのインストール・ディレクト
リを指す @Zend というパス・エイリアスを定義することが出来ます。 一旦そうしてしまえば、その ずづのつ フレームワークのライブラリ内のどんなクラスでも、すどど からオートロードすることが出来るようになります。
パス・エイリアスに関する詳細は エイリアス のセクションを参照してください。

1.2.8

ビュー

すどど 〲 のビューについての最も顕著な変更は、ビューの中の $this という特殊な変数が現在のコントローラやウィジェットを指すものではなくなった、ということです。 今や $this は 〲〮〰 で新しく導入された概念である ビュー・オブジェクトを指します。 ビュー・オブジェクトは べどど
ぜぷづぢぜざどづぷ という型であり、きざぃ パターンのビューの部分を表すものです。 ビューにおいてコントローラやウィジェットにアクセスしたい場合
は、$this->context を使うことが出来ます。
パーシャル・ビューを別のビューの中でレンダリングするためには、$this->renderPartial() ではなく、$this->render() を使います。さらに、render の呼び出しは、〲〮〰 では明示的に づっとは しなくてはなりません。
と言うのは、render() メソッドは、レンダリング結果を返すものであり、それを直接に表示するものではないからです。例えば、
echo $this->render('_item', ['item' => $item]);

ぐえぐ を主たるテンプレート言語として使う以外に、すどど 〲〮〰 は人気のある
二つのテンプレート・エンジン、こねちひぴべ と ごぷどで に対する正式なサポートを備えています。 ぐひちつは テンプレート・エンジンはもはやサポートされていません。 これらのテンプレート・エンジンを使うためには、view〱〮〲〮 バージョン 〱〮〱 からアップグレードする〷

アプリケーション・コンポーネントを構成して ざどづぷ〺〺〤ひづのつづひづひび プロパ
ティをセットする必要があります。 詳細は テンプレート・エンジン のセクションを参照してください。

1.2.9

モデル

すどど 〲〮〰 は 〱〮〱 における CModel と同様な べどどぜぢちびづぜきはつづぬ を基底モデルとして使います。CFormModel というクラスは完全に廃止されました。 すどど 〲では、それの代りに べどどぜぢちびづぜきはつづぬ を拡張して、フォームのモデル・ク
ラスを作成しなければなりません。
すどど 〲〮〰 は サポートされるシナリオを宣言するための びっづのちひどはび〨〩 という新しいメソッドを導入しました。 このメソッドを使って、どのシナリオの下で、ある属性が検証される必要があるか、また、安全とみなされるか否か、などを宣言します。例えば、
public function scenarios(){
return ['backend' => ['email', 'role'],'frontend' => ['email', '!role'],];}上記では二つのシナリオ、すなわち、backend と frontend が宣言されています。 backend シナリオでは、email と role の属性が両方とも安全であり、一括代入が可能です。 frontend シナリオでは、email は一括代入が可能ですが、role は不可能です。email と role は、両方とも、規則を使って検証されなければなりません。
ひふぬづび〨〩 メソッドが、すどど 〱〮〱 に引き続き、検証規則を宣言するために使われます。 びっづのちひどはび〨〩 が導入されたことにより、unsafe バリデータが無くなったことに注意してください。
ほとんどの場合、すなわち、ひふぬづび〨〩 メソッドが存在しうるシナリオ
を完全に指定しており、 そして unsafe な属性を宣言する必要が無い場合
であれば、びっづのちひどはび〨〩 をオーバーライドする必要はありません。
モデルについての詳細を学習するためには、モデル のセクションを参照してください。

1.2.10

コントローラすどど 〲〮〰 は べどどぜぷづぢぜぃはのぴひはぬぬづひ を基底のコントローラ・クラスとして使います。これは すどど 〱〮〱 におけるCController と同様なクラスです。 べどど
ぜぢちびづぜぁっぴどはの がアクション・クラスの基底クラスです。
コントローラに関して、あなたのコードに最も顕著な影響を及ぼす変更点は、 コントローラのアクションは表示したいコンテントを、エコーするのでなく、返さなければならなくなった、ということです。

〸ぃえぁぐごぅげ 〱〮 導入

public function actionView($id){$model = \app\models\Post::findOne($id);
if ($model) {return $this->render('view', ['model' => $model]);} else {throw new \yii\web\NotFoundHttpException;}}

コントローラに関する詳細については コントローラ のセクションを参照
してください。

1.2.11

ウィジェット

すどど 〲〮〰 は べどどぜぢちびづぜしどつでづぴ を基底のウィジェット・クラスとして使用します。これは すどど 〱〮〱 の CWidget と同様なクラスです。
いろんな ぉいぅ においてフレームワークに対するより良いサポートを得るために、すどど 〲〮〰 はウィジェットを使うための新しい構文を導入しました。 スタティックなメソッド ぢづでどの〨〩、づのつ〨〩、そして ぷどつでづぴ〨〩 が導入されました。 以下のようにして使います。
use yii\widgets\Menu;
use yii\widgets\ActiveForm;// 表示するためには結果を "echo" しなければならないことに注意
echo Menu::widget(['items' => $items]);// オブジェクトのプロパティを初期化するための配列を渡す$form = ActiveForm::begin(['options' => ['class' => 'form-horizontal'],'fieldConfig' => ['inputOptions' => ['class' => 'input-xlarge']],]);... ここにフォームの入力フィールド ...
ActiveForm::end();詳細については ウィジェット のセクションを参照してください。

1.2.12

テーマ

テーマは 〲〮〰 では完全に違う動き方をします。 テーマは、ソースのビュー・ファイル・パスをテーマのビュー・ファイル・パスにマップするパス・マッピング機構に基づくものになりました。 例えば、あるテーマのパス・マップが ['/web/views' => '/web/themes/basic'] である場合、ビュー・ファイル /web/views/site/index.php のテーマ版は /web/themes/basic/site/index.phpになります。 この理由により、テーマはどのようなビュー・ファイルに対してでも適用することが出来るようになりました。 コントローラや
ウィジェットのコンテキストの外で表示されるビューに対してすら、適用できます。

〱〮〲〮 バージョン 〱〮〱 からアップグレードする〹

また、CThemeManager コンポーネントはもうありません。 その代りに、theme は view アプリケーション・コンポーネントの構成可能なプロパ
ティになりました。
詳細については テーマ のセクションを参照してください。

1.2.13コンソール・アプリケーション

コンソール・アプリケーションは、ウェブ・アプリケーションと同じように、コントローラとして編成されるようになりました。 〱〮〱 における CConsoleCommand と同様に、コンソール・コントローラは べどどぜっはのびはぬづ
ぜぃはのぴひはぬぬづひ を拡張したものでなければなりません。
コンソール・コマンドを走らせるためには、yii <route> という構文を使います。 ここで <route> はコントローラのルート 〨例えば sitemap/index〩を表します。 追加の無名の引数は、対応するコントローラのアクショ
ン・メソッドに引数として渡されます。 一方、名前付きの引数は、べどど
ぜっはのびはぬづぜぃはのぴひはぬぬづひ〺〺はばぴどはのび〨〩 での宣言に従って解析されます。
すどど 〲〮〰 はコメント・ブロックからコマンドのヘルプ情報を自動的に生成する機能をサポートしています。
詳細については コンソール・コマンド のセクションを参照してください。

1.2.14

国際化

すどど 〲〮〰 は ぐぅぃが どのぴぬ ぐえぐ モジュール12 に賛同して、内蔵の日付フォー
マッタと数字フォーマッタの部品を取り除きました。
メッセージは i18n アプリケーション・コンポーネント経由で翻訳されるようになりました。 このコンポーネントは一連のメッセージ・ソー
スを管理するもので、 メッセージのカテゴリに基づいて異なるメッセー
ジ・ソースを使うことを可能にするものです。
詳細については 国際化 のセクションを参照してください。

1.2.15

アクション・フィルタ

アクシ ョン・フィ ルタはビヘ イビアによ って実装される ようになり
ま し た 。 新 し い カ ス タ ム ・ フ ィ ル タ を 定 義 す る た め に は 、べどどぜぢちびづ
ぜぁっぴどはのうどぬぴづひ を拡張します。 フィルタを使うためには、そのフィル
タ・クラスをビヘイビアとしてコントローラにアタッチします。 例え
ば、べどどぜてどぬぴづひびぜぁっっづびびぃはのぴひはぬ フィルタを使うためには、コントロー
ラに次のコードを書くことになります。
public function behaviors(){
return ['access' => [12https://pecl.php.net/package/intl

〱〰

}

ぃえぁぐごぅげ 〱〮 導入];],'class' => 'yii\filters\AccessControl','rules' => [['allow' => true, 'actions' => ['admin'], 'roles' => ['@']],],

詳細については フィルタ のセクションを参照してください。

1.2.16

アセット

すどど 〲〮〰 は、アセット・バンドル と呼ばれる新しい概念を導入しました。
これは、すどど 〱〮〱 にあったスクリプト・パッケージの概念を置き換えるものです。
アセット・バンドルは、あるディレクトリの下に集められた一群のアセット・ファイル 〨例えば、おちぶちこっひどばぴ ファイル、ぃここ ファイル、イメージ・ファイルなど〩 です。 それぞれのアセット・バンドルは べどどぜぷづぢ
ぜぁびびづぴあふのつぬづ を拡張したクラスとして表わされます。 アセット・バン
ドルを べどどぜぷづぢぜぁびびづぴあふのつぬづ〺〺ひづでどびぴづひ〨〩 を通じて登録することによって、 そのバンドルに含まれるアセットにウェブ経由でアクセスできるよ
うになります。 すどど 〱 とは異なり、バンドルを登録したページは、そのバンドルで指定されている おちぶちこっひどばぴ と ぃここ ファイルへの参照を自動的に含むようになります。
詳細については アセット のセクションを参照してください。

1.2.17ヘルパ

すどど 〲〮〰 はよく使われるスタティックなヘルパ・クラスを数多く導入しま
した。それには以下のものが含まれます。
• べどどぜとづぬばづひびぜえぴねぬ• べどどぜとづぬばづひびぜぁひひちべえづぬばづひ• べどどぜとづぬばづひびぜこぴひどのでえづぬばづひ• べどどぜとづぬばづひびぜうどぬづえづぬばづひ• べどどぜとづぬばづひびぜおびはの詳細については、ヘルパの概要 のセクションを参照してください。

1.2.18

フォーム

すどど 〲〮〰 は べどどぜぷどつでづぴびぜぁっぴどぶづうはひね を使ってフォームを作成する際に使用する フィールド の概念を導入しました。 フィールドは、ラベル、イ
ンプット、エラー・メッセージ および〯または ヒント・テキストを含むコンテナです。 フィールドは ぁっぴどぶづうどづぬつ のオブジェクトとして表現されます。 フィールドを使うことによって、以前よりもすっきりとフォー
ムを作成することが出来るようになりました。

〱〮〲〮 バージョン 〱〮〱 からアップグレードする〱〱<?php $form = yii\widgets\ActiveForm::begin(); ?><? = $form->field($model, 'username') ?><? = $form->field($model, 'password')->passwordInput() ?><div class="form-group"><? = Html::submitButton('ログイン') ?></div><?php yii\widgets\ActiveForm::end(); ?>詳細については フォームを作成する のセクションを参照してください。

1.2.19

クエリ・ビルダ〱〮〱 においては、クエリの構築が CDbCommand、CDbCriteria、CDbCommandBuilderなど、いくつかのクラスに散らばっていました。 すどど 〲〮〰 は いあ クエリ
を けふづひべ オブジェクトの形で表現します。 このオブジェクトが舞台裏でけふづひべあふどぬつづひ の助けを得て こけが 文に変換されます。 例えば、
$query = new \yii\db\Query();$query->select('id, name')->from('user')->limit(10);$command = $query->createCommand();$sql = $command->sql;$rows = $command->queryAll();

何より良いのは、このようなクエリ構築メソッドが アクティブ・レコー
ド を扱う時にも使える、ということです。
詳細については クエリ・ビルダ のセクションを参照してください。

1.2.20

アクティブ・レコード

すどど 〲〮〰 は アクティブ・レコード に数多くの変更を導入しました。 最も顕著な違いは、クエリの構築方法とリレーショナル・クエリの処理の二つです。
〱〮〱 の CDbCriteria クラスは すどど 〲 では べどどぜつぢぜぁっぴどぶづけふづひべ に置き換えられました。このクラスは べどどぜつぢぜけふづひべ を拡張したものであり、従って全てのクエリ構築メソッドを継承します。 以下のように、べどどぜつぢ
ぜぁっぴどぶづげづっはひつ〺〺てどのつ〨〩 を呼んでクエリの構築を開始します。
// 全てのアクティブな顧客を読み出し、ID によって並べる$customers = Customer::find()->where(['status' => $active])->orderBy('id')->all();

リレーションを宣言するために必要なことは、ぁっぴどぶづけふづひべ オブジェク
トを返す でづぴぴづひ メソッドを定義するだけのことです。 でづぴぴづひ によって定義されたプロパティの名前がリレーションの名前を表します。例え〱〲

ぃえぁぐごぅげ 〱〮 導入

ば、以下のコードは orders リレーションを宣言するものです 〨〱〮〱 では
relations() という一個の中枢でリレーションを宣言しなければなりませんでした〩。
class Customer extends \yii\db\ActiveRecord{
public function getOrders(){
return $this->hasMany('Order', ['customer_id' => 'id']);}}

こうすることで、$customer->orders という構文によって関連テーブルにある顧客のオーダにアクセスすることが出来るようになります。 また、下記のコードを用いて、カスタマイズしたクエリ条件によるリレーショナ
ル・クエリをその場で実行することも出来ます。
$orders = $customer->getOrders()->andWhere('status=1')->all();

リレーションをイーガー・ロードするとき、すどど 〲〮〰 は 〱〮〱 とは異なる動きをします。 具体的に言うと、〱〮〱 では おくぉぎ クエリが生成されて、主レコードと関連レコードの両方がセレクトされていました。 すどど 〲〮〰 では、おくぉぎ を使わずに二つの こけが 文が実行されます。 すなわち、第一のこけが 文が主たるレコードを返し、第二の こけが 文は主レコードのプライマ
リ・キーを使うフィルタリングによって関連レコードを返します。
多数のレコードを返すクエリを構築するときは、ぁっぴどぶづげづっはひつ オブジェクトを返す代りに、ちびぁひひちべ〨〩 メソッドをチェインすることが出来ます。 そうすると、クエリ結果は配列として返されることになり、レ
コードの数が多い場合は、必要とされる ぃぐさ 時間とメモリを著しく削減
することが出来ます。 例えば、
$customers = Customer::find()->asArray()->all();

もう一つの変更点は、属性のデフォルト値を ばふぢぬどっ なプロパティによって定義することは出来なくなった、ということです。 デフォルト値を定義する必要がある場合は、アクティブ・レコード・クラスの init メソッドの中で設定しなければなりません。
public function init(){
parent::init();$this->status = self::STATUS_NEW;}〱〮〱 では、アクティブ・レコード・クラスのコンストラクタをオーバーラ
イドすることについて、いくつか問題がありました。バージョン 〲〮〰 では、もう問題はありません。 コンストラクタにパラメータを追加する場〱〮〲〮 バージョン 〱〮〱 からアップグレードする〱〳

合は、べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺どのびぴちのぴどちぴづ〨〩 をオーバーライドする必要があるかもしれないことに注意してください。
アクティブ・レコードについては、他にも多くの変更と機能強化がなされています。 詳細については アクティブ・レコード のセクションを参照してください。

1.2.21

アクティブ・レコードのビヘイビア〲〮〰 では基底のビヘイビア・クラス CActiveRecordBehavior を廃止しました。 アクティブ・レコードのビヘイビアを作成したいときは、直接に
yii\base\Behavior を拡張しなければなりません。 ビヘイビア・クラスがオーナーの何らかのイベントに反応する必要がある場合は、以下のように events() メソッドをオーバーライドしなければなりません。
namespace app\components;
use yii\db\ActiveRecord;
use yii\base\Behavior;class MyBehavior extends Behavior{// ...
public function events(){
return [ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',];}}public function beforeValidate($event){// ...
}

1.2.22User と IdentityInterface〱〮〱 の CWebUser クラスは べどどぜぷづぢぜさびづひ に取って換られました。 そして
CUserIdentity クラスはもうありません。代りに、使い方がもっと単純な
べどどぜぷづぢぜぉつづのぴどぴべぉのぴづひてちっづ を実装しなければなりません。 アドバンス
ト・プロジェクト・テンプレートがそういう例を提供しています。
詳細は 認証、権限付与、そして アドバンスト・プロジェクト・テン
プレート13 のセクションを参照してください。
13
https://www.yiiframework.com/extension/yiisoft/yii2-app-advanced/doc/
guide

〱〴

ぃえぁぐごぅげ 〱〮 導入

1.2.23

URL 管理すどど 〲 の さげが 管理は 〱〮〱 のそれと似たようなものです。 主な機能強化
は、さげが 管理がオプションのパラメータをサポートするようになったことです。 例えば、下記のような規則を宣言した場合に、post/popular とpost/1/popular の両方に合致するようになります。 〱〮〱 では、同じ目的を達成するためには、二つの規則を使う必要がありました。
[]'pattern' => 'post/<page:\d+>/<tag>','route' => 'post/index','defaults' => ['page' => 1],

詳細については ルーティングと さげが 生成 のセクションを参照してください。
ルートの命名規約における重要な変更は、コントローラとアクションのキャメル・ケースの名前が 各単語をハイフンで分けた小文字の名前になるようになった、という点です。 例えば、CamelCaseController のコント
ローラ ぉい は camel-case となります。 詳細については、コントローラ ぉいと アクション ぉい のセクションを参照してください。

1.2.24Yii 1.1 と 2.x を一緒に使う

すどど 〲〮〰 と一緒に使いたい すどど 〱〮〱 のレガシー・コードを持っている場合
は、 すどど 〱〮〱 と 〲〮〰 を一緒に使う のセクションを参照してください。

Chapter 2

始めよう
2.1

何を知っている必要があるか

すどど の学習曲線は他の ぐえぐ フレームワークほど急峻ではありませんが、
それでも すどど を使い始める前に学習すべき事がいくつかはあります。

2.1.1

PHP

すどど は ぐえぐ フレームワークですから、必ず 言語リファレンスを読んで理解する1 ようにして下さい。 すどど を使って開発するときはオブジェクト指向の流儀でコードを書くことになりますから、必ず、クラスとオブジェ
クト2 および 名前空間3 には慣れ親しんでおいて下さい。

2.1.2

オブジェクト指向プログラミング

オブジェクト指向プログラミングの基礎的な理解が必要です。これに慣れていない場合は、利用できるチュートリアルが沢山ありますので、その中の一つをチェックして下さい。 例えば、ぴふぴび〫 の中の一つ4 など。
あなたのアプリケーションが複雑であればあるほど、その複雑性をうまく管理するために、 より高度な くくぐ 概念を学ぶ必要があることに留意して下さい。

2.1.3

コマンド・ラインと Composer

すどど は業界標準の ぐえぐ パッケージ管理ソフトである ぃはねばはびづひ5 を広範囲に使用していますので、必ずその ガイド6 を読んで理解して下さい。 あ
なたがコマンド・ラインの使用に慣れていないのであれば、今こそ使いhttps://www.php.net/manual/ja/langref.php
https://www.php.net/manual/ja/language.oop5.basic.php
3
https://www.php.net/manual/ja/language.namespaces.php
4
https://code.tutsplus.com/tutorials/object-oriented-php-for-beginners--net-12762
5
https://getcomposer.org/
6
https://getcomposer.org/doc/01-basic-usage.md
1
2

〱〵

〱〶

ぃえぁぐごぅげ 〲〮 始めよう

始めてみるべき時です。 いったん基礎さえ学習してしまえば、二度とコ
マンド・ラインなしで仕事をしようとは思わなくなりますよ。

Yii をインストールする

2.2

すどど は二つの方法でインストールすることが出来ます。すなわち、ぃはねばはびづひ7を使うか、アーカイブ・ファイルをダウンロードするかです。 前者がお薦めの方法です。と言うのは、一つのコマンドを走らせるだけで、新しい エクステンション をインストールしたり、すどど をアップデートしたりすることが出来るからです。
すどど の標準的なインストールを実行すると、フレームワークとプロ
ジェクト・テンプレートの両方がダウンロードされてインストールされます。 プロジェクト・テンプレートは、いくつかの基本的な機能、例えば、ログインやコンタクト・フォームなどを実装した、動作する すどど ア
プリケーションです。 そのコードは推奨される方法に従って編成されています。そのため、プロジェクト・テンプレートは、あなたのプロジェクトのための良い開始点としての役割を果たしうるものです。
ここから続くいくつかのセクションにおいては、いわゆる ベーシッ
ク・プロジェクト・テンプレート とともに すどど をインストールする方
法、 および、このテンプレートの上に新しい機能を実装する方法を説明します。 すどど はもう一つ、アドバンスト・プロジェクト・テンプレート8と呼ばれるテンプレートも提供しています。 こちらは、チーム開発環境
において多層構造のアプリケーションを開発するときに使用する方が望ましいものです。
情報〺 ベーシック・プロジェクト・テンプレートは、ウェブ・
アプリケーションの 〹〰 パーセントを開発するのに適したものです。 アドバンスト・プロジェクト・テンプレートとの主な違いは、コードがどのように編成されているかという点にあります。 あなたが すどど は初めてだという場合は、シンプルでありながら十分な機能を持っているベーシック・プロジェク
ト・テンプレートに留まることを強く推奨します。

2.2.1

Composer によるインストール

ぃはねばはびづひ をインストールする
まだ ぃはねばはびづひ をインストールしていない場合は、でづぴっはねばはびづひ〮はひで9 の指示に従ってインストールすることが出来ます。 がどのふへ や きちっ くこ じ では、次のコマンドを実行します。
https://getcomposer.org/
https://www.yiiframework.com/extension/yiisoft/yii2-app-advanced/doc/
guide
9
https://getcomposer.org/download/
78〲〮〲〮 すぉぉ をインストールする〱〷

curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer

しどのつはぷび では、ぃはねばはびづひ〭こづぴふば〮づへづ10 をダウンロードして実行します。
何 か 問 題 が 生 じ た と き は 、ぃはねばはびづひ ド キ ュ メ ン ト の ト ラ ブ ル ・シューティングのセクション11 を参照してください。 ぃはねばはびづひ は初めてだという場合は、少なくとも、ぃはねばはびづひ ドキュメントの 基本的な使い方のセクション12 も参照することを推奨します。
このガイドでは、っはねばはびづひ のコマンドの全ては、あなたが っはねばはびづひを グローバル13 にインストールし、 composer コマンドとして使用できるようにしているものと想定しています。 そうではなく、ローカル・ディ
レクトリにある composer.phar を使おうとする場合は、例に出てくるコマ
ンドをそれに合せて修正しなければなりません。
以前に ぃはねばはびづひ をインストールしたことがある場合は、確実に最新のバージョンを使うようにしてください。 ぃはねばはびづひ は composer
self-update コマンドを実行してアップデートすることが出来ます。
補足〺 すどど のインストールを実行する際に、ぃはねばはびづひ は大量の情報を ぇどぴとふぢ ぁぐぉ から要求する必要が生じます。 リクエ
ストの数は、あなたのアプリケーションが持つ依存の数によりますが、ぇどぴとふぢ ぁぐぉ レート制限 より大きくなることがあり得ます。 この制限にかかった場合、ぃはねばはびづひ は ぇどぴとふぢぁぐぉ アクセス・トークンを取得するために、あなたの ぇどぴとふぢ
ログイン認証情報を要求するでしょう。 高速な接続においては、ぃはねばはびづひ が対処できるよりも早い段階でこの制限にかかることもありますので、 すどど のインストールの前に、このア
クセス・トークンを構成することを推奨します。 アクセス・
トークンの構成の仕方については、ぇどぴとふぢ ぁぐぉ トークンに関する ぃはねばはびづひ ドキュメント14 の指示を参照して下さい。
すどど をインストールする
ぃはねばはびづひ がインストールされたら、ウェブ・アクセス可能なフォルダで下記のコマンドを実行することによって すどど アプリケーション・テンプ
レートをインストールすることが出来ます。
composer create-project --prefer-dist yiisoft/yii2-app-basic basic

このコマンドが basic という名前のディレクトリに すどど アプリケーショ
ン／テンプレートの最新の安定版をインストールします。 必要なら別のディレクトリ名を選ぶことも出来ます。
https://getcomposer.org/Composer-Setup.exe
https://getcomposer.org/doc/articles/troubleshooting.md
12
https://getcomposer.org/doc/01-basic-usage.md
13
https://getcomposer.org/doc/00-intro.md#globally
14
https://getcomposer.org/doc/articles/troubleshooting.md#
api-rate-limit-and-oauth-tokens
10
11

〱〸

ぃえぁぐごぅげ 〲〮 始めよう
情報〺 composer create-project コマンドが失敗するときは、 よ
くあるエラーについて ぃはねばはびづひ ドキュメントのトラブル・
シューティングのセクション15 を参照して下さい。 エラーを修正した後は、basic ディレクトリの中で composer update を実行して、 中断されたインストールを再開することが出来ます。
ヒント〺 すどど の最新の開発バージョンをインストールしたい場
合は、びぴちぢどぬどぴべ はばぴどはの16 を追加した次のコマンドを代りに使うことが出来ます。
composer create-project --prefer-dist --stability=dev
yiisoft/yii2-app-basic basic

開発バージョンは動いているあなたのコードを動かなくするかもしれませんので、本番環境では使うべきでないことに注意してください。

2.2.2

アーカイブ・ファイルからインストールする

アーカイブ・ファイルから すどど をインストールするには、三つの手順を踏みます。
〱〮 べどどてひちねづぷはひに〮っはね17 からアーカイブ・ファイルをダウンロードします。
〲〮 ダウンロードしたファイルをウェブ・アクセス可能なフォルダに展開します。
〳〮 config/web.php ファイルを編集して、cookieValidationKey という構成
情報の項目に秘密キーを入力します 〨ぃはねばはびづひ を使って すどど をインストールするときは、これは自動的に実行されます〩。
// !!! 下記に(もし空白なら)秘密キーを入力する - これはクッキー検証のために必要'cookieValidationKey' => '秘密キーをここに入力',

2.2.3

他のインストール・オプション

上記のインストール方法の説明は すどど のインストールの仕方を示すものですが、それは同時に、直ちに動作する基本的なウェブ・アプリケーショ
ンを作成するものでもあります。 これは、規模の大小に関わらず、ほとんどのプロジェクトを開始するのに良い方法です。 特に、すどど の学習を始めたばかりの場合には、この方法が適しています。
しかし、他のインストール・オプションも利用可能です。
https://getcomposer.org/doc/articles/troubleshooting.md
https://getcomposer.org/doc/04-schema.md#minimum-stability
17
https://www.yiiframework.com/download/
15
16〲〮〲〮 すぉぉ をインストールする〱〹• コア・フレームワークだけをインストールし、アプリケーション全
体を一から構築したい場合は、アプリケーションを一から構築するで説明されている指示に従うことが出来ます。
• もっと洗練された、チーム開発環境により適したアプリケーションから開始したい場合は、 アドバンスト・プロジェクト・テンプレー
ト18 をインストールすることを考慮することが出来ます。

2.2.4

アセットをインストールする

すどど は、アセット 〨ぃここ および おちぶちこっひどばぴ〩 ライブラリのインストール
について あはぷづひ19 および〯または ぎぐき20 のパッケージに依存しています。 すどど はこれらのライブラリを取得するのに ぃはねばはびづひ を使って、ぐえぐと ぃここ〯おちぶちこっひどばぴ のパッケージ・バージョンを同時に解決できるようにしています。 このことは、ちびびづぴ〭ばちっにちでどびぴ〮はひで21 または っはねばはびづひ ちびびづぴ
ばぬふでどの22 を使用することによって達成されます。 詳細は アセットのドキュメント を参照して下さい。
あなたは、アセットの管理をネイティブの あはぷづひ〯ぎぐき クライアントで行ったり、ぃぎい を使ったり、アセットのインストールを完全に避けたりしたいかも知れません。 ぃはねばはびづひ によるアセットのインストールを抑止するためには、composer.json に次の記述を追加して下さい。
"replace": {"bower-asset/jquery": ">=1.11.0","bower-asset/inputmask": ">=3.2.0","bower-asset/punycode": ">=1.3.0","bower-asset/yii2-pjax": ">=2.0.0"},

補足〺 ぃはねばはびづひ によるアセットのインストールをバイパスする場合は、アセットのインストールとバージョン衝突の解決についてあなたが責任を持たなければなりません。 さまざまなエクステンションに由来するアセット・ファイル間で不整合が生じうることを覚悟して下さい。

2.2.5

インストールを検証する

インストール完了後、あなたのウェブ・サーバを構成してください 〨次のセクションを参照してください〩。 あるいは、プロジェクトの web ディレ
クトリで次のコマンドを実行して、 ぐえぐ の内蔵ウェブ・サーバ23 を使ってください。
https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/
README.md19
https://bower.io/20
https://www.npmjs.com/
21
https://asset-packagist.org
22
https://github.com/fxpio/composer-asset-plugin
23
https://www.php.net/manual/ja/features.commandline.webserver.php
18

〲〰

ぃえぁぐごぅげ 〲〮 始めよう

php yii serve補足〺 デフォルトでは、この えごごぐ サーバは 〸〰〸〰 ポートをリスンします。しかし、このポートがすでに使われていたり、
複数のアプリケーションをこの方法で動かしたい場合は、 どのポートを使うかを指定したいと思うでしょう。単に 〕ばはひぴ
引数を追加して下さい。
php yii serve --port=8888

下記の さげが によって、インストールされた すどど アプリケーションにブラウザを使ってアクセスすることが出来ます。
http://localhost:8080/

ブラウザに上のような 【おめでとう〡【 のページが表示されるはずです。もし表示されなかったら、ぐえぐ のインストールが すどど の必要条件を満たしているかどうか、チェックしてください。 最低限の必要条件を満たしているかどうかは、次の方法のどちらかによってチェックすることが出来ます。
• /requirements.php を /web/requirements.php としてコピーし、ブラウザを使って さげが http://localhost/requirements.php にアクセスする。
• 次のコマンドを実行する。
cd basic
php requirements.php

すどど の最低必要条件を満たすように ぐえぐ のインストールを構成しなければなりません。 最も重要なことは、ぐえぐ 〵〮〴 以上でなければならないと〲〮〲〮 すぉぉ をインストールする〲〱いうことです。最新の ぐえぐ 〷 なら理想的です。 また、アプリケーション
がデータベースを必要とする場合は、ぐいく ぐえぐ 拡張24 および対応する
データベース・ドライバ 〨きべこけが データベースのための pdo_mysql など〩
をインストールしなければなりません。

2.2.6

ウェブ・サーバを構成する

情報〺 もし すどど の試運転をしているだけで、本番サーバに配備する意図がないのであれば、 当面、この項は飛ばしても構いません。
上記の説明に従ってインストールされたアプリケーションは、ぁばちっとづ
えごごぐ サーバ25 と ぎでどのへ えごごぐ サーバ26 のどちらでも、また、しどのつはぷび、きちっくこ じ、がどのふへ のどれでも、 ぐえぐ 〵〮〴 以上を走らせている環境であれば、そのままの状態で動作するはずです。 すどど 〲〮〰 は、また、てちっづぢははに の
ええざき27 とも互換性があります。 ただし ええざき がネイティブの ぐえぐとは異なる振舞いをする特殊なケースもいくつかありますので、ええざきを使うときはいくらか余分に注意を払う必要があります。
本番用のサーバでは、https://www.example.com/basic/web/index.php の代
りに https://www.example.com/index.php という さげが でアプリケーションにアクセス出来るようにウェブ・サーバを設定したいでしょう。 そういう設定をするためには、ウェブ・サーバのドキュメント・ルートをbasic/web フォルダに向けることが必要になります。 また、ルーティングと さげが 生成 のセクションで述べられているように、さげが から index.php
を隠したいとも思うでしょう。 この項では、これらの目的を達するために ぁばちっとづ または ぎでどのへ サーバをどのように設定すれば良いかを学びます。
情 報〺 basic/web を ド キ ュ メ ン ト ・ ル ー ト に 設 定 す る こ とは、basic/web の兄弟ディレクトリに保存されたプライベー
トなアプリケーション・コードや 公開できないデータ・ファ
イルにエンド・ユーザがアクセスすることを防止することにもなります。 basic/web 以外のフォルダに対するアクセスを拒否することはセキュリティ強化の一つです。
情報〺 あなたがウェブ・サーバの設定を修正する権限を持たない共用ホスティング環境でアプリケーションが走る場合であっても、 セキュリティ強化のためにアプリケーションの構造を調整することがまだ出来ます。 詳細については、共有ホスティング環境 のセクションを参照してください。
https://www.php.net/manual/ja/pdo.installation.php
https://httpd.apache.org/
26
https://nginx.org/
27
https://hhvm.com/
24
25

〲〲

ぃえぁぐごぅげ 〲〮 始めよう
情報〺 あなたのアプリケーションをリバース・プロキシの背後で動かそうとする場合は、 リクエスト・コンポーネントの 信
頼できるプロキシとヘッダ を構成する必要があるかもしれま
せん。

推奨される ぁばちっとづ の構成
下記の設定を ぁばちっとづ の httpd.conf ファイルまたはバーチャル・ホスト設定の中で使います。 path/to/basic/web の部分を basic/web の実際のパスに置き換えなければならないことに注意してください。
# ドキュメント・ルートを "basic/web" に設定
DocumentRoot "path/to/basic/web"<Directory "path/to/basic/web"># 綺麗な URL をサポートするために mod_rewrite を使う
RewriteEngine on# UrlManager の $showScriptName が false の場合は、スクリプト名で URL に
アクセスすることを許さない
RewriteRule ^index.php/ - [L,R=404]# ディレクトリかファイルが存在する場合は、リクエストをそのまま通す
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d# そうでなければ、リクエストを index.php に送付する
RewriteRule . index.php# ... 他の設定 ...
</Directory>

推奨される ぎでどのへ の構成
ぎでどのへ28 を使うためには、ぐえぐ を うぐき こぁぐぉ29 としてインストールしなければなりません。 下記の ぎでどのへ の設定を使うことができます。
path/to/basic/web の部分を basic/web の実際のパスに置き換え、mysite.test
を実際のサーバのホスト名に置き換えてください。
server {charset utf-8;
client_max_body_size 128M;
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name mysite.test;root/path/to/basic/web;28
29

https://www.nginx.com/resources/wiki/
https://www.php.net/manual/ja/install.fpm.php〲〮〲〮 すぉぉ をインストールする
index

index.php;

access_log
error_log/path/to/basic/log/access.log;/path/to/basic/log/error.log;〲〳

location / {# 本当のファイルでないものは全て index.php にリダイレクト
try_files $uri $uri/ /index.php$is_args$args;}# 存在しない静的ファイルの呼び出しを Yii に処理させたくない場合はコメントを外す#location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {#try_files $uri =404;#}#error_page 404 /404.html;# /assets ディレクトリの php ファイルへのアクセスを拒否する
location ~ ^/assets/.*\.php$ {deny all;}location ~ \.php$ {include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;fastcgi_pass 127.0.0.1:9000;#fastcgi_pass unix:/var/run/php5-fpm.sock;
try_files $uri =404;}
location ~* /\. {deny all;}}

この構成を使う場合は、多数の不要な stat() システム・コールを避けるために、 php.ini ファイルで cgi.fix_pathinfo=0 を同時に設定しておくべきです。
また、えごごぐこ サーバを走らせている場合には、安全な接続であることを すどど が正しく検知できるように、 fastcgi_param HTTPS on; を追加しなければならないことにも注意を払ってください。
推奨される ぎぇぉぎじ さのどぴ の構成ぎぇぉぎじ さのどぴ30 と ぐえぐ 言語モジュールを使って すどど ベースのアプリを走らせることが出来ます。 その構成のサンプルです。
{"listeners": {"*:80": {30

https://unit.nginx.org/

〲〴ぃえぁぐごぅげ 〲〮 始めよう},}

"pass": "routes/yii""routes": {"yii": [{"match": {"uri": ["!/assets/*","*.php","*.php/*"
]
},

},
{

},

]

}

"action": {"pass": "applications/yii/direct"}"action": {"share": "/path/to/app/web/","fallback": {"pass": "applications/yii/index"}}"applications": {"yii": {"type": "php","user": "www-data","targets": {"direct": {"root": "/path/to/app/web/"
},

}

}

}

}

"index": {"root": "/path/to/app/web/","script": "index.php"}

また、自分の ぐえぐ 環境を セットアップ31 したり、この同じ構成でカス
タマイズした php.ini を提供したりすることも出来ます。
31

https://unit.nginx.org/configuration/#php

〲〮〳〮 アプリケーションを走らせる〲〵

ぉぉこ の構成
ドキュメント・ルートが path/to/app/web フォルダを指し、ぐえぐ を実行するように構成された仮想ホスト 〨ウェブ・サイト〩 でアプリケーションをホストすることを推奨します。その web フォルダに web.config という名前のファイル、すなわち path/to/app/web/web.config を配置しなければなりません。ファイルの内容は以下の通りです。
<?xml version="1.0" encoding="UTF-8"?><configuration><system.webServer><directoryBrowse enabled="false" /><rewrite><rules><rule name="Hide Yii Index" stopProcessing="true"><match url="." ignoreCase="false" /><conditions><add input="{REQUEST_FILENAME}" matchType="IsFile"ignoreCase="false" negate="true" /><add input="{REQUEST_FILENAME}" matchType="IsDirectory"
ignoreCase="false" negate="true" /></conditions><action type="Rewrite" url="index.php" appendQueryString="true" /></rule></rules></rewrite></system.webServer></configuration>

また、ぉぉこ 上で ぐえぐ を構成するためには、以下にリストした きどっひはびはてぴの公式リソースが有用でしょう。
〱〮 ぉぉこ の最初の しづぢ サイトを構成する方法32〲〮 ぃはの〜でふひづ ち ぐえぐ しづぢびどぴづ はの ぉぉこ33

2.3

アプリケーションを走らせる

すどど のインストールが終ると、実際に動く すどど のアプリケーションにアクセスすることが出来ます。 その さげが は、https://hostname/basic/web/index.php
あるいは https://hostname/index.php など、設定によって異なります。 このセクションでは、アプリケーションに組み込み済みの機能を紹介し、コードがどのように編成されているか、 そして、一般にアプリケーショ
ンがリクエストをどのように処理するかを説明します。
https://support.microsoft.com/ja-jp/help/323972/
how-to-set-up-your-first-iis-web-site33
https://docs.microsoft.com/en-us/iis/application-frameworks/
scenario-build-a-php-website-on-iis/configure-a-php-website-on-iis32〲〶

ぃえぁぐごぅげ 〲〮 始めよう
情報〺 話を簡単にするために、この「始めよう」のチュートリ
アルを通じて、basic/web をウェブ・サーバのドキュメント・
ルートとして設定したと仮定します。 そして、アプリケー
ションにアクセスするための さげが は https://hostname/index.php
またはそれに似たものになるように設定したと仮定します。
必要に応じて、説明の中の さげが を読み替えてください。

フレームワークそのものとは異なり、プロジェクト・テンプレートはインストール後は完全にあなたのものであることに注意してください。 必要に応じてコードを追加したり削除したり、完全に書き換えたりするのはあなたの自由です。

2.3.1

機能

インストールされたベーシック・アプリケーションは四つのページを持っています。
• ホームページ〺 https://hostname/index.php の さげが にアクセスすると表示されます。
• 「について」のページ。
• 「コンタクト」のページ〺 エンド・ユーザがメールであなたに連絡を取ることが出来るコンタクト・フォームが表示されます。
• 「ログイン」ページ〺 エンド・ユーザを認証するためのログイン・フォームが表示されます。 【ちつねどの〯ちつねどの】 でログインしてみてください。「ログイン」のメイン・メニュー項目が「ログアウト」に変ることに気付くでしょう。
これらのページは共通のヘッダとフッタを持っています。 ヘッダには、異なるページ間を行き来することを可能にするメイン・メニュー・バー
があります。
ブラウザのウィンドウの下部にツールバーがあることにも気がつくはずです。 これは すどど によって提供される便利な デバッグ・ツール34 であり、たくさんのデバッグ情報、例えば、ログ・メッセージ、レスポンスのステータス、実行されたデータベース・クエリなどを記録して表示するものです。
ウェブ・アプリケーションに加えて、yii というコンソール・スクリ
プトがアプリケーションのベース・ディレクトリにあります。 このスクリプトは、バックグラウンドのタスクまたはメンテナンスのタスクを実行するために使用することが出来ます。 これについては、コンソール・
アプリケーションのセクション で説明されています。

2.3.2

アプリケーションの構造

アプリケーションにとって最も重要なディレクトリとファイルは 〨アプリ
34

md

https://github.com/yiisoft/yii2-debug/blob/master/docs/guide-ja/README.

〲〮〳〮 アプリケーションを走らせる〲〷

ケーションのルート・ディレクトリが basic だと仮定すると〩 以下の通りです。

basic/
アプリケーションのベース・パス
composer.json
Composer によって使用される。パッケージ情報を記述
config/アプリケーションその他の構成情報を格納
console.php
コンソール・アプリケーションの構成情報
web.php
ウェブ・アプリケーションの構成情報
commands/
コンソール・コマンドのクラスを格納
controllers/
コントローラのクラスを格納
models/モデルのクラスを格納
runtime/
実行時に Yii によって生成されるファイル (ログやキャッシュなど) を格納
vendor/
インストールされた Composer パッケージ (Yii フレーム
ワークそのものを含む) を格納
views/
ビュー・ファイルを格納
web/
アプリケーションのウェブ・ルート。ウェブ・アクセス可能なファイルを格納
assets/Yii によって発行されるアセット・ファイル (javascriptと CSS) を格納
index.php
アプリケーションのエントリ・スクリプト (ブートストラッ
プ・スクリプト)yii
Yii コンソール・コマンド実行スクリプト

一般に、アプリケーションのファイルは二種類に分けることが出来ます。すなわち、basic/web の下にあるファイルとその他のディレクトリの下にあるファイルです。 前者は えごごぐ で 〨すなわちブラウザで〩 直接にアクセスすることが出来ますが、後者は直接のアクセスは出来ません
し、許可すべきでもありません。
すどど は モデル・ビュー・コントローラ 〨きざぃ〩35 アーキテクチャ・パターンを実装していますが、 それが上記のディレクトリ構成にも反映されています。 models ディレクトリが全ての モデル・クラス を格納し、views ディレクトリが全ての ビュー・スクリプト を格納し、controllers ディレクトリが全ての コントローラ・クラス を格納しています。
次の図がアプリケーションの静的な構造を示すものです。

35

https://wikipedia.org/wiki/Model-view-controller〲〸ぃえぁぐごぅげ 〲〮 始めよう

各アプリケーションは一つのエントリ・スクリプト web/index.php を持ちます。 これはアプリケーション中で唯一ウェブ・アクセス可能な ぐえぐ
スクリプトです。 エントリ・スクリプトは入力されたリクエストを受け取って、アプリケーション のインスタンスを作成します。 アプリケー
ション は コンポーネント の助力を得てリクエストを解決し、リクエス
トを きざぃ に送付します。 ウィジェット は、複雑で動的なユーザ・イン
タフェイス要素を構築するために、ビュー の中で使われます。

2.3.3

リクエストのライフサイクル

次の図は、アプリケーションがどのようにリクエストを処理するかを示すものです。

〲〮〳〮 アプリケーションを走らせる〲〹〱〮 ユーザが エントリ・スクリプト web/index.php に対してリクエストを出します。
〲〮 エントリ・スクリプトはアプリケーションの 構成情報 を読み出して、 リクエストを処理する アプリケーション のインスタンスを作成します。
〳〮 アプリケーションは、リクエスト アプリケーション・コンポーネン
トの助力を得て、 リクエストされた ルート を解決します。
〴〮 アプリケーションがリクエストを処理する コントローラ のインスタンスを作成します。
〵〮 コントローラが アクション のインスタンスを作成し、アクションのためのフィルタを実行します。
〶〮 一つでもフィルタが失敗したときは、アクションはキャンセルされます。
〷〮 すべてのフィルタを通ったとき、アクションが実行されます。
〸〮 アクションはデータ・モデルを、おそらくはデータベースから、読み出します。
〹〮 アクションはデータ・モデルをビューに提供して、ビューをレンダリングします。

〳〰

ぃえぁぐごぅげ 〲〮 始めよう〱〰〮 レンダリング結果が レスポンス アプリケーション・コンポーネン
トに返されます。
〱〱〮 レスポンス・コンポーネントがレンダリング結果をユーザのブラウ
ザに送信します。

こんにちは、と言う

2.4

このセクションでは、アプリケーションに「こんにちは」という新しいページを作成する方法を説明します。 この目的を達するために、アクション と ビュー を作成します。
• アプリケーションは、このページへのリクエストをそのアクションに送付します。
• 次にそのアクションが「こんにちは」という言葉をエンド・ユーザに示すビューを表示します。
このチュートリアルを通じて、三つのことを学びます。
〱〮 リクエストに応える アクション を作成する方法〲〮 レスポンスのコンテントを作成する ビュー を作成する方法〳〮 アプリケーションがリクエストを アクション に送付する仕組み

2.4.1

アクションを作成する「こんにちは」のタスクのために、リクエストから message パラメータを読んで、そのメッセージをユーザに表示して返す say アクション を作ります。 リクエストが message パラメータを提供しなかった場合は、アクションはデフォルト値として 【こんにちは】 というメッセージを表示する
ものとします。
情報〺 アクション は、エンド・ユーザが直接に参照して実行できるオブジェクトです。 アクションは コントローラ によってグループ化されます。 アクションの実行結果が、エンド・ユーザが受け取るレスポンスです。
アクションは コントローラ の中で宣言されなければなりません。 話を簡単にするために、say アクションを既存の SiteController の中で宣言しましょう。 このコントローラは controllers/SiteController.php というク
ラス・ファイルの中で定義されています。次のようにして、新しいアクションが始まります。
<?php
namespace app\controllers;〲〮〴〮 こんにちは、と言う〳〱

use yii\web\Controller;class SiteController extends Controller{// ... 既存のコード ...

}public function actionSay($message = 'こんにちは'){return $this->render('say', ['message' => $message]);}

上記のコードでは、SiteController クラスの中で、say アクションが actionSayという名前のメソッドとして定義されています。 すどど はコントローラ・
クラスの中で、アクション・メソッドと非アクション・メソッドを区別するために、action という接頭辞を使います。 action という接頭辞の後に続く名前がアクション ぉい にマップされます。
アクションを命名するについては、すどど がアクション ぉい をどのように取り扱うかを知っていなければなりません。 アクション ぉい は常に小文字で参照されます。 アクション ぉい が複数の単語を必要とするときは、
単語がダッシュ 〨〭〩 で連結されます 〨例えば、create-comment〩。 アクショ
ン・メソッドの名前は、アクション ぉい からダッシュを全て削除し、各単語の先頭の文字を大文字にした結果に action という接頭辞を付けたものになります。 例えば、アクション ぉい create-comment はアクション・メ
ソッド名 actionCreateComment に対応します。
私たちの例では、アクション・メソッドは $message というパラメータを取り、そのデフォルト値は "こんにちは" です 〨ぐえぐ で関数やメソッドの引数にデフォルト値を設定するのと全く同じ方法です〩。 アプリケーショ
ンがリクエストを受け取って、当該リクエストの処理を say アクションが担当すべきであると決定した場合は、 リクエストの中に見つかった同じ
名前のパラメータの値をこの $message パラメータに代入します。 言い換
えれば、もしリクエストの中に "さようなら" という値の message パラメー
タが入っていれば、アクションの $message 変数にその値が割り当てられます。
アクション・メソッドの中では、ひづのつづひ〨〩 が呼ばれて say と言う名前の ビュー ファイルがレンダリングされます。 message パラメータも同時にビューに渡され、そこで使用されます。 レンダリング結果はアクショ
ン・メソッドによって返されます。 返された結果はアプリケーションによって受け取られ、ブラウザ上でエンド・ユーザに 〨完全な えごきが ペー
ジの一部として〩 表示されます。

2.4.2

ビューを作成する

ビュー は、レスポンスのコンテントを生成するために書かれるスクリプ
トです。 「こんにちは」のタスクのためには、アクション・メソッドから受け取った message パラメータを出力する say ビューを作成します。

〳〲

ぃえぁぐごぅげ 〲〮 始めよう<?php
use yii\helpers\Html;?><? = Html::encode($message) ?>say ビューは views/site/say.php というファイルに保存しなければなりま

せん。 アクションの中で ひづのつづひ〨〩 メソッドが呼ばれるとき、render() メ
ソッドは views/ControllerID/ViewName.php という名前の ぐえぐ ファイルを探します。
上記のコードで message パラメータが出力される前に えごきが〭エンコー
ド されていることに注意してください。 パラメータはエンド・ユーザ
から来るものであり、悪意のある おちぶちこっひどばぴ コードを埋め込まれて ク
ロス・サイト・スクリプティング 〨じここ〩 攻撃36 に使われうるものですから、 脆弱性を防止するためにこうすることが必要です。
当然ながら、say ビューにはもっと多くのコンテントを入れても構いません。コンテントには、えごきが タグ、平文テキスト、さらには ぐえぐ
文を含めることが出来ます。 実際、say ビューは ひづのつづひ〨〩 メソッドによって実行される ぐえぐ スクリプトであるに過ぎません。 ビュー・ス
クリプトによって出力されたコンテントはレスポンス結果としてアプ
リケーションに返されます。そしてアプリケーションがこの結果をエンド・ユーザに対して出力します。

2.4.3

試してみる

アクションとビューを作成したら、下記の さげが で新しいページにアクセスすることが出来ます。

https://hostname/index.php?r=site%2Fsay&message=Hello+World

https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%82%B9%E3%82%B5%E3%
82%A4%E3%83%88%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%86%E3%82%A3%E3%83%
B3%E3%82%B036〲〮〴〮 こんにちは、と言う〳〳

この さげが は、結果として、〢えづぬぬは しはひぬつ】 を表示するページになります。このページはアプリケーションの他のページと同じヘッダとフッタを共有しています。
さげが から message パラメータを省略すると、】こんにちは】 を表示するページを見ることになるでしょう。 これは、message が actionSay() メ
ソッドにパラメータとして渡されるものであり、それが省略された場合には、デフォルト値である "こんにちは" が代りに使われるからです。
情報〺 新しいページは他のページと同じヘッダとフッタを共有していますが、それは ひづのつづひ〨〩 メソッドが say ビューの結果
を いわゆる レイアウト に自動的に埋め込むからです。 レイ
アウトは、この場合、views/layouts/main.php にあります。
上記の さげが の r パラメータについては、さらに説明が必要でしょう。 これは ルート、すなわち、アクションを指し示すアプリケーションを通じて一意な ぉい を表します。 ルートの書式は ControllerID/ActionID です。 ア
プリケーションはリクエストを受け取ると、このパラメータ r をチェッ
クし、ControllerID の部分を使って、このリクエストを処理するためにどのコントローラ・クラスのインスタンスを作成すべきかを決定します。
そして、コントローラは ActionID の部分を使って、実際の仕事をする
ためにどのアクションを呼び出すべきかを決定します。 この例で言えば、site/say というルートは、SiteController コントローラ・クラスと say
アクションとして解決されます。 結果として、SiteController::actionSay()
メソッドがリクエストを処理するために呼び出されます。
情報〺 アクションと同じく、コントローラもまたアプリケー
ションの中で一意に定義される ぉい を持ちます。 コントロー

〳〴ぃえぁぐごぅげ 〲〮 始めよう
ラ ぉい も、アクション ぉい と同じ命名規則を使います。 コン
トローラ・クラスの名前は、コントローラ ぉい からダッシュを削除し、各単語の最初の文字を大文字にし、 結果として出来る文字列に Controller という接尾辞を追加したものとなります。 例えば、post-comment というコントローラ ぉい に対応する
コントローラ・クラスの名前は PostCommentController です。

2.4.4

まとめ

このセクションでは、きざぃ アーキテクチャ・パターンのうちのコント
ローラとビューの部分に触れました。 特定のリクエストを処理するためのアクションをコントローラの一部として作成しました。また、レスポ
ンスのコンテントを作成するためのビューも作成しました。 この単純な例においては、使用される唯一のデータが message パラメータであったた
め、モデルは関係していません。
また、すどど におけるルートについても学びました。ルートはユーザのリクエストとコントローラのアクションとの橋渡しとして働くものです。
次のセクションでは、モデルを作成する方法を学びます。そして、えごきが フォームを含むページを追加します。

2.5

フォームを扱う

このセクションでは、ユーザからデータを取得するためのフォームを持
つ新しいページを作る方法を説明します。 このページは名前のインプッ
ト・フィールドとメールのインプット・フィールドを持つフォームを表示します。 ユーザからこれら二つの情報を受け取った後、ウェブ・ペー
ジは確認のために入力された値をエコー・バックします。
この目的を達するために、一つの アクション と 二つの ビュー を作成する以外に、 一つの モデル をも作成します。
このチュートリアルを通じて、次の方法を学びます。
• フォームを通じてユーザによって入力されるデータを表す モデルを作成する方法• 入力されたデータを検証する規則を宣言する方法• ビュー の中で えごきが フォームを構築する方法

2.5.1

モデルを作成する

ユーザに入力してもらうデータは、下に示されているように EntryForm モ
デル・クラスとして表現され、 models/EntryForm.php というファイルに保存されます。 クラス・ファイルの命名規約についての詳細は クラスのオートロード のセクションを参照してください。
<?php〲〮〵〮 フォームを扱う〳〵

namespace app\models;use Yii;
use yii\base\Model;
class EntryForm extends Model{public $name;public $email;}public function rules(){return [[['name', 'email'], 'required'],['email', 'email'],];}

このクラスは、すどど によって提供される基底クラス べどどぜぢちびづぜきはつづぬ を拡張するものです。 通常、この基底クラスがフォーム・データを表現するのに使われます。
情報〺 べどどぜぢちびづぜきはつづぬ はデータベース・テーブルと関連しないモデル・クラスの親として使われます。 データベー
ス・テーブルと対応するモデル・クラスでは、通常は べどど
ぜつぢぜぁっぴどぶづげづっはひつ が親になります。
EntryForm クラスは二つのパブリック・メンバー、name と email を持っており、これらがユーザによって入力されるデータを保管するのに使われます。 このクラスはまた rules() という名前のメソッドを持っています。
このメソッドがデータを検証する一連の規則を返します。 上記で宣言されている検証規則は次のことを述べています。
• name と email は、ともに値を要求される• email のデータは構文的に有効なメール・アドレスでなければならない
ユーザによって入力されたデータを EntryForm オブジェクトに投入した
後、ぶちぬどつちぴづ〨〩 メソッドを呼んでデータ検証ルーチンを始動することが出来ます。 データ検証が失敗すると とちびぅひひはひび プロパティが true に設定されます。 そして、づひひはひび を通じて、どのような検証エラーが発生したかを知ることが出来ます。
<?php$model = new EntryForm();$model->name = 'Qiang';$model->email = 'bad';if ($model->validate()) {// 良し!
} else {〳〶}ぃえぁぐごぅげ 〲〮 始めよう// 失敗!
// $model->getErrors() を使う

2.5.2

アクションを作成する

次に、この新しいモデルを使う entry アクションを site コントローラに作る必要があります。 アクションを作成して使うプロセスについて
は、こんにちは、と言う のセクションで既に説明されています。
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\EntryForm;class SiteController extends Controller{// ... 既存のコード ...
public function actionEntry(){$model = new EntryForm();
if ($model->load(Yii::$app->request->post()) && $model->validate()){// $model に有効なデータを受け取った場合// ここで $model について何か意味のあることをする ...

}}return $this->render('entry-confirm', ['model' => $model]);} else {// ページの初期表示か、または、何か検証エラーがある場合
return $this->render('entry', ['model' => $model]);}アクションは最初に EntryForm オブジェクトを生成します。 次に、モデルに $_POST のデータ、すどど においては べどどぜぷづぢぜげづぱふづびぴ〺〺ばはびぴ〨〩 によって提供されるデータを投入しようと試みます。 モデルへのデータ投入が成功した場合（つまり、ユーザが えごきが フォームを送信した場合〩、アクションはぶちぬどつちぴづ〨〩 を呼んで、 入力された値が有効なものであるかどうかを確認します。
情報〺 Yii::$app という式は アプリケーション インスタンスを表現します。 これはグローバルにアクセス可能なシング
ルトンです。 これは、また、特定の機能性をサポートする〲〮〵〮 フォームを扱う〳〷

request、response、db などのコンポーネントを提供する サー

ビス・ロケータ でもあります。 上記のコードでは、アプリ
ケーション・インスタンスの request コンポーネントが $_POST
データにアクセスするために使われています。
す べ て が 適 正 で あ る 場 合 、 ア ク シ ョ ン は entry-confirm と い う 名 前 のビューを表示して、データの送信が成功したことをユーザに確認させます。 データが送信されなかったり、データがエラーを含んでいたりす
る場合は、entry ビューが表示され、 その中で えごきが フォームが 〨もし有れば〩 検証エラーのメッセージとともに表示されます。
補足〺 この簡単な例では、有効なデータ送信に対して単純に確認ページを表示しています。 実際の仕事では、フォーム送信の諸問題37 を避けるために、 ひづてひづびと〨〩 または ひづつどひづっぴ〨〩を使うことを考慮すべきです。

2.5.3

ビューを作成する

最後に、entry-confirm と entry という名前の二つのビュー・ファイルを作成します。 今まさに説明したように、これらが entry アクションによって表示されます。
entry-confirm ビューは単純に名前とメールのデータを表示するものです。このビューは views/site/entry-confirm.php というファイルに保存しなければなりません。
<?php
use yii\helpers\Html;?><p>あなたは次の情報を入力しました</p><ul><li><label>名前</label>: <? = Html::encode($model->name) ?> </li><li><label>メール</label>: <? = Html::encode($model->email) ?> </li></ul>entry ビューは えごきが フォームを表示します。これは views/site/entry.phpというファイルに保存しなければなりません。
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;?><?php $form = ActiveForm::begin(); ?><? = $form->field($model, 'name') ?><? = $form->field($model, 'email') ?>37

https://en.wikipedia.org/wiki/Post/Redirect/Get〳〸ぃえぁぐごぅげ 〲〮 始めよう

<div class="form-group"><? = Html::submitButton('送信', ['class' => 'btn btn-primary']) ?></div><?php ActiveForm::end(); ?>このビューは えごきが フォームを構築するのに、ぁっぴどぶづうはひね と呼ばれる強力な ウィジェット を使います。 ウィジェットの begin() メソッドと end() メソッドが、それぞれ、フォームの開始タグと終了タグをレンダリングします。 この二つのメソッドの呼び出しの間に、てどづぬつ〨〩 メ
ソッドによってインプット・フィールドが作成されます。 最初のイン
プット・フィールドは 【のちねづ】 のデータ、第二のインプット・フィール
ドは 【づねちどぬ】 のデータのためのものです。 インプット・フィールドの後に、べどどぜとづぬばづひびぜえぴねぬ〺〺びふぢねどぴあふぴぴはの〨〩 メソッドが呼ばれて、送信ボタンを生成しています。

2.5.4

試してみる

どのように動作するかを見るために、ブラウザで下記の さげが にアクセス
してください。

https://hostname/index.php?r=site%2Fentry

二つのインプット・フィールドを持つフォームを表示するページが表示されるでしょう。それぞれのインプット・フィールドの前には、どんなデータを入力すべきかを示すラベルがあります。 何も入力せずに、あるいは、無効なメール・アドレスを入力して送信ボタンをクリックすると、それぞれ問題のあるインプット・フィールドの後ろにエラー・メッ
セージが表示されます。

〲〮〵〮 フォームを扱う〳〹

有効な名前とメール・アドレスを入力してから送信ボタンをクリック
すると、 たった今入力したデータを表示する新しいページが表示されま
す。

魔法の説明
あなたは、舞台裏で えごきが フォームがどのように動いているのか、不思議に思うかも知れません。 なぜなら、フォームが、ほとんど魔法のよ〴〰

ぃえぁぐごぅげ 〲〮 始めよう

うに、各インプット・フィールドのラベルを表示し、データを正しく入力しなかった場合には、 ページをリロードすることなく、エラー・メッ
セージを表示するからです。
そう、データの検証は、最初に おちぶちこっひどばぴ を使ってクライアント・サ
イドで実行され、次に ぐえぐ によってサーバ・サイドで実行されます。
べどどぜぷどつでづぴびぜぁっぴどぶづうはひね は、賢いことに、EntryForm で宣言した検証規則を抽出し、それを実行可能な おちぶちこっひどばぴ コードに変換して、 おちぶちこっひどばぴを使ってデータ検証を実行します。 ブラウザで おちぶちこっひどばぴ を無効にした場合でも、actionEntry() メソッドで示されているように、サーバ・サ
イドでの検証は引き続き実行されます。 これにより、どのような状況であっても、データの有効性が保証されます。
警告〺 クライアント・サイドの検証は、ユーザにとってのより良い使い心地のために利便性を提供するものです。 クライア
ント・サイドの検証の有無にかかわらず、サーバ・サイドの検証は常に必要です。
インプット・フィールドのラベルは、モデルのプロパティ名を使用して、field() メソッドによって生成されます。 例えば、name というプロパ
ティから Name というラベルが生成されます。
ビューの中で、下記のコードのように、 ラベルをカスタマイズするこ
とも出来ます。
<?= $form->field($model, 'name')->label('お名前') ?><? = $form->field($model, 'email')->label('メール・アドレス') ?>情報〺 すどど はこのようなウィジェットを数多く提供して、複雑で動的なビューを素速く作成することを手助けしてくれます。 後で学ぶように、新しいウィジェットを書くことも非常に簡単です。 あなたは、将来のビュー開発を単純化するために、多くのビュー・コードを再利用可能なウィジェットに変換したいと思うことでしょう。

2.5.5

まとめ

ガイドのこのセクションにおいては、きざぃ アーキテクチャ・パターンの全ての部分に触れました。 そして、ユーザ・データを表現し、当該デー
タを検証するモデル・クラスを作成する方法を学びました。
また、ユーザからデータを取得する方法と、ブラウザにデータを表示
して返す方法も学びました。 この作業は、アプリケーションを開発する
ときに、多大な時間を必要とするものになり得るものです。 しかし、すどどはこの作業を非常に容易にする強力なウィジェットを提供しています。
次のセクションでは、ほとんど全てのアプリケーションで必要とされるデータベースを取り扱う方法を学びます。

〲〮〶〮 データベースを扱う〴〱

データベースを扱う

2.6

このセクションでは、country という名前のデータベース・テーブルから読み出した国データを表示する新しいページの作り方を説明します。 この目的を達するために、データベース接続を構成し、 アクティブ・レ
コード クラスを作成し、アクション を定義し、 そして ビュー を作成します。
このチュートリアルを通じて、次のことを学びます。
• いあ 接続を構成する方法• アクティブ・レコードのクラスを定義する方法• アクティブ・レコードのクラスを使ってデータを検索する方法• 改ページを伴う仕方でビューにデータを表示する方法
このセクションを完了するためには、データベースを使うことについて
基本的な知識と経験が無ければならないことに注意してください。 具体的に言えば、いあ クライアント・ツールを用いてデータベースを作成する
方法と、こけが 文を実行する方法を知っていなければなりません。

2.6.1

データベースを準備する

まず初めに、yii2basic という名前のデータベースを作成してください。
このデータベースからアプリケーションにデータを読み出すことになります。 すどど は多数のデータベース製品に対するサポートを内蔵しており、作成するデータベースは、こけがどぴづ、きべこけが、ぐはびぴぴひづこけが、きここけが または くひちっぬづ から選ぶことが出来ます。以下の説明では、話を単純にするために、きべこけが を前提とします。
情報〺 きちひどちいあ は、かつては きべこけが と差し替え可能な代替物でしたが、現在では完全にそうだとは言えません。きちひどちいあ
で JSON サポートのような高度な機能を使いたいときは、後述する きちひどちいあ エスステンションの使用を検討して下さい。
次に、データベースに country という名前のテーブルを作り、いくつかのサンプル・データを挿入します。そうするためには、次の こけが 文を実行することが出来ます。
CREATE TABLE `country` (`code` CHAR(2) NOT NULL PRIMARY KEY,
`name` CHAR(52) NOT NULL,`population` INT(11) NOT NULL DEFAULT '0') ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `country` VALUES ('AU','Australia',24016400);
INSERT INTO `country` VALUES ('BR','Brazil',205722000);
INSERT INTO `country` VALUES ('CA','Canada',35985751);
INSERT INTO `country` VALUES ('CN','China',1375210000);
INSERT INTO `country` VALUES ('DE','Germany',81459000);
INSERT INTO `country` VALUES ('FR','France',64513242);〴〲

ぃえぁぐごぅげ 〲〮 始めよう

INSERT INTO `country` VALUES ('GB','United Kingdom',65097000);
INSERT INTO `country` VALUES ('IN','India',1285400000);
INSERT INTO `country` VALUES ('RU','Russia',146519759);
INSERT INTO `country` VALUES ('US','United States',322976000);

この時点で、あなたは yii2basic という名前のデータベースを持ち、その中に三つのカラムを持つ country というテーブルがあり、country テーブ
ルは 〱〰 行のデータを持っている、ということになります。

2.6.2

DB 接続を構成する

先に進む前に、ぐいく38 ぐえぐ 拡張および使用しているデータベースの
ぐいく ドライバ 〨例えば、きべこけが のための pdo_mysql〩 の両方をインストー
ル済みであることを確認してください。 アプリケーションがリレーショ
ナル・データベースを使う場合、これは基本的な必要条件です。
これらがインストール済みなら、config/db.php というファイルを開いて、あなたのデータベースに適合するようにパラメータを変更してくだ
さい。 デフォルトでは、このファイルは下記の記述を含んでいます。
<?php
return ['class' => 'yii\db\Connection','dsn' => 'mysql:host=localhost;dbname=yii2basic','username' => 'root','password' => '','charset' => 'utf8',];

この config/db.php というファイルは典型的なファイル・ベースの 構成情報 ツールです。 この構成情報ファイルが、背後のデータベースに対するこけが クエリの実行を可能にする べどどぜつぢぜぃはののづっぴどはの インスタンスの作成と初期化に必要なパラメータを指定するものです。
上記のようにして構成された いあ 接続は、アプリケーション・コードの中で Yii::$app->db という式でアクセスすることが出来ます。
情報〺 config/db.php は、メインのアプリケーション構成情報
ファイルである config/web.php によってインクルードされます。 この config/web.php が アプリケーション インスタンスが初期化される仕方を指定するものです。 詳しい情報について
は、構成情報 のセクションを参照してください。
すどど がサポートを内蔵していないデータベースを扱う必要がある場合は、以下のエクステンションの利用を検討してください。
• ぉのてはひねどへ39
38
39

https://www.php.net/manual/ja/book.pdo.php
https://github.com/edgardmessias/yii2-informix〲〮〶〮 データベースを扱う〴〳• ぉあき いあ〲40• うどひづぢどひつ41• きちひどちいあ42

2.6.3

アクティブ・レコードを作成する

country テーブルの中のデータを表現し取得するために、アクティブ・レコード から派生した Country という名前のクラスを作成し、 それをmodels/Country.php というファイルに保存します。
<?phpnamespace app\models;
use yii\db\ActiveRecord;class Country extends ActiveRecord{}
Country クラスは べどどぜつぢぜぁっぴどぶづげづっはひつ を拡張しています。この中には一

つもコードを書く必要はありません。 単に上記のコードだけで、すどど は関連付けられたテーブル名をクラス名から推測します。
情報〺 クラス名とテーブル名を直接に合致させることが出来ない場合は、べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺ぴちぢぬづぎちねづ〨〩 メソッドを
オーバーライドして、関連づけられたテーブル名を明示的に指定することが出来ます。
Country クラスを使うことによって、以下のコード断片で示すように、country

テーブルの中のデータを簡単に操作することが出来ます。
use app\models\Country;// country テーブルから全ての行を取得して "name" 順に並べる$countries = Country::find()->orderBy('name')->all();// プライマリ・キーが "US" である行を取得する$country = Country::findOne('US');// "United States" を表示する
echo $country->name;// 国名を "U.S.A." に修正してデータベースに保存する$country->name = 'U.S.A.';$country->save();https://github.com/edgardmessias/yii2-ibm-db2
https://github.com/edgardmessias/yii2-firebird
42
https://github.com/sam-it/yii2-mariadb
40
41

〴〴

ぃえぁぐごぅげ 〲〮 始めよう
情報〺 アクティブ・レコードは、オブジェクト指向の流儀でデータベースのデータにアクセスし、操作する強力な方法です。アクティブ・レコード のセクションで、詳細な情報を得ることが出来ます。 もう一つの方法として、データベース・
アクセス・オブジェクト と呼ばれる、より低レベルなデー
タ・アクセス方法を使ってデータベースを操作することも出
来ます。

2.6.4

アクションを作成する

国データをエンド・ユーザに公開するために、新しいアクションを作成する必要があります。 これまでのセクションでしたように site コント
ローラの中に新しいアクションを置くのではなく、国データに関係する
全てのアクションに限定した新しいコントローラを作成する方が理にかなうでしょう。 この新しいコントローラを CountryController と名付けます。そして、下記に示すように、index アクションをその中に作成します。
<?php
namespace app\controllers;
use yii\web\Controller;
use yii\data\Pagination;
use app\models\Country;
class CountryController extends Controller{
public function actionIndex(){$query = Country::find();$pagination = new Pagination(['defaultPageSize' => 5,'totalCount' => $query->count(),]);$countries = $query->orderBy('name')->offset($pagination->offset)->limit($pagination->limit)->all();}}

return $this->render('index', ['countries' => $countries,'pagination' => $pagination,]);

上記のコードを controllers/CountryController.php というファイルに保存します。

〲〮〶〮 データベースを扱う〴〵

最 初 に index ア ク シ ョ ン は Country::find() を 呼 び 出 し ま す 。 こ の〜のつ〨〩43 メソッドが country テーブルからデータを取得するメソッドを提供する ぁっぴどぶづけふづひべ44 クエリ・オブジェクトオブジェクトを生成します。
一回のリクエストで返される国の数を制限するために、クエリ・オブ
ジェクトは べどどぜつちぴちぜぐちでどのちぴどはの オブジェクトの助けを借りてページ付
けされます。 Pagination オブジェクトは二つの目的に奉仕します。
• クエリによって表現される こけが 文に offset 句と limit 句をセットして、 一度に一ページ分のデータだけ 〨〱ページ最大〵行〩 を返すよ
うにします。
• 次の項で説明されるように、一連のページ・ボタンからなるペー
ジャを ビューに表示するために使われます。
次に、ちぬぬ〨〩45 メソッドがクエリ結果に基づいて全ての country レコードを返します。
コードの最後で、index アクションは index と言う名前のビューをレンダリングします。 このときに、返された国データとそのページネーショ
ン情報がビューに渡されます。

2.6.5

ビューを作成する

最初に、views ディレクトリの下に country という名前のサブ・ディレク
トリを作ってください。 このフォルダが country コントローラによって表示される全てのビューを保持するのに使われます。 views/country ディ
レクトリの中に、下記のコードを含む index.php という名前のファイルを作成します。
<?php
use yii\helpers\Html;
use yii\widgets\LinkPager;?><h1>国リスト</h1><ul><?php foreach ($countries as $country): ?><li><? = Html::encode("{$country->code} ({$country->name})") ?> :<? = $country->population ?></li><?php endforeach; ?></ul><? = LinkPager::widget(['pagination' => $pagination]) ?>ビューは国データの表示に関連して二つの部分に分けられます。 最初の部分では、提供された国データがたどられて、えごきが の順序無しリスト
https://www.yiiframework.com/doc/api/2.0/yii-db-activerecord#find()-detail44
https://www.yiiframework.com/doc/api/2.0/yii-db-activequery45
https://www.yiiframework.com/doc/api/2.0/yii-db-activequery#all()-detail43

〴〶

ぃえぁぐごぅげ 〲〮 始めよう

としてレンダリングされます。 第二の部分では、アクションから渡されたページネーション情報を使って、べどどぜぷどつでづぴびぜがどのにぐちでづひ ウィジェッ
トがレンダリングされます。 LinkPager ウィジェットはページ・ボタンのリストを表示します。ボタンのどれかをクリックすると、対応するページの国データが更新表示されます。

2.6.6

試してみる

上記のコード全てがどのように動作するかを見るために、ブラウザで下記の さげが をアクセスします。
https://hostname/index.php?r=country%2Findex

最初、ページは〵つの国を表示しています。そして、国リストの下には、〴つのボタンを持ったページャがあります。 【〲】 のボタンをクリック
すると、ページはデータベースにある次の〵つの国、すなわち、〲ページ
目のレコードを表示します。 注意深く観察すると、ブラウザの さげが も次のように変ったことに気付くでしょう。
https://hostname/index.php?r=country%2Findex&page=2

舞台裏では、ぐちでどのちぴどはの が、データ・セットをページ付けするのに必要な全ての機能を提供しています。
• 初期状態では、ぐちでどのちぴどはの は、〱ページ目を表しています。 これを反映して、国の こぅがぅぃご クエリは LIMIT 5 OFFSET 0 という句を伴うことになります。その結果、最初の〵つの国が取得されて表示されます。

〲〮〷〮 ぇぉぉ でコードを生成する〴〷• がどのにぐちでづひ ウィジェットは、ぐちでどのちぴどはの によって作成された さげがを使ってページ・ボタンをレンダリングします。 さげが は、別々のページ番号を表現する page というクエリ・パラメータを含んだものになります。
• ページ・ボタン 【〲】 をクリックすると、country/index のルートに対する新しいリクエストが発行され、処理されます。 ぐちでどのちぴどはの がさげが から page クエリ・パラメータを読み取って、カレント・ペー
ジ番号を 〲 にセットします。 こうして、新しい国のクエリは LIMIT
5 OFFSET 5 という句を持ち、 次の〵つの国を表示のために返すことになります。

2.6.7

まとめ

このセクションでは、データベースを扱う方法を学びました。 また、べどど
ぜつちぴちぜぐちでどのちぴどはの と べどどぜぷどつでづぴびぜがどのにぐちでづひ の助けを借りて、ページ付けされたデータを取得し表示する方法も学びました。
次のセクションでは、ぇどど46 と呼ばれる強力なコード生成ツールを使う方法を学びます。 このツールは、データベース・テーブルのデータを取り扱うための「作成・読出し・更新・削除 〨ぃげさい〩」操作のような、通常必要とされることが多い諸機能の迅速な実装を手助けしてくれるものです。 実際のところ、あなたがたった今書いたばかりのコードは、ぇどどツールを使えば、全部、すどど が自動的に生成してくれるものです。

2.7

Gii でコードを生成する

このセクションでは、ぇどど47 を使って、ウェブ・サイトの一般的な機能のいくつかを実装するコードを自動的に生成する方法を説明します。 ぇどどを使ってコードを自動生成することは、ぇどど のウェブ・ページに表示される指示に対して正しい情報を入力するだけのことです。
このチュートリアルを通じて、次のことを学びます。
• アプリケーションで ぇどど を有効にする方法• ぇどど を使って、アクティブ・レコードのクラスを生成する方法• ぇどど を使って、いあ テーブルの ぃげさい 操作を実装するコードを生成する方法• ぇどど によって生成されるコードをカスタマイズする方法

2.7.1

Gii を開始する

ぇどど48 は すどど の モジュール として提供されています。 ぇどど は、アプ
リケーションの ねはつふぬづび プロパティの中で構成することで有効にすること が出来ます。 アプリケー ションを生成した仕方にもよ りますhttps://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide
https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide48
https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide
46
47

〴〸

ぃえぁぐごぅげ 〲〮 始めよう

が、config/web.php の構成情報ファイルの中に、多分、下記のコードが既に提供されているでしょう。

$config = [ ... ];if (YII_ENV_DEV) {$config['bootstrap'][] = 'gii';$config['modules']['gii'] = ['class' => 'yii\gii\Module',];}

上記の構成情報は、開発環境 において、アプリケーションは gii という名前のモジュールをインクルードすべきこと、 そして gii は べどどぜでどどぜきはつふぬづ というクラスであることを記述しています。
アプリケーションの エントリ・スクリプト である web/index.php をチェックすると、次の行があることに気付くでしょう。 これは本質的には YII_ENV_DEV を true に設定するものです。

defined('YII_ENV') or define('YII_ENV', 'dev');

この行のおかげで、アプリケーションは開発モードになっており、上記の構成情報によって、ぇどど が既に有効になっています。これで、下記のさげが によって ぇどど にアクセスすることが出来ます。

https://hostname/index.php?r=gii

補足〺 ローカルホスト以外のマシンから ぇどど にアクセスしようとすると、デフォルトではセキュリティ上の理由でアクセスが拒否されます。 下記のように ぇどど を構成して、許可される
ぉぐ アドレスを追加することが出来ます。

'gii' => ['class' => 'yii\gii\Module','allowedIPs' => ['127.0.0.1', '::1', '192.168.0.*','192.168.178.20'] // 必要に応じて調整],〲〮〷〮 ぇぉぉ でコードを生成する

2.7.2

〴〹

アクティブ・レコードのクラスを生成する

ぇどど を使ってアクティブ・レコードのクラスを生成するためには、〢きはつづぬぇづのづひちぴはひ】 を選びます 〨ぇどど のインデックス・ページのリンクをクリック
して下さい〩。そして、次のようにフォームに入力します。

• ごちぢぬづ ぎちねづ〺 country• きはつづぬ ぃぬちびび〺 Country〵〰

ぃえぁぐごぅげ 〲〮 始めよう

次に、〢ぐひづぶどづぷ】 ボタンをクリックします。そうすると、結果として作成されるクラス・ファイルのリストに models/Country.php が挙ってきます。クラス・ファイルの名前をクリックすると、内容をプレビューすることが出来ます。

ぇどど を使うときに、既に同じファイルを作成していて、それを上書きしようとしている場合は、 ファイル名の隣の diff ボタンをクリックして、 生成されようとしているコードと既存のバージョンの違いを見てください。

〲〮〷〮 ぇぉぉ でコードを生成する〵〱

既存のファイルを上書きするときは、〢はぶづひぷひどぴづ】 の隣のチェックボッ
クスをチェックしてから 【ぇづのづひちぴづ】 ボタンをクリックします。新しいファイルを作成するときは、単に 【ぇづのづひちぴづ】 をクリックすれば十分です。
次に、コードの生成が成功したことを示す確認ページが表示されます。 既存のファイルがあった場合は、それが新しく生成されたコードで上書きされたことを示すメッセージも同じく表示されます。

2.7.3

CRUD コードを生成する

ぃげさい は ぃひづちぴづ〨作成〩、げづちつ〨読出し〩、さばつちぴづ〨更新〩、そして いづぬづぴづ〨削除〩 を意味しており、ほとんどのウェブ・サイトでデータを扱うときによく用いられる〴つのタスクを表しています。ぇどど を使って ぃげさい 機能を作成するためには、〢ぃげさい ぇづのづひちぴはひ】 を選びます 〨ぇどど のインデックス・
ページのリンクをクリックしてください〩 。「国リスト」のサンプルのためには、表示されたフォームに以下のように入力します。
• きはつづぬ ぃぬちびび〺 app\models\Country• こづちひっと きはつづぬ ぃぬちびび〺 app\models\CountrySearch• ぃはのぴひはぬぬづひ ぃぬちびび〺 app\controllers\CountryController〵〲

ぃえぁぐごぅげ 〲〮 始めよう

次に、〢ぐひづぶどづぷ】 ボタンをクリックします。生成されるファイルのリ
ストは、次のようになります。

〲〮〷〮 ぇぉぉ でコードを生成する〵〳

以前に（ガイドのデータベースのセクションで）controllers/CountryController.phpと views/country/index.php のファイルを作成していた場合は、それらを置き換えるために 【はぶづひぷひどぴづ】 のチェックボックスをチェックしてください。 〨以前のバージョンは フル機能の ぃげさい をサポートしていません。〩

2.7.4

試してみる

どのように動作するかを見るために、ブラウザを使って下記の さげが にアクセスしてください。

https://hostname/index.php?r=country%2Findex

データ・グリッドがデータベース・テーブルから取得した国を表示しているページが表示されます。 グリッドをソートしたり、カラムのヘッダに検索条件を入力してグリッドにフィルタを適用したりすることが出来ます。
グリッドに表示されているそれぞれの国について、詳細を見たり、更新したり、または削除したりすることが出来ます。 また、グリッドの上にある 【ぃひづちぴづ ぃはふのぴひべ】 ボタンをクリックすると、新しい国データを作成するためのフォームが利用に供されます。

〵〴

ぃえぁぐごぅげ 〲〮 始めよう

下記が ぇどど によって生成されるファイルのリストです。 これらの機能がどのように実装されているかを調査したい場合、また、これらの機能をカスタマイズしたいときに参照してください。
• ぃはのぴひはぬぬづひ〺 controllers/CountryController.php〲〮〸〮 先を見通す〵〵• きはつづぬび〺 models/Country.php と models/CountrySearch.php• ざどづぷび〺 views/country/*.php
情報〺 ぇどど は非常にカスタマイズしやすく拡張しやすいコード
生成ツールとして設計されています。 これを賢く使うと、アプリケーションの開発速度を大いに高めることが出来ます。
詳細については、ぇどど49 のセクションを参照してください。

2.7.5

まとめ

このセクションでは、ぇどど を使ってコードを生成して、データベース・
テーブルに保存されているコンテントのための 完全な ぃげさい 機能を実装する方法を学びました。

2.8

先を見通す

「はじめよう」の章全体を読み通したなら、いまやあなたは、完全なすどど のアプリケーションを作成したことがある、ということになります。
その過程で、あなたは必要とされることが多いいくつかの機能、例えば、えごきが フォームを通じてユーザからデータを取得することや、デー
タベースからデータを取得すること、また、ページ付けをしてデータを表示することなどを実装する方法を学びました。 また、ぇどど50 を使ってコードを自動的に生成する方法も学びました。 ぇどど をコード生成に使うと、ウェブ開発のプロセスの大部分が、いくつかのフォームに入力していくだけの簡単な仕事になります。
このセクションでは、すどど フレームワークを使うときの生産性を更に高めるために利用できるリソースについてまとめます。
• ドキュメント〕 決定版ガイド51 〺 名前が示すように、このガイドは すどど がどのように動作すべきものかを正確に記述し、すどど を使用するについての全般的な手引きを提供するものです。 これは唯一の最も重要な すどど のチュートリアルであり、すどど のコードを少しでも書く前にあなたが読まなければならないものです。
〕 クラス・リファレンス52 〺 これは すどど によって提供される全てのクラスの使用法を記述しています。 主として、コードを書いている時に、特定のクラス、メソッド、プロパティについて理解したい場合に読まれるべきものです。 クラス・リファレ
ンスの使用は、フレームワーク全体の文脈的な理解が出来てからにするのが最善です。
〕 しどにど の記事53 〺 しどにど の記事は、すどど のユーザが自身の経験に基
https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide
https://www.yiiframework.com/extension/yiisoft/yii2-gii/doc/guide51
https://www.yiiframework.com/doc-2.0/guide-README.html
52
https://www.yiiframework.com/doc-2.0/index.html
53https://www.yiiframework.com/wiki/?tag=yii2
49
50

〵〶

ぃえぁぐごぅげ 〲〮 始めよう

づいて書いたものです。 ほとんどの記事は、料理本のレシピのように書かれており、特定の問題を すどど を使って解決する方法を示しています。 これらの記事の品質は決定版ガイドほどには良くないかもしれませんが、より広範なトピックをカバーしていることと、たいていは即座に使えるソリューションを提供してくれることにおいて有用なものです。
〕 書籍54• エクステンション55 〺 すどど は、ユーザによって作られた数千におよぶ
エクステンションのライブラリを誇りとしています。 エクステン
ションはあなたのアプリケーションに簡単に組み込むことが出来、そうすることでアプリケーションの開発作業をより一層速くて簡単なものにします。
• コミュニティ〕 フォーラム〺 とぴぴばび〺〯〯てはひふね〮べどどてひちねづぷはひに〮っはね〯〕 ぉげぃ チャット〺 がどぢづひち ネットワーク 〨どひっび〺〯〯どひっ〮ぬどぢづひち〮っとちぴ〺〶〶〹〷〯べどど〩 の 〣べどど チャンネル〕 こぬちっに チャンネル〺 とぴぴばび〺〯〯なはどの〮びぬちっに〮っはね〯ぴ〯べどど〯びとちひづつたどのぶどぴづ〯
づのけぴきぺけ〴きいぅへきいっべぎごに〲がごっ〰ぎいけ〲ずごずとぎなにぺずいでぷすなぅ〴すなずぬぎぇけへずなうねずいあなずごさ〳ぎなざどきいぅ〴〕 ぇどぴぴづひ チャット〺 とぴぴばび〺〯〯でどぴぴづひ〮どね〯べどどびはてぴ〯べどど〲〕 ぇどぴえふぢ〺 とぴぴばび〺〯〯でどぴとふぢ〮っはね〯べどどびはてぴ〯べどど〲〕 うちっづぢははに〺 とぴぴばび〺〯〯ぷぷぷ〮てちっづぢははに〮っはね〯でひはふばび〯べどどぴちぬに〯〕 ごぷどぴぴづひ〺 とぴぴばび〺〯〯ぴぷどぴぴづひ〮っはね〯べどどてひちねづぷはひに〕 がどのにづつぉの〺 とぴぴばび〺〯〯ぷぷぷ〮ぬどのにづつどの〮っはね〯でひはふばび〯べどど〭てひちねづぷはひに〭〱〴〸〳〳〶〷〕 こぴちっにはぶづひ〝はぷ〺 とぴぴばび〺〯〯びぴちっにはぶづひてぬはぷ〮っはね〯ぱふづびぴどはのび〯ぴちででづつ〯
べどど〲

54
55

https://www.yiiframework.com/books/
https://www.yiiframework.com/extensions/Chapter 3

アプリケーションの構造
3.1

概要

すどど のアプリケーションは モデル・ビュー・コントローラ 〨きざぃ〩1 アー
キテクチャ・パターンに従って編成されています。 モデル は、データ、
ビジネス・ロジック、規則を表現します。 ビュー は、モデルの出力表
現です。 そして コントローラ は入力を受け取って、それを モデル とビュー のためのコマンドに変換します。
きざぃ 以外にも、すどど のアプリケーションは下記の要素を持っています。
• エントリ・スクリプト〺 エンド・ユーザから直接アクセスできる
ぐえぐ スクリプトです。 これはリクエスト処理サイクルを開始する
役目を持っています。
• アプリケーション〺 グローバルにアクセス可能なオブジェクトであり、 アプリケーション・コンポーネントを管理し、連携させて、リクエストに応えます。
• アプリケーション・コンポーネント〺 アプリケーションと共に登録されたオブジェクトであり、 リクエストに応えるための様々なサービスを提供します。
• モジュール〺 それ自身に完全な きざぃ を含む自己完結的なパッケー
ジです。 アプリケーションは複数のモジュールとして編成することが出来ます。
• フィルタ〺 各リクエストが実際に処理される前と後に、 コントロー
ラから呼び出される必要があるコードを表現します。
• ウィジェット〺 ビュー に埋め込むことが出来るオブジェクトです。
コントローラのロジックを含むことが可能で、異なるビューで再利用することが出来ます。
下の図がアプリケーションの静的な構造を示すものです。
1

https://ja.wikipedia.org/wiki/Model_View_Controller

〵〷

〵〸

3.2

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

エントリ・スクリプト

エントリ・スクリプトは、アプリケーションのブートストラップの過程における最初のステップです。 アプリケーションは 〨ウェブ・アプリ
ケーションであれ、コンソール・アプリケーションであれ）単一のエントリ・スクリプトを持ちます。 エンド・ユーザはエントリ・スクリプトに対してリクエストを発行し、エントリ・スクリプトはアプリケーショ
ンのインスタンスを作成して、それにリクエストを送付します。
ウェブ・アプリケーションのエントリ・スクリプトは、エンド・ユー
ザからアクセス出来るように、 ウェブからのアクセスが可能なディレク
トリの下に保管されなければなりません。 たいていは index.php と名付けられますが、ウェブ・サーバが見つけることが出来る限り、どのような名前を使っても構いません。
コンソール・アプリケーションのエントリ・スクリプトは、通常は、
アプリケーションの ベース・パス の下に保管され、yii と名付けられます 〨.php の拡張子を伴います〩 。 これは、ユーザが ./yii <route> [引数][オプション] というコマンドによってコンソール・アプリケーションを走らせることが出来るようにするためのスクリプトであり、 実行可能な
パーミッションを与えられるべきものです。
エントリ・スクリプトは主として次の仕事をします。
• グローバルな定数を定義する。

〳〮〲〮 エントリ・スクリプト〵〹• ぃはねばはびづひ のオートローダ2 を登録する。
• すどど クラス・ファイルをインクルードする。
• アプリケーションの構成情報を読み出す。
• アプリケーション のインスタンスを生成して構成する。
• べどどぜぢちびづぜぁばばぬどっちぴどはの〺〺ひふの〨〩 を呼んで、受け取ったリクエストを
処理する。

3.2.1

ウェブ・アプリケーション

次に示すのが、ベーシック・ウェブ・プロジェクト・テンプレート のエントリ・スクリプトです。
<?phpdefined('YII_DEBUG') or define('YII_DEBUG', true);defined('YII_ENV') or define('YII_ENV', 'dev');// Composer のオートローダを登録
require __DIR__ . '/../vendor/autoload.php';// Yii クラス・ファイルをインクルード
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';// アプリケーションの構成情報を読み出す$config = require __DIR__ . '/../config/web.php';// アプリケーションを作成し、構成して、走らせる(new yii\web\Application($config))->run();

3.2.2

コンソール・アプリケーション

同様に、下記がコンソール・アプリケーションのエントリ・スクリプトです。
#!/usr/bin/env php
<?php
/**
* Yii console bootstrap file.
** @link https://www.yiiframework.com/* @copyright Copyright (c) 2008 Yii Software LLC* @license https://www.yiiframework.com/license/*/
defined('YII_DEBUG') or define('YII_DEBUG', true);defined('YII_ENV') or define('YII_ENV', 'dev');// Composer のオートローダを登録
require __DIR__ . '/vendor/autoload.php';
2

https://getcomposer.org/doc/01-basic-usage.md#autoloading〶〰

ぃえぁぐごぅげ 〳〮 アプリケーションの構造// Yii クラス・ファイルをインクルード
require __DIR__ . '/vendor/yiisoft/yii2/Yii.php';// アプリケーションの構成情報を読み出す$config = require __DIR__ . '/config/console.php';$application = new yii\console\Application($config);$exitCode = $application->run();exit($exitCode);

3.2.3

定数を定義するグローバルな定数を定義するには、エントリ・スクリプトが最善の場所です。すどど は下記の三つの定数をサポートしています。
• YII_DEBUG〺 アプリケーションがデバッグ・モードで走るかどうかを指定します。 デバッグ・モードにおいては、アプリケーションはより多くのログ情報を保持し、例外が投げられたときに、より詳細なエラーのコール・スタックを表示します。 この理由により、デバッグ・モードは主として開発時に使用されるべきものとなります。YII_DEBUG のデフォルト値は false です。
• YII_ENV〺 どういう環境でアプリケーションが走っているかを指定します。 詳細は、構成情報 のセクションで説明されます。 YII_ENV の
デフォルト値は 'prod' であり、アプリケーションが本番環境で走っていることを意味します。
• YII_ENABLE_ERROR_HANDLER〺 すどど によって提供されるエラー・ハンドラを有効にするかどうかを指定します。 この定数のデフォルト値はtrue です。
定数を定義するときには、しばしば次のようなコードを用います。
defined('YII_DEBUG') or define('YII_DEBUG', true);

これは下記のコードと同じ意味のものです。
if (!defined('YII_DEBUG')) {define('YII_DEBUG', true);}

明らかに前者の方が簡潔で理解しやすいでしょう。
他のぐえぐ ファイルがインクルードされる時に定数の効力が生じるようにするために、 定数はエントリ・スクリプトの冒頭で定義されなければなりません。

3.3

アプリケーション

アプリケーションは すどど アプリケーション・システム全体の構造とライフサイクルを統制するオブジェクトです。 全ての すどど アプリケーション・〳〮〳〮 アプリケーション〶〱

システムは、それぞれ、単一のアプリケーション・オブジェクトを持ちます。 アプリケーション・オブジェクトは、エントリ・スクリプト において作成され、\Yii::$app という式でグローバルにアクセスすることが出来るオブジェクトです。
情報〺 ガイドの中で「アプリケーション」という言葉は、文脈に応じて、アプリケーション・オブジェクトを意味したり、アプリケーション・システムを意味したりします。
二種類のアプリケーション、すなわち、ウェブ・アプリケーション と コ
ンソール・アプリケーション があります。 名前が示すように、前者は主にウェブのリクエストを処理し、後者はコンソール・コマンドのリクエ
ストを処理します。

3.3.1

アプリケーションの構成情報

エントリ・スクリプト は、アプリケーションを作成するときに、下記のように、 構成情報 を読み込んで、それをアプリケーションに適用します。
require __DIR__ . '/../vendor/autoload.php';
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';// アプリケーションの構成情報を読み込む$config = require __DIR__ . '/../config/web.php';// アプリケーションのインスタンスを作成し、構成情報を適用する(new yii\web\Application($config))->run();

通常の 構成情報 と同じように、アプリケーションの構成情報は、 アプリ
ケーション・オブジェクトのプロパティをどのように初期化するかを指定するものです。 アプリケーションの構成情報は、たいていは非常に複雑なものですから、通常は、上記の例の web.php ファイルのように、 構
成情報ファイル に保管されます。

3.3.2

アプリケーションのプロパティ

アプリケーションの構成情報で構成すべき重要なアプリケーションのプ
ロパティは数多くあります。 それらのプロパティの典型的なものは、
アプリケーションが走る環境を記述するものです。 例えば、アプリケー
ションは、どのようにして コントローラ をロードするか、また、どこに
テンポラリフ・ァイルを保存するかなどを知らなければなりません。 以下において、それらのプロパティを要約します。
必須のプロパティ
どのアプリケーションでも、最低二つのプロパティは構成しなければなりません。 すなわち、どつ と ぢちびづぐちぴと です。

〶〲

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

どつ どつ プロパティは、アプリケーションを他のアプリケーションから区別するユニークな ぉい を指定するものです。 このプロパティは主としてプログラム内部で使われます。 必須ではありませんが、最良の相互運用性を確保するために、アプリケーション ぉい を指定するときには英数字だ
けを使うことが推奨されます。
ぢちびづぐちぴと ぢちびづぐちぴと プロパティは、アプリケーションのルート・ディレ
クトリを指定するものです。 これは、アプリケーション・システムの全ての保護されたソース・コードを収容するディレクトリです。 通常、このディレクトリの下に、きざぃ パターンに対応するソース・コードを収容した models、views、controllers などのサブ・ディレクトリがあります。
ぢちびづぐちぴと プ ロ パ テ ィ の 構 成 に は 、 デ ィ レ ク ト リ ・ パ ス を 使 っ ても、パス・エイリアス を使っても構いません。 どちらの形式においても、対応するディレクトリが存在しなければなりません。 さもなくば、例外が投げられます。パスは realpath() 関数を呼び出して正規化されます。
ぢちびづぐちぴと プロパティは、しばしば、他の重要なパス 〨例えば、ひふのぴどねづのパス〩 を派生させるために使われます。 このため、basePath を示す @appというパス・エイリアスが、あらかじめ定義されています。 その結果、派生的なパスはこのエイリアスを使って形成することが出来ます〨例えば、ひふのぴどねづ ディレクトリを示す @app/runtime など〩。
重要なプロパティ
この項で説明するプロパティは、アプリケーションごとに異なるものであるため、 構成する必要がよく生じるものです。
ちぬどちびづび このプロパティを使って、配列形式で一連の エイリアス を定義することが出来ます。 配列のキーがエイリアスの名前であり、配列の値が対応するパスの定義です。 例えば、[]

'aliases' => ['@name1' => 'path/to/path1','@name2' => 'path/to/path2',],

このプロパティが提供されているのは、すどど〺〺びづぴぁぬどちび〨〩 メソッドを呼び出す代りに、 アプリケーションの構成情報を使ってエイリアスを定義することが出来るようにするためです。
ぢははぴびぴひちば これは非常に有用なプロパティです。 これによって、アプ
リケーションの ブートストラップの過程 において走らせるべきコンポー
ネントを配列として指定することが出来ます。 例えば、ある モジュール〳〮〳〮 アプリケーション〶〳に さげが 規則 をカスタマイズさせたいときに、 モジュールの ぉい をこの
プロパティの要素として挙げることが出来ます。
このプロパティにリストする各コンポーネントは、以下の形式のいず
れかによって指定することが出来ます。
• っはねばはのづのぴび によって指定されているアプリケーション・コンポー
ネントの ぉい
• ねはつふぬづび によって指定されているモジュールの ぉい• クラス名• 構成情報の配列• コンポーネントを作成して返す無名関数
例えば、['bootstrap' => [// アプリケーション・コンポーネント ID、または、モジュール ID'demo',// クラス名'app\components\Profiler',// 構成情報の配列['class' => 'app\components\Profiler','level' => 3,
],

]

],

// 無名関数
function () {return new app\components\Profiler();}

情報〺 モジュール ぉい と同じ ぉい のアプリケーション・コン
ポーネントがある場合は、 ブートストラップの過程ではア
プリケーション・コンポーネントが使われます。 代りにモジュールを使いたいときは、次のように、無名関数を使って指定することが出来ます。
[]

function () {return Yii::$app->getModule('user');},

ブートストラップの過程で、各コンポーネントのインスタンスが作成されます。 そして、コンポーネント・クラスが べどどぜぢちびづぜあははぴびぴひちばぉのぴづひてちっづ
を実装している場合は、 その ぢははぴびぴひちば〨〩 メソッドも呼び出されます。
もう一つの実用的な例が ベーシック・プロジェクト・テンプレートのアプリケーションの構成情報の中にあります。 そこでは、アプリケー

〶〴ぃえぁぐごぅげ 〳〮 アプリケーションの構造

ションが開発環境で走るときには debug モジュールと gii モジュールがブートストラップ・コンポーネントとして構成されています。
if (YII_ENV_DEV) {// 'dev' 環境のための構成情報の修正$config['bootstrap'][] = 'debug';$config['modules']['debug'] = 'yii\debug\Module';}$config['bootstrap'][] = 'gii';$config['modules']['gii'] = 'yii\gii\Module';補足〺 あまり多くのコンポーネントを bootstrap に置くと、
アプリケーションのパフォーマンスを劣化させます。 なぜなら、リクエストごとに同じ一連のコンポーネントを走らせなければならないからです。ですから、ブートストラップ・コ
ンポーネントは賢く使ってください。
っちぴっとぁぬぬ このプロパティは ウェブ・アプリケーション においてのみサポートされます。 これは、全てのユーザ・リクエストを処理すべき コ
ントローラ・アクション を指定するものです。 これは主としてアプリ
ケーションがメンテナンス・モードにあって、入ってくる全てのリクエ
ストを単一のアクションで処理する必要があるときに使われます。
構成情報は配列の形を取り、最初の要素はアクションのルートを指定します。 そして、配列の残りの要素 〨キー・値のペア〩 は、アクションに渡されるパラメータを指定します。例えば、[]'catchAll' => ['offline/notice','param1' => 'value1','param2' => 'value2',],

情報〺 このプロパティを有効にすると、開発環境でデバッグ・
パネルが動作しなくなります。
っはねばはのづのぴび これこそが、唯一の最も重要なプロパティです。 これによって、アプリケーション・コンポーネント と呼ばれる一連の名前付きのコンポーネントを登録して、それらを他の場所で使うことが出来るよ
うになります。例えば、['components' => ['cache' => ['class' => 'yii\caching\FileCache',],〳〮〳〮 アプリケーション

]

],

〶〵

'user' => ['identityClass' => 'app\models\User','enableAutoLogin' => true,],

全てのアプリケーション・コンポーネントは、それぞれ、配列の中で「キー・値」のペアとして指定されます。 キーはコンポーネントの ぉいを示し、値はコンポーネントのクラス名または 構成情報 を示します。
どのようなコンポーネントでもアプリケーションに登録することが出来ます。 そして登録されたコンポーネントは、後で、\Yii::$app->componentIDという式を使ってグローバルにアクセスすることが出来ます。
詳細は アプリケーション・コンポーネント のセクションを読んでください。
っはのぴひはぬぬづひきちば このプロパティは、コントローラ ぉい を任意のコント
ローラ・クラスに割り付けることを可能にするものです。 デフォルト
では、すどど は 規約 に基づいてコントローラ ぉい をコントローラ・クラスに割り付けます 〨例えば、post という ぉい は app\controllers\PostControllerに割り付けられます〩。 このプロパティを構成することによって、特定のコントローラに対する規約を破ることが出来ます。 下記の例では、account は app\controllers\UserController に割り付けられ、article はapp\controllers\PostController に割り付けられることになります。
[]'controllerMap' => ['account' => 'app\controllers\UserController','article' => ['class' => 'app\controllers\PostController','enableCsrfValidation' => false,],],

このプロパティの配列のキーはコントローラ ぉい を表し、配列の値は対応するコントローラ・クラスの名前または 構成情報 を表します。
っはのぴひはぬぬづひぎちねづびばちっづ
このプロパティは、コントローラ・クラスが配置されるべきデフォルトの名前空間を指定するものです。 デフォル
ト値は app\controllers です。 コントローラ ぉい が post である場合、規約によって対応するコントローラの 〨名前空間を略した〩 クラス名はPostController となり、完全修飾クラス名は app\controllers\PostControllerとなります。
コントローラ・クラスは、この名前空間に対応するディレクトリのサ
ブ・ディレクトリに配置されても構いません。 例えば、コントローラ ぉい〶〶

ぃえぁぐごぅげ 〳〮 アプリケーションの構造として admin/post を仮定すると、対応するコントローラの完全修飾クラス名は app\controllers\admin\PostController となります。
重要なことは、完全修飾されたコントローラ・クラスが オートロー
ド可能 でなければならず、 コントローラ・クラスの実際の名前空間がこのプロパティと合致していなければならない、ということです。 そうでないと、アプリケーションにアクセスしたときに 【ページがみつかりません】 というエラーを受け取ることになります。
上で説明された規約を破りたい場合は、 っはのぴひはぬぬづひきちば プロパティを構成することが出来ます。
ぬちのでふちでづ このプロパティは、アプリケーションがコンテントをエンド・ユーザに表示するときに使うべき言語を指定するものです。 このプ
ロパティのデフォルト値は en であり、英語を意味します。 アプリケー
ションが多言語をサポートする必要があるときは、このプロパティを構成しなければなりません。
このプロパティの値が、メッセージの翻訳、日付の書式、数字の書式などを含む 国際化 のさまざまな側面を決定します。 例えば、べどどぜなふどぜいちぴづぐどっにづひ ウィジェットは、どの言語でカレンダーを表示すべきか、
そして日付をどのように書式設定すべきかを、デフォルトでは、 このプ
ロパティを使用して決定します。
言語を指定するのには、ぉぅごう 言語タグ3 に従うことが推奨されます。 例えば、en は英語を意味し、en-US はアメリカ合衆国の英語を意味します。
このプロパティに関する詳細は 国際化 のセクションで読むことが出来ます。
ねはつふぬづび このプロパティはアプリケーションが含む モジュール を指定するものです。
このプロパティは、モジュールの ぉい をキーとする、モジュールのクラスまたは 構成情報 の配列です。 例えば、[

'modules' => [// モジュール・クラスで指定された "booking" モジュール'booking' => 'app\modules\booking\BookingModule',],]// 構成情報の配列で指定された "comment" モジュール'comment' => ['class' => 'app\modules\comment\CommentModule','db' => 'db',],

詳細は モジュール のセクションを参照してください。
3

https://ja.wikipedia.org/wiki/IETF%E8%A8%80%E8%AA%9E%E3%82%BF%E3%82%B0〳〮〳〮 アプリケーション〶〷

のちねづ このプロパティは、エンド・ユーザに対して表示されるアプリ
ケーション名を指定するものです。 どつ プロパティがユニークな値を取らなければならないのとは違って、 このプロパティの値は主として表示目的であり、ユニークである必要はありません。
コードのどこにも使わないのであれば、このプロパティは必ずしも構成する必要はありません。
ばちひちねび このプロパティは、グローバルにアクセス可能なアプリケー
ション・パラメータの配列を指定するものです。 コードの中のいたる処でハードコードされた数値や文字列を使う代りに、それらをアプリケー
ション・パラメータとして一ヶ所で定義し、 必要な場所ではそのパラメータを使うというのが良いプラクティスです。 例えば、次のように、サムネール画像のサイズをパラメータとして定義することが出来ます。
['params' => ['thumbnail.size' => [128, 128],],]

そして、このサイズの値を使う必要があるコードにおいては、下記のよ
うなコードを使うだけで済ませることが出来ます。
$size = \Yii::$app->params['thumbnail.size'];$width = \Yii::$app->params['thumbnail.size'][0];後でサムネールのサイズを変更すると決めたときは、アプリケーションの構成情報においてのみサイズを修正すればよく、 これに依存するコー
ドには少しも触れる必要がありません。
びはふひっづがちのでふちでづ このプロパティはアプリケーション・コードが書かれている言語を指定するものです。デフォルト値は 'en-US'、アメリカ合衆
国の英語です。 あなたのコードのテキストのコンテントが英語以外で書かれているときは、このプロパティを構成しなければなりません。
ぬちのでふちでづ プロパティと同様に、このプロパティは ぉぅごう 言語タグ4 に従って構成しなければなりません。 例えば、en は英語を意味し、en-US はアメリカ合衆国の英語を意味します。
このプロパティに関する詳細は 国際化 のセクションで読むことが出来ます。
ぴどねづずはのづ このプロパティは、ぐえぐ ランタイムのデフォルト・タイム・ゾーンを設定する代替手段として提供されています。 このプロパティを構成することによって、本質的には ぐえぐ 関数 つちぴづたつづてちふぬぴたぴどねづぺはのづたびづぴ〨〩5を呼び出すことになります。 例えば、
45

https://ja.wikipedia.org/wiki/IETF%E8%A8%80%E8%AA%9E%E3%82%BF%E3%82%B0
https://www.php.net/manual/ja/function.date-default-timezone-set.php

〶〸
[
]

ぃえぁぐごぅげ 〳〮 アプリケーションの構造'timeZone' => 'Asia/Tokyo',

タイム・ゾーンを設定することの意味合いについては、日付のフォー
マッティングのセクション で詳細を参照して下さい。
ぶづひびどはの このプロパティはアプリケーションのバージョンを指定するものです。デフォルト値は '1.0' です。 コードの中で全く使わないのであれば、必ずしも構成する必要はありません。
有用なプロパティ
この項で説明されるプロパティは通常は構成されません。というのは、そのデフォルト値が通常の規約に由来するものであるからです。 しかしながら、規約を破る必要がある場合には、これらのプロパティを構成することが出来ます。
っとちひびづぴ このプロパティはアプリケーションが使う文字セットを指定するものです。 デフォルト値は 'UTF-8' であり、多数の非ユニコード・
データを使うレガシー・システムを扱っている場合を除けば、たいていのアプリケーションでは、そのままにしておくべきです。
つづてちふぬぴげはふぴづ このプロパティは、リクエストがルートを指定していないときにアプリケーションが使用すべき ルート を指定するものです。 ルートは、チャイルド・モジュール ぉい、コントローラ ぉい、および〯または アクション ぉい を構成要素とすることが出来ます。 例え
ば、help、post/create、admin/post/create などです。 アクション ぉい が与えられていない場合は、べどどぜぢちびづぜぃはのぴひはぬぬづひ〺〺〤つづてちふぬぴぁっぴどはの で指定されるデフォルト値を取ります。
ウェブ・アプリケーション では、このプロパティのデフォルト値は'site' であり、 その意味するところは、SiteController コントローラとそのデフォルト・アクションが使用されるべきである、ということです。 結果として、ルートを指定せずにアプリケーションにアクセスすると、app\controllers\SiteController::actionIndex() の結果が表示されます。
コ ン ソ ー ル ・ ア プ リ ケ ー シ ョ ン で は 、 デ フ ォ ル ト 値 は 'help' であり、 コア・コマンドの べどどぜっはのびはぬづぜっはのぴひはぬぬづひびぜえづぬばぃはのぴひはぬぬづひ〺〺
ちっぴどはのぉのつづへ〨〩 が使用されるべきであるという意味です。 結果として、何も引数を与えずに yii というコマンドを実行すると、ヘルプ情報が表示されることになります。
づへぴづのびどはのび このプロパティは、アプリケーションにインストールされて使われている エクステンション のリストを指定するものです。 デフォ
ルトでは、@vendor/yiisoft/extensions.php というファイルによって返され〶〹〳〮〳〮 アプリケーション

る配列を取ります。 extensions.php は、ぃはねばはびづひ6 を使ってエクステン
ションをインストールすると、自動的に生成され保守されます。 ですから、たいていの場合、このプロパティをあなたが構成する必要はありません。
エクステンションを手作業で保守したいという特殊なケースにおいては、次のようにしてこのプロパティを構成することが出来ます。
['extensions' => [['name' => 'extension name','version' => 'version number','bootstrap' => 'BootstrapClassName',
列でもよい'alias' => [ // optional'@alias1' => 'to/path1','@alias2' => 'to/path2',],],// オプション、構成情報の配// ... 上記と同じように、更にエクステンションを構成 ...
],]ご覧のように、このプロパティはエクステンションの仕様を示す配列を取ります。 それぞれのエクステンションは、name と version の要素を含む配列によって指定されます。 エクステンションが ブートストラップ の過程で走る必要がある場合には、bootstrap 要素をブートストラップのクラス名または 構成情報 の配列によって指定することが出来ます。 また、
エクステンションはいくつかの エイリアス を定義することも出来ます。
ぬちべはふぴ このプロパティは、ビュー をレンダリングするときに使われるべきデフォルトのレイアウトを指定するものです。 デフォルト値は'main' であり、レイアウト・パス の下にある main.php というファイルが使われるべきことを意味します。 レイアウト・パス と ビュー・パス の両方がデフォルト値を取る場合、デフォルトのレイアウト・ファイルは@app/views/layouts/main.php というパス・エイリアスとして表すことが出来ます。
滅多には無いことですが、レイアウトをデフォルトで無効にしたい場
合は、このプロパティを false として構成することが出来ます。
ぬちべはふぴぐちぴと このプロパティは、レイアウト・ファイルが捜されるべきパスを指定するものです。 デフォルト値は、ビュー・パス の下の layouts
サブ・ディレクトリです。 ビュー・パス がデフォルト値を取る場合、デ6

https://getcomposer.org

〷〰

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

フォルトのレイアウト・パスは @app/views/layouts というパス・エイリア
スとして表すことが出来ます。
このプロパティはディレクトリまたはパス・エイリアス として構成することが出来ます。
ひふのぴどねづぐちぴと このプロパティは、ログ・ファイルやキャッシュ・ファ
イルなどの一時的ファイルを生成することが出来るパスを指定するものです。 デフォルト値は、@app/runtime というエイリアスで表現されるディレクトリです。
このプロパティはディレクトリまたはパス・エイリアス として構成することが出来ます。 ランタイムパスは、アプリケーションを実行するプ
ロセスによって書き込みが可能なものでなければならないことに注意してください。 そして、この下にある一時的ファイルは秘匿を要する情報を含みうるものですので、ランタイム・パスはエンド・ユーザによるアクセスから保護されなければなりません。
このパスに簡単にアクセスできるように、すどど は @runtime というパス・エイリアスを事前に定義しています。
ぶどづぷぐちぴと このプロパティはビュー・ファイルが配置されるルート・
ディレクトリを指定するものです。デフォルト値は、@app/views というエイリアスで表現されるディレクトリです。 このプロパティはディレクト
リまたはパス・エイリアス として構成することが出来ます。
ぶづのつはひぐちぴと このプロパティは、ぃはねばはびづひ7 によって管理される ぶづのつはひ
ディレクトリを指定するものです。 すどど フレームワークを含めて、あな
たのアプリケーションによって使われる全てのサード・パーティ・ライ
ブラリを格納するディレクトリです。 デフォルト値は、@app/vendor というエイリアスで表現されるディレクトリです。
このプロパティはディレクトリまたはパス・エイリアス として構成することが出来ます。 このプロパティを修正するときは、必ず、ぃはねばはびづひの構成もそれに合せて修正してください。
このパスに簡単にアクセスできるように、すどど は @vendor というパス・
エイリアスを事前に定義しています。
づのちぢぬづぃはひづぃはねねちのつび このプロパティは コンソール・アプリケーショ
ン においてのみサポートされています。 すどど リリースに含まれているコ
ア・コマンドを有効にすべきか否かを指定するものです。デフォルト値
は true です。

3.3.3

アプリケーションのイベント

アプリケーションはリクエストを処理するライフサイクルの中でいくつ
7

https://getcomposer.org

〳〮〳〮 アプリケーション〷〱

かのイベントをトリガします。 これらのイベントに対して、下記のよ
うにして、アプリケーションの構成情報の中でイベント・ハンドラをアタッチすることが出来ます。
[]'on beforeRequest' => function ($event) {// ...
},

on eventName という構文の使い方については、構成情報 のセクションで説明されています。
別の方法として、アプリケーションのインスタンスが生成された
後、ブートストラップの過程 の中でイベント・ハンドラをアタッチすることも出来ます。 例えば、
\Yii::$app->on(\yii\base\Application::EVENT_BEFORE_REQUEST, function($event) {// ...
});

ぅざぅぎごたあぅうくげぅたげぅけさぅこご
このイベントは、アプリケーションがリクエストを処理する 前 にトリガされます。実際のイベント名は beforeRequest です。
このイベントがトリガされるときには、アプリケーションのインスタ
ンスは既に構成されて初期化されています。 ですから、イベント・メカ
ニズムを使って、リクエスト処理のプロセスに干渉するカスタム・コー
ドを挿入するのには、ちょうど良い場所です。 例えば、このイベント・
ハンドラの中で、何らかのパラメータに基づいて べどどぜぢちびづぜぁばばぬどっちぴどはの〺〺〤ぬちのでふちでづ プロパティを動的にセットすることが出来ます。
ぅざぅぎごたぁうごぅげたげぅけさぅこご
このイベントは、アプリケーションがリクエストの処理を完了した 後、レスポンスを送信する 前 にトリガされます。 実際のイベント名はafterRequest です。
このイベントがトリガされるときにはリクエストの処理は完了していますので、この機をとらえて、 リクエストに対する何らかの後処理をしたり、レスポンスをカスタマイズしたりすることが出来ます。
ひづびばはのびづ コンポーネントも、エンド・ユーザにレスポンスのコンテントを送出する間にいくつかのイベントをトリガすることに注意してください。 それらのイベントは、このイベントの 後 にトリガされます。
ぅざぅぎごたあぅうくげぅたぁぃごぉくぎ
このイベントは、コントローラ・アクション を実行する 前 に毎回トリガされます。 実際のイベント名は beforeAction です。

〷〲

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

イベントのパラメータは べどどぜぢちびづぜぁっぴどはのぅぶづのぴ のインスタンスです。 イベント・ハンドラは、べどどぜぢちびづぜぁっぴどはのぅぶづのぴ〺〺〤どびざちぬどつ プロパ
ティを false にセットして、アクションの実行を中止することが出来ます。 例えば、[]'on beforeAction' => function ($event) {if (何らかの条件) {$event->isValid = false;} else {}},同じ beforeAction イベントが、モジュール と コントローラ からもトリガされることに注意してください。 アプリケーション・オブジェクトが最初にこのイベントをトリガし、次に 〨もし有れば〩 モジュールが、 そして最後にコントローラがこのイベントをトリガします。 いずれかのイベン
ト・ハンドラが べどどぜぢちびづぜぁっぴどはのぅぶづのぴ〺〺〤どびざちぬどつ を false にセットすると、後続のイベントはトリガされません。

ぅざぅぎごたぁうごぅげたぁぃごぉくぎ
このイベントは、コントローラ・アクション を実行した 後 に毎回トリガされます。 実際のイベント名は afterAction です。
イベントのパラメータは べどどぜぢちびづぜぁっぴどはのぅぶづのぴ のインスタンスです。 べどどぜぢちびづぜぁっぴどはのぅぶづのぴ〺〺〤ひづびふぬぴ プロパティを通じて、イベント・
ハンドラはアクションの結果にアクセスしたり、またはアクションの結果を修正したり出来ます。 例えば、[]

'on afterAction' => function ($event) {if (何らかの条件) {// $event->result を修正する} else {}},同じ afterAction イベントが、モジュール と コントローラ からもトリガされることに注意してください。 これらのオブジェクトは、beforeActionの場合とは逆の順でイベントをトリガします。 すなわち、コントロー
ラ・オブジェクトが最初にこのイベントをトリガし、次に 〨もし有れば〩モジュールが、 そして最後にアプリケーションがこのイベントをトリガします。

〳〮〳〮 アプリケーション

3.3.4

〷〳

アプリケーションのライフサイクル

エントリ・スクリプト が実行されて、リクエストが処理されるとき、
アプリケーションは次のようなライフサイクルを経ます。
〱〮 エントリ・スクリプトがアプリケーションの構成情報を配列として読み出す。
〲〮 エントリ・スクリプトがアプリケーションの新しいインスタンスを作成する。
• ばひづぉのどぴ〨〩 が呼び出されて、ぢちびづぐちぴと のような、 優先度の高いアプリケーション・プロパティを構成する。
• エラー・ハンドラ を登録する。
• アプリケーションのプロパティを構成する。
• どのどぴ〨〩 が呼ばれ、そこから更に、ブートストラップ・コン
ポーネントを走らせるために、 ぢははぴびぴひちば〨〩 が呼ばれる。
〳〮 エ ン ト リ ・ ス ク リ プ ト が べどどぜぢちびづぜぁばばぬどっちぴどはの〺〺ひふの〨〩 を 呼 ん
で、アプリケーションを走らせる。
• ぅざぅぎごたあぅうくげぅたげぅけさぅこご イベントをトリガする。
• リクエストを処理する〺 リクエストを ルート とそれに結び付くパラメータとして解決する。 ルートによって指定されたモ
ジュール、コントローラ、および、アクションを作成する。そしてアクションを実行する。

〷〴

ぃえぁぐごぅげ 〳〮 アプリケーションの構造• ぅざぅぎごたぁうごぅげたげぅけさぅこご イベントをトリガする。
• エンド・ユーザにレスポンスを送信する。
〴〮 エントリ・スクリプトがアプリケーションから終了ステータスを受け取り、リクエストの処理を完了する。

3.4

アプリケーション・コンポーネント

アプリケーションは サービス・ロケータ です。 アプリケーションは、
リクエストを処理するためのいろいろなサービスを提供する一組の アプ
リケーション・コンポーネント と呼ばれるものをホストします。 例え
ば、urlManager がウェブ・リクエストを適切なコントローラにルーティングする役割を負い、 db コンポーネントが いあ 関連のサービスを提供する、等々です。
全てのアプリケーション・コンポーネントは、それぞれ、同一のアプ
リケーション内で他のアプリケーション・コンポーネントから区別できるように、ユニークな ぉい を持ちます。 アプリケーション・コンポーネントには、次の式によってアクセス出来ます。
\Yii::$app->componentID

例えば、\Yii::$app->db を使って、アプリケーションに登録された いあ 接続 を取得することが出来ます。 また、\Yii::$app->cache を使って、プライマリ・キャッシュ を取得できます。
アプリケーション・コンポーネントは、上記の式を使ってアクセスされた最初の時に作成されます。 二度目以降のアクセスでは、同じコン
ポーネント・インスタンスが返されます。
どのようなオブジェクトでも、アプリケーション・コンポーネントとすることが可能です。 アプリケーションの構成情報 の中で べどどぜぢちびづ
ぜぁばばぬどっちぴどはの〺〺〤っはねばはのづのぴび プロパティを構成することによって、アプ
リケーション・コンポーネントを登録することが出来ます。 例えば、[

'components' => [// クラス名を使って "cache" コンポーネントを登録'cache' => 'yii\caching\ApcCache',// 構成情報の配列を使って "db" コンポーネントを登録'db' => ['class' => 'yii\db\Connection','dsn' => 'mysql:host=localhost;dbname=demo','username' => 'root','password' => '',],// 無名関数を使って "search" コンポーネントを登録〳〮〴〮 アプリケーション・コンポーネント

]

],

〷〵

'search' => function () {return new app\components\SolrService;},

情報〺 必要なだけ多くのアプリケーション・コンポーネントを登録することが出来ますが、慎重にしなければなりません。
アプリケーション・コンポーネントはグローバル変数のようなものです。 あまり多くのアプリケーション・コンポーネン
トを使うと、コードのテストと保守が困難になるおそれがあります。 多くの場合、必要なときにローカルなコンポーネン
トを作成して使用するだけで十分です。

3.4.1

コンポーネントをブートストラップに含める

上述のように、アプリケーション・コンポーネントは最初にアクセスされた時に初めてインスタンスが作成されます。 リクエストの間に全くアクセスされなかった時は、インスタンスは作成されません。 けれども、場合によっては、明示的にアクセスされないときでも、リクエストごとにアプリケーション・コンポーネントのインスタンスを作成したいことがあります。 そうするために、アプリケーションの ぢははぴびぴひちば プロパ
ティのリストにそのコンポーネントの ぉい を挙げることが出来ます。
また、カスタマイズしたコンポーネントをブートストラップするためにクロージャを用いることも出来ます。インスタンス化されたコンポー
ネントを返すことは要求されません。 単に べどどぜぢちびづぜぁばばぬどっちぴどはの のイ
ンスタンス化の後にコードを走らせるだけのためにクロージャを使うこ
とも出来ます。
例えば、次のアプリケーション構成情報は、log コンポーネントが常にロードされることを保証するものです。
[]'bootstrap' => ['log',
function($app){
return new ComponentX();},
function($app){// 何らかのコード
return;}],'components' => ['log' => [// "log" コンポーネントの構成情報
],
],

〷〶

3.4.2

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

コア・アプリケーション・コンポーネント

すどど は固定の ぉい とデフォルトの構成情報を持つ一連の コア・アプリケー
ション・コンポーネントを定義しています。 例えば、ひづぱふづびぴ コンポー
ネントは、ユーザ・リクエストに関する情報を収集して、 それを ルートとして解決するために使用されます。 また、つぢ コンポーネントは、それを通じてデータ・ベースクエリを実行できるデータベース接続を表現します。 すどど のアプリケーションがユーザ・リクエストを処理出来るのは、
まさにこれらのコア・アプリケーション・コンポーネントの助けがあってこそです。
下記が事前に定義されたコア・アプリケーション・コンポーネントです。 通常のアプリケーション・コンポーネントに対するのと同様に、これらを構成し、カスタマイズすることが出来ます。 コア・アプリケー
ション・コンポーネントを構成するときは、クラスを指定しない場合
は、デフォルトのクラスが使用されます。
• ちびびづぴきちのちでづひ〺 アセット・バンドルとアセットの発行を管理します。 詳細は アセット のセクションを参照してください。
• つぢ〺 データベース接続を表します。これを通じて、いあ クエリを実行することが出来ます。 このコンポーネントを構成するときは、コンポーネントのクラスはもちろん、べどどぜつぢぜぃはののづっぴどはの〺〺〤つびの のよ
うな必須のコンポーネント・プロパティを指定しなければならない
ことに注意してください。 詳細は データベース・アクセス・オブ
ジェクト のセクションを参照してください。
• づひひはひえちのつぬづひ〺 ぐえぐ のエラーと例外を処理します。 詳細は エラー
処理 のセクションを参照してください。
• てはひねちぴぴづひ〺 エンド・ユーザに表示されるデータに書式を設定します。 例えば、数字が〳桁ごとの区切りを使って表示されたり、日付が長い書式で表示されたりします。 詳細は データの書式設定 のセクションを参照してください。
• ど〱〸の〺 メッセージの翻訳と書式設定をサポートします。 詳細は 国際
化 のセクションを参照してください。
• ぬはで〺 ログ・ターゲットを管理します。 詳細は ロギング のセクションを参照してください。
• べどどぜびぷどてぴねちどぬづひぜきちどぬづひ〺 メールの作成と送信をサポートします。
詳細は メール のセクションを参照してください。
• ひづびばはのびづ〺 エンド・ユーザに送信されるレスポンスを表現します。
詳細は レスポンス のセクションを参照してください。
• ひづぱふづびぴ〺 エンド・ユーザから受信したリクエストを表現します。
詳細は リクエスト のセクションを参照してください。
• びづびびどはの〺 セッション情報を表現します。 このコンポーネントは、
ウェブ・アプリケーション においてのみ利用できます。 詳細はセッションとクッキー のセクションを参照してください。
• ふひぬきちのちでづひ〺 さげが の解析と生成をサポートします。 詳細は ルー
ティング と さげが 生成 のセクションを参照してください。

〳〮〵〮 コントローラ〷〷• ふびづひ〺 ユーザの認証情報を表現します。 このコンポーネントは、
ウェブ・アプリケーション においてのみ利用できます。 詳細は 認
証 のセクションを参照してください。
• ぶどづぷ〺 ビューのレンダリングをサポートします。 詳細は ビュー のセクションを参照してください。

3.5

コントローラコントローラは きざぃ8 アーキテクチャの一部を成すものです。 それは
べどどぜぢちびづぜぃはのぴひはぬぬづひ を拡張したクラスのオブジェクトであり、リクエ
ストの処理とレスポンスの生成について責任を負います。 具体的には、コントローラは、アプリケーション から制御を引き継いだ後、 入ってきたリクエストのデータを分析し、それを モデル に引き渡して、 モデルが生成した結果を ビュー に投入し、最終的に外に出て行くレスポンスを生成します。

3.5.1

アクション

コントローラは、エンド・ユーザがアドレスを指定して実行をリクエス
トできる最も基本的なユニットである アクション から構成されます。 コントローラは一つまたは複数のアクションを持つことが出来ます。
次の例は、view と create という二つのアクションを持つ post コント
ローラを示すものです。
namespace app\controllers;
use Yii;
use app\models\Post;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
class PostController extends Controller{
public function actionView($id){$model = Post::findOne($id);
if ($model === null) {throw new NotFoundHttpException;}}

return $this->render('view', ['model' => $model,]);

public function actionCreate(){8

https://ja.wikipedia.org/wiki/Model_View_Controller〷〸ぃえぁぐごぅげ 〳〮 アプリケーションの構造$model = new Post;}}

if ($model->load(Yii::$app->request->post()) && $model->save()) {return $this->redirect(['view', 'id' => $model->id]);} else {return $this->render('create', ['model' => $model,]);}

view アクション 〨actionView() メソッドで定義されます〩 において、コードは最初に、リクエストされたモデルの ぉい に従って モデル を読み出します。 モデルの読み出しが成功したときは、view という名前の ビュー を使ってモデルを表示します。 失敗したときは例外を投げます。
create アクション 〨actionCreate() メソッドで定義されます〩 においても、コードは似たようなものです。 最初に、リクエスト・データを使って モデル の新しいインスタンスにデータを投入することを試み、そして、モデルを保存することを試みます。 両方が成功したときは、新しく作成されたモデルの ぉい を使って view アクションにブラウザをリダイレ
クトします。 どちらかが失敗したときは、ユーザが必要なデータを入力できるようにするための create ビューを表示します。

3.5.2

ルート

エンド・ユーザは、いわゆる ルート によって、アクションを指定します。ルートは、次の部分からなる文字列です。
• モジュール ぉい〺 この部分は、コントローラがアプリケーションではない モジュール に属する場合にのみ存在します。
コントローラ ぉい 〨〨〣っはのぴひはぬぬづひ〭どつび〩〺 同じアプリケーション 〨または、コントローラがモジュールに属する場合は、同じモジュール〩 に属する全てのコン
トローラの中から、コントローラを一意に特定する文字列。
• アクション ぉい〺 同じコントローラに属する全てのアクションの中から、アクションを一意に特定する文字列。
ルートは次の形式を取ります。
ControllerID/ActionIDまたは、コントローラがモジュールに属する場合は、次の形式を取ります。
ModuleID/ControllerID/ActionIDですから、ユーザが https://hostname/index.php?r=site/index という さげがでリクエストをした場合は、 site コントローラの中の index アクションが実行されます。 ルートがどのようにしてアクションとして解決されるかについての詳細は、ルーティングと さげが 生成 のセクションを参照してください。

〳〮〵〮 コントローラ

3.5.3

〷〹

コントローラを作成する

ウェブ・アプリケーション では、コントローラは べどどぜぷづぢぜぃはのぴひはぬぬづひ
またはその子クラスから派生させなければなりません。 同様に、
コンソ ール ・ ア プ リ ケー シ ョ ン で は 、コ ン ト ロ ー ラ は べどどぜっはのびはぬづ
ぜぃはのぴひはぬぬづひ またはその子クラスから派生させなければなりません。
次のコードは site コントローラを定義するものです。
namespace app\controllers;
use yii\web\Controller;class SiteController extends Controller{}

コントローラ ぉい
通常、コントローラは特定のタイプのリソースに関するリクエストを処理するように設計されます。 この理由により、たいていは、処理するリ
ソースのタイプを示す名詞をコントローラの ぉい として使います。 例え
ば、記事データを処理するコントローラの ぉい としては、article を使うことが出来ます。
デフォルトでは、コントローラ ぉい は、小文字の英字、数字、アン
ダースコア、ダッシュ、および、フォワード・スラッシュのみを含むべきものです。 例えば、article と post-comment はともに有効なコントロー
ラ ぉい ですが、 article?、PostComment、admin\post はそうではありません。
コントローラ ぉい は、サブ・ディレクトリの接頭辞を含んでも構いません。 例えば、admin/article は、コントローラ名前空間 の下の admin サ
ブ・ディレクトリにある article コントローラを表します。 サブ・ディ
レクトリの接頭辞として有効な文字は、小文字または大文字の英字、数字、アンダースコア、そして、フォワード・スラッシュです。 フォワー
ド・スラッシュは、複数レベルのサブ・ディレクトリの区切り文字として使われます 〨例えば、panels/admin〩。
コントローラ・クラスの命名規則
コントローラ・クラスの名前は下記の手順に従ってコントローラ ぉい から導出することが出来ます。
〱〮 ハイフンで区切られた各単語の最初の文字を大文字に変える。 コン
トローラ ぉい がスラッシュを含む場合、この規則は ぉい の最後のス
ラッシュの後ろの部分にのみ適用されることに注意。
〲〮 ハイフンを削除し、フォワード・スラッシュを全てバックワード・
スラッシュに置き換える。
〳〮 接尾辞 Controller を追加する。

〸〰

ぃえぁぐごぅげ 〳〮 アプリケーションの構造〴〮 コントローラ名前空間 を頭に付ける。

以下は、コントローラ名前空間 がデフォルト値 app\controllers を取っていると仮定したときの、いくつかの例です。
• article は app\controllers\ArticleController になる。
• post-comment は app\controllers\PostCommentController になる。
• admin/post-comment は app\controllers\admin\PostCommentController になる。
• adminPanels/post-comment は app\controllers\adminPanels\PostCommentControllerになる。
コントローラ・クラスは オートロード可能 でなければなりません。
こ の 理 由 に よ り 、 上 記 の 例 の aritcle コ ン ト ロ ー ラ ・ ク ラ ス は エ イ
リアス が @app/controllers/ArticleController.php であるファイルに保存されるべきものとなります。 一方、admin/post-comment コントローラは@app/controllers/admin/PostCommentController.php というエイリアスのファ
イルに保存されるべきものとなります。
情報〺 最後の例である admin/post-comment は、どうすれば コン
トローラ名前空間 のサブ・ディレクトリにコントローラを置くことが出来るかを示しています。 この方法は、コントロー
ラをいくつかのカテゴリに分けて編成したい、けれども モジュール は使いたくない、という場合に役立ちます。
コントローラ・マップ
コントローラ・マップ を構成すると、上で述べたコントローラ ぉい とク
ラス名の制約を乗り越えることが出来ます。 これは、主として、クラス名に対する制御が及ばないサード・パーティのコントローラを使おうとする場合に有用です。
コントローラ・マップ は アプリケーションの構成情報 の中で、次のように構成することが出来ます。
[]'controllerMap' => [// クラス名を使って "account" コントローラを宣言する'account' => 'app\controllers\UserController',],// 構成情報配列を使って "article" コントローラを宣言する'article' => ['class' => 'app\controllers\PostController','enableCsrfValidation' => false,],〳〮〵〮 コントローラ〸〱

デフォルト・コントローラ
全てのアプリケーションは、それぞれ、べどどぜぢちびづぜぁばばぬどっちぴどはの〺〺〤つづてちふぬぴげはふぴづ
プロパティによって指定されるデフォルト・コントローラを持ちます。
リクエストが ルート を指定していない場合、このプロパティによって指定されたルートが使われます。 ウェブ・アプリケーション では、この値は 'site' であり、一方、コンソール・アプリケーション では、help です。 従って、さげが が https://hostname/index.php である場合は、site コン
トローラがリクエストを処理することになります。
次のように アプリケーションの構成情報 を構成して、デフォルト・
コントローラを変更することが出来ます。
[]'defaultRoute' => 'main',

3.5.4

アクションを作成する

アクションは、コントローラ・クラスの中にいわゆる アクション・メ
ソッド を定義するだけで簡単に作成することが出来ます。 アクション・
メソッドとは、action という語で始まる名前を持つ public メソッドのことです。 アクション・メソッドの返り値がエンド・ユーザに送信されるレスポンス・データを表します。次のコードは、index と hello-world という二つのアクションを定義するものです。
namespace app\controllers;
use yii\web\Controller;class SiteController extends Controller{
public function actionIndex(){
return $this->render('index');}}public function actionHelloWorld(){
return 'Hello World';}

アクション ぉいアクシ ョンは、た いてい、あ るリソース について特定の操作を実行するように設計されます。 この理由により、アクション ぉい は、通常、view、update などのような動詞になります。
デフォルトでは、アクション ぉい は、小文字の英字、数字、アンダー
スコア、そして、ハイフンのみを含むべきものです。 アクション ぉい の中〸〲ぃえぁぐごぅげ 〳〮 アプリケーションの構造のハイフンは単語を分けるために使われます。 例えば、view、update2、comment-postは全て有効なアクション ぉい ですが、view?、Update はそうではありません。
アクションは二つの方法、すなわち、インライン・アクションまたは
スタンドアロン・アクションとして作成することが出来ます。 インライ
ン・アクションはコントローラ・クラスのメソッドとして定義されるものであり、 一方、スタンドアロン・アクションは べどどぜぢちびづぜぁっぴどはの ま
たはその子クラスを拡張するクラスです。 インライン・アクションは作成するのにより少ない労力を要するため、通常は、アクションを再利用する意図がない場合に推奨されます。 もう一方のスタンドアロン・
アクションは、主として、さまざまなコントローラの中で使われること
や、エクステンション として再配布されることを目的として作成されます。
インライン・アクション
インライン・アクションは、たった今説明したように、アクション・メ
ソッドの形で定義されるアクションを指します。
アクション・メソッドの名前は、次の手順に従って、アクション ぉいから導出されます。
〱〮 アクション ぉい に含まれる各単語の最初の文字を大文字に変換する。
〲〮 ハイフンを削除する。
〳〮 接頭辞 action を付ける。
例えば、index は actionIndex となり、hello-world は actionHelloWorld となります。
補足〺 アクション・メソッドの名前は、大文字と小文字を区別します。 ActionIndex という名前のメソッドがあっても、それはアクション・メソッドとは見なされず、結果として、index
アクションに対するリクエストは例外に帰結します。 アクション・メソッドが ばふぢぬどっ でなければならない事にも注意してください。 ばひどぶちぴづ や ばひはぴづっぴづつ なメソッドがインライン・
アクションを定義することはありません。
インライン・アクションは作成するのにほとんど労力を要さないため、たいていのアクションはインライン・アクションとして定義されます。
しかし、同じアクションを別の場所で再利用する計画を持っていたり、
また、アクションを再配布したいと思っていたりする場合は、 アクショ
ンを スタンドアロン・アクション として定義することを検討すべきです。

〳〮〵〮 コントローラ〸〳

スタンドアロン・アクション
スタンドアロン・アクションは、べどどぜぢちびづぜぁっぴどはの またはその子クラスを拡張するアクション・クラスの形で定義されるものです。 例えば、すどどのリリースに べどどぜぷづぢぜざどづぷぁっぴどはの と べどどぜぷづぢぜぅひひはひぁっぴどはの が含まれていますが、 これらは両方ともスタンドアロン・アクションです。
スタンドアロン・アクションを使用するためには、下記のように、コントローラの べどどぜぢちびづぜぃはのぴひはぬぬづひ〺〺ちっぴどはのび〨〩 メソッドをオーバーラ
イドして、 アクション・マップ の中でスタンドアロン・アクションを宣言しなければなりません。
public function actions(){
return [// クラス名を使って "error" アクションを宣言する'error' => 'yii\web\ErrorAction',}];// 構成情報配列を使って "view" アクションを宣言する'view' => ['class' => 'yii\web\ViewAction','viewPrefix' => '',],ご覧のように、actions() メソッドは、キーがアクション ぉい であり、値が対応するアクションのクラス名または 構成情報 である配列を返さなけ
ればなりません。 インライン・アクションと違って、スタンドアロン・
アクションのアクション ぉい は、actions() メソッドにおいて宣言される限りにおいて、任意の文字を含むことが出来ます。
スタンドアロン・アクション・クラスを作成するためには、べどどぜぢちびづ
ぜぁっぴどはの またはその子クラスを拡張して、run() という名前の ばふぢぬどっ メ
ソッドを実装しなければなりません。 run() メソッドの役割はアクショ
ン・メソッドの役割と同じです。例えば、<?php
namespace app\components;
use yii\base\Action;
class HelloWorldAction extends Action{
public function run(){
return "Hello World";}}

アクションの結果
アクション・メソッド、または、スタンドアロン・アクションの run() メ〸〴ぃえぁぐごぅげ 〳〮 アプリケーションの構造

ソッドの返り値は、重要な意味を持ちます。 それは、対応するアクションの結果を表すものです。
返り値は、エンド・ユーザにレスポンスとして送信される レスポンス
オブジェクトとすることが出来ます。
• ウェブ・アプリケーション では、返り値を べどどぜぷづぢぜげづびばはのびづ〺〺〤つちぴち に割り当てられる任意のデータとすることも出来ます。 この
データは、後に、レスポンス・ボディを表す文字列へと変換されます。
• コンソール・アプリケーション では、返り値をコマンド実行の 終了ステータス を示す整数とすることも出来ます。
これまでに示した例においては、アクションの結果はすべて文字列であり、エンド・ユーザに送信されるレスポンス・ボディとして扱われるものでした。 次の例では、アクションがレスポンス・オブジェクトを返すことによって、ユーザのブラウザを 新しい さげが にリダイレクトすることが出来る様子が示されています 〨ひづつどひづっぴ〨〩 メソッドの返り値はレス
ポンス・オブジェクトです〩。
public function actionForward(){// ユーザのブラウザを https://example.com にリダイレクトする
return $this->redirect('https://example.com');}

アクション・パラメータ
インライン・アクションのアクション・メソッドと、スタンドアロン・
アクションの run() メソッドは、アクション・パラメータ と呼ばれるパラメータを取ることが出来ます。 パラメータの値はリクエストから取得されます。 ウェブ・アプリケーション では、各アクション・パラメータの値は $_GET からパラメータ名をキーとして読み出されます。 コンソー
ル・アプリケーション では、アクション・パラメータはコマンドライン
引数に対応します。
次の例では、view アクション 〨インライン・アクションです〩 は、二つのパラメータ、すなわち、$id と $version を宣言しています。
namespace app\controllers;
use yii\web\Controller;class PostController extends Controller{
public function actionView($id, $version = null){// ...
}}

アクション・パラメータには、次のように、さまざまなリクエストに応じて異なる値が投入されます。

〳〮〵〮 コントローラ〸〵• https://hostname/index.php?r=post/view&id=123〺 $id パラメータには '123'という値が入れられます。 一方、version というクエリ・パラメー
タは無いので、$version は null のままになります。
• https://hostname/index.php?r=post/view&id=123&version=2〺 $id および $version
パラメータに、 それぞれ、'123' と '2' が入ります。
• https://hostname/index.php?r=post/view〺 必須の $id パラメータがリク
エストで提供されていないため、 べどどぜぷづぢぜあちつげづぱふづびぴえぴぴばぅへっづばぴどはの
例外が投げられます。
• https://hostname/index.php?r=post/view&id[]=123〺 $id パラメータが予期しない配列値 ['123'] を受け取ろうとするため、 べどどぜぷづぢぜあちつげづぱふづびぴえぴぴばぅへっづばぴどはの
例外が投げられます。
アクション・パラメータに配列値を受け取らせたい場合は、次のように、パラメータに array の型ヒントを付けなければなりません。
public function actionView(array $id, $version = null){// ...
}

このようにすると、リクエストが https://hostname/index.php?r=post/view&id[]=123である場合は、$id パラメータは ['123'] という値を受け取ります。 リク
エストが https://hostname/index.php?r=post/view&id=123 である場合も、ス
カラ値 '123' が自動的に配列に変換されるため、 $id パラメータは引き続
き同じ配列値を受け取ります。
上記の例は主としてウェブ・アプリケーションでのアクション・パラ
メータの動作を示すものです。 コンソール・アプリケーションについて
は、コンソール・コマンド のセクションで詳細を参照してください。
デフォルト・アクション
すべてのコントローラは、それぞれ、べどどぜぢちびづぜぃはのぴひはぬぬづひ〺〺〤つづてちふぬぴぁっぴどはのによって指定されるデフォルト・アクションを持ちます。 ルート がコ
ントローラ ぉい のみを含む場合は、 指定されたコントローラのデフォル
ト・アクションがリクエストされたことを意味します。
デフォルトでは、デフォルト・アクションは index と設定されます。
このデフォルト値を変更したい場合は、以下のように、コントローラ・
クラスでこのプロパティをオーバーライドするだけです。
namespace app\controllers;
use yii\web\Controller;class SiteController extends Controller{
public $defaultAction = 'home';
public function actionHome()〸〶ぃえぁぐごぅげ 〳〮 アプリケーションの構造
{

}

}

3.5.5

return $this->render('home');

コントローラのライフサイクル

リクエストを処理するときに、アプリケーション はリクエストされた
ルート に基いてコントローラを作成します。 そして、次に、コントロー
ラはリクエストに応じるために以下のライフサイクルを経過します。
〱〮 コントローラが作成され構成された後、べどどぜぢちびづぜぃはのぴひはぬぬづひ〺〺
どのどぴ〨〩 メソッドが呼ばれる。
〲〮 コントローラは、リクエストされたアクション ぉい に基いて、アクション・オブジェクトを作成する。
• アクション ぉい が指定されていないときは、デフォルト・アク
ション ぉい が使われる。
• アクション ぉい が アクション・マップ の中に見つかった場合
は、 スタンドアロン・アクションが作成される。
• アクション ぉい に合致するアクション・メソッドが見つかった
場合は、インライン・アクションが作成される。
• 上記以外の場合は、べどどぜぢちびづぜぉのぶちぬどつげはふぴづぅへっづばぴどはの 例外が投げられる。
〳〮 コントローラは、アプリケーション、〨コントローラがモジュールに属する場合は〩 モジュール、 そしてコントローラの beforeAction()
メソッドをこの順で呼び出す。
• どれか一つの呼び出しが false を返した場合は、残りのまだ呼ばれていない beforeAction() メソッドはスキップされ、 アクションの実行はキャンセルされる。
• デフォルトでは、それぞれの beforeAction() メソッドは、ハン
ドラをアタッチすることが可能な beforeAction イベントをトリガする。
〴〮 コントローラがアクションを実行する。
• アクション・パラメータが解析されて、リクエスト・データか
らデータが投入される。
〵〮 コントローラは、コントローラ、〨コントローラがモジュールに属する場合は〩 モジュール、 そしてアプリケーションの afterAction()
メソッドをこの順で呼び出す。
• デフォルトでは、それぞれの afterAction() メソッドは、ハン
ドラをアタッチすることが可能な afterAction イベントをトリガする。

〳〮〶〮 モデル〸〷〶〮 アプリケーションはアクションの結果を受け取り、それを レスポン
ス に割り当てる。

3.5.6

ベスト・プラクティス

良く設計されたアプリケーションでは、コントローラはたいてい非常に軽いものになり、 それぞれのアクションは数行のコードしか含まないものになります。 あなたのコントローラが少々複雑になっている場合、そのことは、通常、コントローラをリファクタして、コードの一部を他のクラスに移動すべきことを示すものです。
いくつかのベスト・プラクティスを特に挙げるなら、コントローラ
は、• リクエスト データにアクセスすることが出来ます。
• リクエスト・データを使って モデル や他のサービス・コンポーネントのメソッドを呼ぶことが出来ます。
• ビュー を使ってレスポンスを構成することが出来ます。
• リクエストされたデータの処理をするべきではありません 〭 データ
は モデルのレイヤ において処理されるべきです。
• えごきが を埋め込むなどの表示に関わるコードは避けるべきです 〭 表
示は ビュー で行う方が良いです。

3.6

モデル

モデルは きざぃ9 アーキテクチャの一部を成すものです。 これは、ビジネスのデータ、規則、ロジックを表現するオブジェクトです。
モデル・クラスは、べどどぜぢちびづぜきはつづぬ またはその子クラスを拡張することによって作成することが出来ます。 基底クラス べどどぜぢちびづぜきはつづぬ
は、次のような数多くの有用な機能をサポートしています。
• 属性〺 ビジネス・データを表現します。通常のオブジェクト・プロ
パティや配列要素のようにして アクセスすることが出来ます。
• 属性のラベル〺 属性の表示ラベルを指定します。
• 一括代入〺 一回のステップで複数の属性にデータを投入することをサポートしています。
• 検証規則〺 宣言された検証規則に基いて入力されたデータの有効性を保証します。
• データのエクスポート〺 カスタマイズ可能な形式でモデル・データ
を配列にエクスポートすることが出来ます。
Model クラスは、アクティブ・レコード のような、更に高度なモデルの基底クラスでもあります。 それらの高度なモデルについての詳細は、関連するドキュメントを参照してください。
情報〺 あなたのモデル・クラスの基底クラスとして べどどぜぢちびづ
ぜきはつづぬ を使うことが要求されている訳ではありません。 し9https://ja.wikipedia.org/wiki/Model_View_Controller〸〸

ぃえぁぐごぅげ 〳〮 アプリケーションの構造
かしながら、すどど のコンポーネントの多くが べどどぜぢちびづぜきはつづぬをサポートするように作られていますので、通常は べどどぜぢちびづ
ぜきはつづぬ がモデルの基底クラスとして推奨されます。

3.6.1

属性

モデルはビジネス・データを 属性 の形式で表現します。全ての属性はそれぞれパブリックにアクセス可能なモデルのプロパティと同様なものです。 べどどぜぢちびづぜきはつづぬ〺〺ちぴぴひどぢふぴづび〨〩 メソッドが、モデルがどのような属性を持つかを指定します。
属性に対しては、通常のオブジェクト・プロパティにアクセスするのと同じようにして、アクセスすることが出来ます。
$model = new \app\models\ContactForm;// "name" は ContactForm の属性$model->name = 'example';echo $model->name;

また、配列の要素にアクセスするようして、属性にアクセスすることも出来ます。 これは、べどどぜぢちびづぜきはつづぬ が ぁひひちべぁっっづびび インタフェイス10 とごひちぶづひびちぢぬづ インタフェイス11 をサポートしている恩恵です。
$model = new \app\models\ContactForm;// 配列要素のように属性にアクセスする$model['name'] = 'example';echo $model['name'];// モデルは foreach で中身をたどることが出来る
foreach ($model as $name => $value) {echo "$name: $value\n";}属性を定義する
あなたのモデルが べどどぜぢちびづぜきはつづぬ を直接に拡張するものである場合、デフォルトでは、全ての static でない public な メンバ変数は属性となります。 例えば、次に示す ContactForm モデルは四つの属性、すなわ
ち、name、email、subject、そして、body を持ちます。 この ContactForm モ
デルは、えごきが フォームから受け取る入力データを表現するために使われます。
namespace app\models;
use yii\base\Model;
1011https://www.php.net/manual/ja/class.arrayaccess.php
https://www.php.net/manual/ja/class.traversable.php〳〮〶〮 モデル〸〹

class ContactForm extends Model{public $name;public $email;public $subject;public $body;}

べどどぜぢちびづぜきはつづぬ〺〺ちぴぴひどぢふぴづび〨〩 をオーバーライドして、属性を異なる方法で定義することが出来ます。 このメソッドはモデルが持つ属性の名
前を返さなくてはなりません。 例えば、べどどぜつぢぜぁっぴどぶづげづっはひつ は、関連付けられたデータベース・テーブルのコラム名を属性の名前として返す
ことによって、属性を定義しています。 ただし、これと同時に、定義された属性に対して通常のオブジェクト・プロパティと同じようにアクセスすることが出来るように、 __get() や __set() などのマジック・メソッ
ドをオーバーライドする必要があるかもしれないことに注意してください。
属性のラベル
属性の値を表示したり、入力してもらったりするときに、属性と関連付けられたラベルを表示する必要があることがよくあります。 例えば、firstName という名前の属性を考えたとき、入力フォームやエラー・
メッセージのような箇所でエンド・ユーザに表示するときは、 もっと
ユーザ・フレンドリーな First Name というラベルを表示したいと思うでしょう。
べどどぜぢちびづぜきはつづぬ〺〺でづぴぁぴぴひどぢふぴづがちぢづぬ〨〩 を呼ぶことによって属性のラベルを得ることが出来ます。例えば、$model = new \app\models\ContactForm;// "Name" を表示する
echo $model->getAttributeLabel('name');

デフォルトでは、属性のラベルは属性の名前から自動的に生成されます。 ラベルの生成は べどどぜぢちびづぜきはつづぬ〺〺でづのづひちぴづぁぴぴひどぢふぴづがちぢづぬ〨〩 というメソッドによって行われます。 このメソッドは、キャメルケースの変数名を複数の単語に分割し、各単語の最初の文字を大文字にします。 例
えば、username は Username となり、firstName は First Name となります。
自動的に生成されるラベルを使用したくない場合は、べどどぜぢちびづぜきはつづぬ〺〺ちぴぴひどぢふぴづがちぢづぬび〨〩 をオーバーライドして、 属性のラベルを明示的に宣言することが出来ます。例えば、
namespace app\models;
use yii\base\Model;〹〰

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

class ContactForm extends Model{public $name;public $email;public $subject;public $body;}

public function attributeLabels(){
return ['name' => 'Your name','email' => 'Your email address','subject' => 'Subject','body' => 'Content',];}

複数の言語をサポートするアプリケーションでは、属性のラベルを翻訳したいと思うでしょう。 これも、以下のように、ちぴぴひどぢふぴづがちぢづぬび〨〩 の中で行うことが出来ます。
public function attributeLabels(){
return ['name' => \Yii::t('app', 'Your name'),'email' => \Yii::t('app', 'Your email address'),'subject' => \Yii::t('app', 'Subject'),'body' => \Yii::t('app', 'Content'),];}

条件に従って属性のラベルを定義することも出来ます。 例えば、モデルが使用される シナリオ に基づいて、同じ属性に対して違うラベルを返す
ことことが出来ます。
情報〺 厳密に言えば、属性のラベルは ビュー の一部を成すものです。 しかし、たいていの場合、モデルの中でラベルを宣言する方が便利が良く、結果としてクリーンで再利用可能な
コードになります。

3.6.2

シナリオ

モデルはさまざまに異なる シナリオ で使用されます。 例えば、User モデ
ルはユーザ・ログインの入力を収集するために使われますが、同時に、ユーザ登録の目的でも使われます。 異なるシナリオの下では、モデルが使用するビジネス・ルールとロジックも異なるものになり得ます。 例え
ば、email 属性はユーザ登録の際には必須とされるかも知れませんが、ログインの際にはそうではないでしょう。

〳〮〶〮 モデル〹〱

モデルは べどどぜぢちびづぜきはつづぬ〺〺〤びっづのちひどは プロパティを使って、自身が使われているシナリオを追跡します。 デフォルトでは、モデルは defaultという一つのシナリオだけをサポートします。 次のコードは、モデルのシナリオを設定する二つの方法を示すものです。
// シナリオをプロパティとして設定する$model = new User;$model->scenario = User::SCENARIO_LOGIN;// シナリオを設定情報で設定する$model = new User(['scenario' => User::SCENARIO_LOGIN]);

デフォルトでは、モデルによってサポートされるシナリオは、モデルで宣言されている 検証規則 によって決定されます。 しかし、次のように、べどどぜぢちびづぜきはつづぬ〺〺びっづのちひどはび〨〩 メソッドをオーバーライドして、 この振る舞いをカスタマイズすることが出来ます。
namespace app\models;
use yii\db\ActiveRecord;class User extends ActiveRecord{
const SCENARIO_LOGIN = 'login';const SCENARIO_REGISTER = 'register';}public function scenarios(){
return [self::SCENARIO_LOGIN => ['username', 'password'],self::SCENARIO_REGISTER => ['username', 'email', 'password'],];}情報〺 上記の例と後続の例では、モデル・クラスは べどどぜつぢ
ぜぁっぴどぶづげづっはひつ を拡張するものとなっています。 というのは、複数のシナリオを使用することは、通常は、アクティ
ブ・レコード クラスで発生するからです。
scenarios() メソッドは、キーがシナリオの名前であり、値が対応する
アクティブな属性 である配列を返します。 アクティブな属性とは、一括代入 することが出来て、検証 の対象になる属性です。 上記の例では、login シナリオにおいては username と password の属性がアクティブであり、 一方、register シナリオにおいては、username と password に加えて
email もアクティブです。
scenarios() のデフォルトの実装は、検証規則の宣言メソッドである
べどどぜぢちびづぜきはつづぬ〺〺ひふぬづび〨〩 に現れる全てのシナリオを返すものです。
scenarios() をオーバーライドするときに、デフォルトのシナリオに加えて新しいシナリオを導入したい場合は、 次のようなコードを書きます。

〹〲

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

namespace app\models;
use yii\db\ActiveRecord;class User extends ActiveRecord{
const SCENARIO_LOGIN = 'login';const SCENARIO_REGISTER = 'register';}public function scenarios(){$scenarios = parent::scenarios();$scenarios[self::SCENARIO_LOGIN] = ['username', 'password'];$scenarios[self::SCENARIO_REGISTER] = ['username', 'email','password'];return $scenarios;}

シナリオの機能は、主として、検証 と 属性の一括代入 によって使用されます。 しかし、他の目的に使うことも可能です。例えば、現在のシナリオに基づいて異なる 属性のラベル を宣言することも出来ます。

3.6.3

検証規則

モデルのデータをエンド・ユーザから受け取ったときは、データを検証して、 それが一定の規則 〨検証規則、あるいは、いわゆる ビジネス・ルール〩 を満たしていることを確認しなければなりません。 ContactForm
モデルを例に挙げるなら、全ての属性が空ではなく、email 属性が有効な
メール・アドレスを含んでいることを確認したいでしょう。 いずれかの属性の値が対応するビジネス・ルールを満たしていないときは、 ユーザ
がエラーを訂正するのを助ける適切なエラー・メッセージが表示されなければなりません。
受信したデータを検証するために、べどどぜぢちびづぜきはつづぬ〺〺ぶちぬどつちぴづ〨〩 を呼ぶことが出来ます。 このメソッドは、べどどぜぢちびづぜきはつづぬ〺〺ひふぬづび〨〩 で宣言された検証規則を使って、該当するすべての属性を検証します。 エラーが見つからなければ、メソッドは true を返します。 そうでなければ、べどどぜぢちびづぜきはつづぬ〺〺〤づひひはひび にエラーを保存して、false を返します。
例えば、$model = new \app\models\ContactForm;// モデルの属性にユーザの入力を代入する$model->attributes = \Yii::$app->request->post('ContactForm');
if ($model->validate()) {// すべての入力値は有効である} else {// 検証が失敗: $errors はエラー・メッセージを含む配列

〳〮〶〮 モデル}〹〳$errors = $model->errors;

モデルに関連付けられた検証規則を宣言するためには、べどどぜぢちびづぜきはつづぬ〺〺ひふぬづび〨〩 メソッドをオーバーライドして、 モデルの属性が満たすべき規則を返すようにします。 次の例は、ContactForm モデルのために宣言された検証規則を示します。
public function rules(){return [// name、email、subject、body の属性が必須[['name', 'email', 'subject', 'body'], 'required'],}];// email 属性は、有効なメール・アドレスでなければならない['email', 'email'],

一つの規則は、一つまたは複数の属性を検証するために使うことが出来ます。 また、一つの属性は、一つまたは複数の規則によって検証することが出来ます。 検証規則をどのように宣言するかについての詳細は 入力を検証する のセクションを参照してください。
時として、特定の シナリオ にのみ適用される規則が必要になるでしょう。 そのためには、下記のように、規則に on プロパティを指定することが出来ます。
public function rules(){return [// "register" シナリオでは、username、email、password のすべてが必須[['username', 'email', 'password'], 'required', 'on' =>
self::SCENARIO_REGISTER],}];// "login" シナリオでは、username と password が必須[['username', 'password'], 'required', 'on' =>
self::SCENARIO_LOGIN],

on プロパティを指定しない場合は、その規則は全てのシナリオに適用されることになります。 現在の シナリオ に適用可能な規則は アクティブな規則 と呼ばれます。
属性が検証されるのは、それが scenarios() の中でアクティブな属性であると宣言されており、かつ、 その属性が rules() の中で宣言されている一つまたは複数のアクティブな規則と結び付けられている場合であり、また、そのような場合だけです。

〹〴

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

3.6.4

一括代入

一括代入は、一行のコードを書くだけで、ユーザの入力した複数のデータをモデルに投入できる便利な方法です。 一括代入は、入力されたデー
タを べどどぜぢちびづぜきはつづぬ〺〺〤ちぴぴひどぢふぴづび プロパティに直接に代入することによって、モデルの属性にデータを投入します。 次の二つのコード断片は等価であり、どちらもエンド・ユーザから送信されたフォームのデータ
を ContactForm モデルの属性に割り当てようとするものです。 明らかに、一括代入を使う前者の方が、後者よりも明快で間違いも起こりにくいでしょう。
$model = new \app\models\ContactForm;$model->attributes = \Yii::$app->request->post('ContactForm');$model = new \app\models\ContactForm;$data = \Yii::$app->request->post('ContactForm', []);
$model->name = isset($data['name']) ? $data['name'] : null;$model->email = isset($data['email']) ? $data['email'] : null;$model->subject = isset($data['subject']) ? $data['subject'] : null;$model->body = isset($data['body']) ? $data['body'] : null;

安全な属性
一括代入は、いわゆる 安全な属性、すなわち、べどどぜぢちびづぜきはつづぬ〺〺びっづのちひどはび〨〩
においてモデルの現在の シナリオ のためにリストされている属性に対してのみ適用されます。 例えば、User モデルが次のようなシナリオ宣言を持っている場合において、現在のシナリオが login であるときは、
username と password のみが一括代入が可能です。 その他の属性はいっさ
い触れられません。
public function scenarios(){
return [self::SCENARIO_LOGIN => ['username', 'password'],self::SCENARIO_REGISTER => ['username', 'email', 'password'],];}情報〺 一括代入が安全な属性に対してのみ適用されるのは、
エンド・ユーザの入力データがどの属性を修正することが出来るか、 ということを制御する必要があるからです。 例えば、User モデルに、ユーザに割り当てられた権限を決定する
permission という属性がある場合、 この属性を修正できるのは、管理者がバックエンドのインタフェイスを通じてする時だけに制限したいでしょう。
べどどぜぢちびづぜきはつづぬ〺〺びっづのちひどはび〨〩 のデフォルトの実装は べどどぜぢちびづぜきはつづぬ〺〺
ひふぬづび〨〩 に現われる全てのシナリオと属性を返すものです。 従って、こ〳〮〶〮 モデル〹〵のメソッドをオーバーライドしない場合は、アクティブな検証規則のどれかに出現する限り、 その属性は安全である、ということになります。
このため、実際に検証することなく属性を安全であると宣言できるよ
うに、 safe というエイリアスを与えられた特別なバリデータが提供されています。 例えば、次の規則は title と description の両方が安全な属性であると宣言しています。
public function rules(){return [[['title', 'description'], 'safe'],];}

安全でない属性
上記で説明したように、べどどぜぢちびづぜきはつづぬ〺〺びっづのちひどはび〨〩 メソッドは二つの目的を持っています。 すなわち、どの属性が検証されるべきかを決めることと、どの属性が安全であるかを決めることです。 めったにない場
合として、属性を検証する必要はあるが、安全であるという印は付けた
くない、ということがあります。 そういう時は、下の例の secret 属性のように、名前の前に感嘆符 ! を付けて scenarios() の中で宣言することが出来ます。
public function scenarios(){
return [self::SCENARIO_LOGIN => ['username', 'password', '!secret'],];}このモデルが login シナリオにある場合、三つの属性は全て検証されます。 しかし、username と password の属性だけが一括代入が可能です。
secret 属性に入力値を割り当てるためには、下記のように明示的に代入を実行する必要があります。
$model->secret = $secret;

同じ事が rules() メソッドの中でも出来ます。
public function rules(){return [[['username', 'password', '!secret'], 'required', 'on' => 'login']];}

この場合、username、password そして secret の属性が必須項目とされますが、secret は明示的に代入される必要があります。

〹〶

3.6.5

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

データのエクスポート

モデルを他の形式にエクスポートする必要が生じることはよくあります。例えば、モデルのコレクションを おこくぎ や ぅへっづぬ 形式に変換したい
場合があるでしょう。 このエクスポートのプロセスは二つの独立したス
テップに分割することが出来ます。
• モデルが配列に変換され、• 配列が目的の形式に変換される。
あなたは最初のステップだけに注力することが出来ます。 と言うのは、第二のステップは汎用的なデータ・フォーマッタ、例えば べどどぜぷづぢ
ぜおびはのげづびばはのびづうはひねちぴぴづひ によって達成できるからです。
モデルを配列に変換する最も簡単な方法は、べどどぜぢちびづぜきはつづぬ〺〺〤ちぴぴひどぢふぴづび
プロパティを使うことです。 例えば、
$post = \app\models\Post::findOne(100);$array = $post->attributes;

デフォルトでは、べどどぜぢちびづぜきはつづぬ〺〺〤ちぴぴひどぢふぴづび プロパティは べどどぜぢちびづ
ぜきはつづぬ〺〺ちぴぴひどぢふぴづび〨〩 で宣言されている 全て の属性の値を返します。
モデルを配列に変換するためのもっと柔軟で強力な方法は、べどどぜぢちびづ
ぜきはつづぬ〺〺ぴはぁひひちべ〨〩 メソッドを使うことです。 このメソッドのデフォル
トの動作は べどどぜぢちびづぜきはつづぬ〺〺〤ちぴぴひどぢふぴづび のそれと同じものです。 しかしながら、このメソッドを使うと、どのデータ項目 〨フィールド と呼ばれます〩 を結果の配列に入れるか、そして、その項目にどのような書式を適用するかを選ぶことが出来ます。 実際、レスポンス形式の設定 で説明されているように、げぅこごてふぬ ウェブサービスの開発においては、 これがモデルをエクスポートするデフォルトの方法となっています。
フィールド
フィールドとは、単に、モデルの べどどぜぢちびづぜきはつづぬ〺〺ぴはぁひひちべ〨〩 メソッドを呼ぶことによって取得される配列に含まれる、 名前付きの要素のことです。
デフォルトでは、フィールドの名前は属性の名前と等しいものになります。 しかし、このデフォルトの動作は、てどづぬつび〨〩 および〯またはづへぴひちうどづぬつび〨〩 メソッドをオーバーライドして、変更することが出来ます。 どちらのメソッドも、フィールド定義のリストを返すものです。
fields() によって定義されるフィールドは、デフォルト・フィールドです。すなわち、toArray() はデフォルトでこれらのフィールドを返す、ということを意味します。 extraFields() メソッドは、$expand パラメータによって指定する限りにおいて toArray() によって返される、追加のフィールドを定義するものです。 例として、次のコードは、fields() で定義された全てのフィールドと、〨extraFields() で定義されていれば〩 prettyNameと fullAddress フィールドを返すものです。
$array = $model->toArray([], ['prettyName', 'fullAddress']);〳〮〶〮 モデル〹〷fields() をオーバーライドして、フィールドを追加、削除、リネーム、再定義することが出来ます。 fields() の返り値は配列でなければなりま
せん。配列のキーはフィールド名であり、配列の値は対応するフィール
ド定義です。 フィールドの定義には、プロパティ〯属性 の名前か、または、対応するフィールドの値を返す無名関数を使うことが出来ます。
フィールド名がそれを定義する属性名と同一であるという特殊な場合においては、配列のキーを省略することが出来ます。 例えば、// 明示的に全てのフィールドをリストする方法。(API の後方互換性を保つために) DB
テーブルや// モデル属性の変更がフィールドの変更を引き起こさないことを保証したい場合に適している。
public function fields(){
return [// フィールド名が属性名と同じ'id',// フィールド名は "email"、対応する属性名は "email_address"'email' => 'email_address',}];// フィールド名は "name"、その値は PHP コールバックで定義'name' => function () {return $this->first_name . ' ' . $this->last_name;},// いくつかのフィールドを除外する方法。親の実装を継承しつつ、公開すべきでない
フィールドを// 除外したいときに最適。
public function fields(){$fields = parent::fields();// 公開すべきでない情報を含むフィールドを削除する
unset($fields['auth_key'], $fields['password_hash'],$fields['password_reset_token']);}return $fields;

警告〺 デフォルトではモデルの全ての属性がエクスポート
される配列に含まれるため、データを精査して、 公開すべきでない情報が含まれていないことを確認しなければなりません。 そういう情報がある場合は、fields() をオー
バーライドして、除外しなければなりません。 上記の例では、auth_key、password_hash および password_reset_token を除外
しています。

〹〸

3.6.6

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

ベスト・プラクティス

モデルは、ビジネスのデータ、規則、ロジックを表わす中心的なオブジェクトです。 モデルは、たいてい、さまざまな場所で再利用される必要があります。 良く設計されたアプリケーションでは、通常、モデルはコントローラ よりもはるかに太ったものになります。
要約すると、モデルは、• ビジネス・データを表現する属性を含むことが出来ます。
• データの有効性と整合性を保証する検証規則を含むことが出来ます。
• ビジネス・ロジックを実装するメソッドを含むことが出来ます。
• リクエスト、セッション、または他の環境データに直接アクセスするべきではありません。 これらのデータは、コントローラ によってモデルに注入されるべきです。
• えごきが を埋め込むなどの表示用のコードは避けるべきです 〭 表示は
ビュー で行う方が良いです。
• あまりに多くの シナリオ を一つのモデルで持つことは避けましょう。
大規模で複雑なシステムを開発するときには、たいてい、上記の最後にあげた推奨事項を考慮するのが良いでしょう。 そういうシステムでは、モデルは数多くの場所で使用され、それに従って、数多くの規則セット
やビジネス・ロジックを含むため、 非常に太ったものになり得ます。
コードの一ヶ所に触れるだけで数ヶ所の違った場所に影響が及ぶため、ついには、モデルのコードの保守が悪夢になってしまうこともよくあります。 モデルのコードの保守性を高めるためには、以下の戦略をとることが出来ます。
• 異なる アプリケーション または モジュール によって共有される
一連の基底モデル・クラスを定義します。 これらのモデル・クラス
は、すべてで共通に使用される最小限の規則セットとロジックのみを含むべきです。
• モデルを使用するそれぞれの アプリケーション または モジュールにおいて、 対応する基底モデル・クラスから拡張した具体的なモデ
ル・クラスを定義します。 この具体的なモデル・クラスが、そのアプリケーションやモジュールに固有の規則やロジックを含むべきです。
例えば、アドバンスト・プロジェクト・テンプレート12 の中で、基底モデル・クラス common\models\Post を定義することが出来ます。 次に、
フロントエンド・アプリケーションにおいては、common\models\Post から拡張した具体的なモデル・クラス frontend\models\Post を定義して使います。 また、バックエンド・アプリケーションにおいても、同様に、backend\models\Post を定義します。 この戦略を取ると、frontend\models\Postの中のコードはフロントエンド・アプリケーション固有のものであると
12
https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/
README.md〳〮〷〮 ビュー〹〹

保証することが出来ます。 そして、フロントエンドのコードにどのような変更を加えても、バックエンド・アプリケーションを壊すかもしれな
いと心配する必要がなくなります。

3.7

ビュー

ビューは きざぃ13 アーキテクチャの一部を成すものです。 ビューはエンド・ユーザにデータを表示することに責任を持つコードです。 ウェブ・
アプリケーションにおいては、ビューは、通常、ビュー・テンプレー
ト の形式、すなわち、 主として えごきが コードと表示目的の ぐえぐ コードを含む ぐえぐ スクリプト・ファイルとして作成されます。 そして、
ビュー・テンプレートを管理する ビュー アプリケーション・コンポー
ネント が、ビューの構築とレンダリングを助けるためによく使われるメ
ソッドを提供します。 なお、簡潔さを重視して、ビュー・テンプレート
またはビュー・テンプレート・ファイルを単にビューと呼ぶことがよく
あります。

3.7.1

ビューを作成する

前述のように、ビューは えごきが と ぐえぐ コードが混ざった単なる ぐえぐ
スクリプトです。 次に示すのは、ログイン・フォームを表示するビューです。 ご覧のように、ぐえぐ コードがタイトルやフォームなど動的なコン
テントを生成するのに使われ、えごきが コードがそれらを編成して表示可
能な えごきが ページを作っています。
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;/* @var $this yii\web\View *//* @var $form yii\widgets\ActiveForm *//* @var $model app\models\LoginForm */$this->title = 'ログイン';?><h1><? = Html::encode($this->title) ?> </h1><p>次の項目を入力してログインしてください:</p><?php $form = ActiveForm::begin(); ?><? = $form->field($model, 'username') ?><? = $form->field($model, 'password')->passwordInput() ?><? = Html::submitButton('ログイン') ?><?php ActiveForm::end(); ?>13

https://ja.wikipedia.org/wiki/Model_View_Controller〱〰〰

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

ビューの中では、このビュー・テンプレートを管理しレンダリングしている ビュー・コンポーネント を参照する $this にアクセスすることが出来ます。
$this 以外に、上記の例の $model のように、事前に定義される変数をビューの中に置くことが出来ます。 このような変数は、ビューのレンダ
リング をトリガする コントローラ などのオブジェクトによってビューに プッシュ されるデータを表します。
ヒント〺 上の例では、事前に定義される変数は、ぉいぅ に認識されるように、ビューの先頭のコメント・ブロックの中にリストされています。 これは、ビューにドキュメントを付けるのにも良い方法です。
セキュリティ
えごきが ページを生成するビューを作成するときは、エンド・ユーザから受け取るデータを表示する前にエンコード および〯または フィルタすることが重要です。 そうしなければ、あなたのアプリケーションは クロ
ス・サイト・スクリプティング14 攻撃を こうむるおそれがあります。
プレーン・テキストを表示するためには、まず べどどぜとづぬばづひびぜえぴねぬ〺〺
づのっはつづ〨〩 を呼んでエンコードします。 例えば、次のコードはユーザの名前を表示する前にエンコードしています。
<?php
use yii\helpers\Html;?><div class="username"><? = Html::encode($user->name) ?></div>

えごきが コンテントを表示するためには、べどどぜとづぬばづひびぜえぴねぬぐふひどてどづひ を使って、最初にコンテントをフィルタします。 例えば、次のコードは、投稿のコンテントを表示する前にフィルタしています。
<?php
use yii\helpers\HtmlPurifier;?><div class="post"><? = HtmlPurifier::process($post->text) ?></div>

ヒント〺 えごきがぐふひど〜づひ は、出力を安全なものにすることにおいては素晴らしい仕事をしますが、速くはありません。 アプ
https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AD%E3%82%B9%E3%82%B5%E3%
82%A4%E3%83%88%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%86%E3%82%A3%E3%83%
B3%E3%82%B014〳〮〷〮 ビュー〱〰〱

リケーションが高いパフォーマンスを要求する場合は、フィルター結果を キャッシュ することを考慮すべきです。
ビューを編成する
コントローラ や モデル と同じように、ビューを編成するための規約があります。〮• コントローラによって表示されるビューは、デフォルトでは、ディレクトリ @app/views/ControllerID の下に置かれるべきものです。 こ
こで、ControllerID は コントローラ ぉい を指します。 例えば、コントローラ・クラスが PostController である場合、ディレクトリは@app/views/post となります。 PostCommentController の場合は、ディレクトリは @app/views/post-comment です。 また、コントローラがモジュールに属する場合は、ディレクトリは モジュール・ディレクト
リ の下の views/ControllerID です。
• ウィジェット で表示されるビューは、デフォルトでは、WidgetPath/views
ディレクトリの下に置かれるべきものです。 ここで、WidgetPathは、ウィジェットのクラス・ファイルを含んでいるディレクトリを指します。
• 他のオブジェクトによって表示されるビューについても、ウィジェットの場合と同じ規約に従うことが推奨されます。
これらのデフォルトのビュー・ディレクトリは、コントローラやウィジェットの べどどぜぢちびづぜざどづぷぃはのぴづへぴぉのぴづひてちっづ〺〺でづぴざどづぷぐちぴと〨〩 メソッドをオーバーライドすることでカスタマイズすることが可能です。

3.7.2

ビューをレンダリングする

コントローラ の中でも、ウィジェット の中でも、または、その他のどんな場所でも、ビューをレンダリングするメソッドを呼ぶことによってビューをレンダリングすることが出来ます。 これらのメソッドは、下記に示されるような類似のシグニチャを共有します。
/*** @param string $view ビュー名またはファイル・パス (実際のレンダリング・メ
ソッドに依存する)* @param array $params ビューに引き渡されるデータ* @return string レンダリングの結果*/
methodName($view, $params = [])コントローラでのレンダリング
コントローラ の中では、ビューをレンダリングするために次のコント
ローラ・メソッドを呼ぶことが出来ます。
• ひづのつづひ〨〩〺 名前付きビュー をレンダリングし、 その結果に レイア
ウト を適用する。

〱〰〲

ぃえぁぐごぅげ 〳〮 アプリケーションの構造• ひづのつづひぐちひぴどちぬ〨〩〺 名前付きビュー をレイアウトなしでレンダリン
グする。
• ひづのつづひぁなちへ〨〩〺 名前付きビュー をレイアウトなしでレンダリング
し、登録されている全ての おこ〯ぃここ スクリプトおよびファイルを注入する。 通常、ぁおぁじ ウェブ・リクエストに対するレスポンスにおいて使用される。
• ひづのつづひうどぬづ〨〩〺 ビュー・ファイルのパスまたは エイリアス の形式で指定されたビューをレンダリングする。
• ひづのつづひぃはのぴづのぴ〨〩〺 静的な文字列をレンダリングして、現在適用可
能な レイアウトに埋め込む。 このメソッドは バージョン 〲〮〰〮〱 以
降で使用可能。
例えば、
namespace app\controllers;
use Yii;
use app\models\Post;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
class PostController extends Controller{
public function actionView($id){$model = Post::findOne($id);
if ($model === null) {throw new NotFoundHttpException;}}}// "view" という名前のビューをレンダリングし、レイアウトを適用する
return $this->render('view', ['model' => $model,]);

ウィジェットでのレンダリング
ウィジェット の中では、ビューをレンダリングするために、次のウィジェット・メソッドを使用することが出来ます。
• ひづのつづひ〨〩〺 名前付きビュー をレンダリングする。
• ひづのつづひうどぬづ〨〩〺 ビュー・ファイルのパスまたは エイリアス の形式で指定されたビューをレンダリングする。
例えば、namespace app\components;
use yii\base\Widget;
use yii\helpers\Html;

〳〮〷〮 ビュー〱〰〳

class ListWidget extends Widget{
public $items = [];}public function run(){// "list" という名前のビューをレンダリングする
return $this->render('list', ['items' => $this->items,]);}

ビューでのレンダリング
ビュー・コンポーネント によって提供される下記のメソッドのどれかを使うと、ビューの中で、別のビューをレンダリングすることが出来ます。
• ひづのつづひ〨〩〺 名前付きビュー をレンダリングする。
• ひづのつづひぁなちへ〨〩〺 名前付きビュー をレンダリングし、登録されている全ての おこ〯ぃここ スクリプトおよびファイルを注入する。 通常、ぁおぁじ ウェブリクエストに対するレスポンスにおいて使用される。
• ひづのつづひうどぬづ〨〩〺 ビュー・ファイルのパスまたは エイリアス の形式で指定されたビューをレンダリングする。
例えば、 ビューの中の次のコー ドは、現在レンダ リングされ ている
ビューと同じディレクトリにある _overview.php というビュー・ファイル
をレンダリングします。 ビューでは $this が ビュー・コンポーネントを参照することを思い出してください。
<?= $this->render('_overview') ?>他の場所でのレンダリング
場所がどこであれ、Yii::$app->view という式によって ビュー・アプリ
ケーション・コンポーネントにアクセスすることが出来ますから、 前述の ビュー・コンポーネント・メソッドを使ってビューをレンダリングすることが出来ます。例えば、// ビュー・ファイル "@app/views/site/license.php" を表示echo \Yii::$app->view->renderFile('@app/views/site/license.php');

名前付きビュー
ビューをレンダリングするとき、ビューを指定するのには、ビューの名
前か、ビュー・ファイルのパス〯エイリアスか、どちらかを使うことが出来ます。 たいていの場合は、より簡潔で柔軟な前者を使います。名前を使って指定されるビューを 名前付きビュー と呼びます。

〱〰〴

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

ビューの名前は、以下の規則に従って、対応するビュー・ファイルのパスに解決されます。
• ビュー名はファイル拡張子を省略することが出来ます。その場
合、.php が拡張子として使われます。 例えば、about というビュー
名は about.php というファイル名に対応します。
• ビ ュ ー 名 が 二 つ の ス ラ ッ シ ュ 〨//〩 で 始 ま る 場 合 は 、 対 応 す る
ビュー・ファイルのパスは @app/views/ViewName となります。 つまり、ビュー・ファイルは アプリケーションのビュー・パス の下で探されます。 例えば、//site/about は @app/views/site/about.php へと解決されます。
• ビュー名が一つのスラッシュ 〨/〩 で始まる場合は、ビュー・ファ
イルのパスは、ビュー名の前に、現在アクティブな モジュール の
ビュー・パス を置くことによって形成されます。 アクティブなモジュールが無い場合は、@app/views/ViewName が使用されます。 例え
ば、/user/create は、現在アクティブなモジュールが user である場
合は、@app/modules/user/views/user/create.php へと解決されます。 アクティブなモジュールが無い場合は、ビュー・ファイルのパスは@app/views/user/create.php となります。
• ビュ ーが コンテ キスト を伴って レンダリ ングさ れ、その コン
テキストが べどどぜぢちびづぜざどづぷぃはのぴづへぴぉのぴづひてちっづ を実装している場合
は、 ビュー・ファイルのパスは、コンテキストの ビュー・パス を
ビュー名の前に置くことによって形成されます。 これは、主として、コントローラとウィジェットの中でレンダリングされるビューに当てはまります。 例えば、コンテキストが SiteController コント
ローラである場合、about は @app/views/site/about.php へと解決されます。
• あるビューが別のビューの中でレンダリングされる場合は、後者のビュー・ファイルを含んでいるディレクトリが前者のビュー名の前に置かれて、 実際のビュー・ファイルのパスが形成されます。 例
えば、item は、@app/views/post/index.php というビューの中でレンダリングされる場合、@app/views/post/item へと解決されます。
上記の規則によって、コントローラ app\controllers\PostController の中で$this->render('view') を呼ぶと、 実際には、ビュー・ファイル @app/views/post/view.php
がレンダリングされ、一方、そのビューの中で $this->render('_overview')を呼ぶと、 ビュー・ファイル @app/views/post/_overview.php がレンダリン
グされることになります。
ビューの中でデータにアクセスするビューの中でデータにアクセスするためのアプローチが二つあります。
「プッシュ」と「プル」です。
ビューをレンダリングするメソッドに二番目のパラメータとしてデー
タを渡すのが「プッシュ」のアプローチです。 データは、「名前〭値」のペアの配列として表わされなければなりません。 ビューがレンダリング〳〮〷〮 ビュー〱〰〵

されるときに、ぐえぐ の extract() 関数がこの配列に対して呼び出され、ビューの中で使う変数が抽出されます。 例えば、次のコードはコント
ローラの中でビューをレンダリングしていますが、report ビューに二つの変数、 すなわち、$foo = 1 と $bar = 2 をプッシュしています。
echo $this->render('report', ['foo' => 1,'bar' => 2,]);「プル」のアプローチは、ビュー・コンポーネント またはビューからアクセス出来るその他のオブジェクト 〨例えば Yii::$app〩 から積極的にデータを読み出すものです。 下記のコード例のように、ビューの中では $this->context という式でコントローラ・オブジェクトを取得することが出来ます。 その結果、report ビューの中で、コントローラの全てのプロパティやメソッドにアクセスすることが出来ます。 次の例ではコント
ローラ ぉい にアクセスしています。
The controller ID is: <?= $this->context->id ?>通常は「プッシュ」アプローチが、ビューでデータにアクセスする方法として推奨されます。なぜなら、ビューのコンテキスト・オブジェクトに対する依存がより少ないからです。 その短所は、常にデータ配列を手作業で作成する必要がある、ということです。 ビューが共有されてさま
ざまな場所でレンダリングされる場合、その作業が面倒くさくなり、また、間違いも生じやすくなります。
ビューの間でデータを共有する
ビュー・コ ンポー ネン ト が提供する ばちひちねび プロ パティ を使うと 、ビューの間でデータを共有することが出来ます。
例えば、about というビューで、次のようなコードを使って、 パン屑
リストの現在の区分を指定することが出来ます。
$this->params['breadcrumbs'][] = 'About Us';

そして、レイアウト ファイル 〨これも一つのビューです〩 の中で、ばちひちねび
によって渡されたデータを使って、 パン屑リストを表示することが出来ます。
<?= yii\widgets\Breadcrumbs::widget(['links' => isset($this->params['breadcrumbs']) ?
$this->params['breadcrumbs'] : [],
]) ?>

〱〰〶

3.7.3

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

レイアウト

レイア ウトは、複数のビュ ーの共通部分をあら わす特殊なタイ プのビューです。 例えば、たいていのウェブ・アプリケーションでは、ページは共通のヘッダとフッタを持っています。 すべてのビューで同じヘッダとフッタを繰り返すことも出来ますが、もっと良い方法は、 そういうことはレイアウトの中で一度だけして、コンテント・ビューのレンダリ
ング結果をレイアウトの中の適切な場所に埋め込むことです。
レイアウトを作成する
レイアウトもまたビューですので、通常のビューと同様な方法で作成することが出来ます。 デフォルトでは、レイアウトは @app/views/layouts
ディレクトリに保存されます。 モジュール の中で使用されるレイアウ
トについては、モジュール・ディレクトリ の下の views/layouts ディレク
トリに保存されるべきものとなります。 デフォルトのレイアウト・ディ
レクトリは、アプリケーションまたはモジュールの べどどぜぢちびづぜきはつふぬづ〺〺〤ぬちべはふぴぐちぴと プロパティを構成することでカスタマイズすることが出来ます。
次の例は、レイアウトがどのようなものであるかを示すものです。
説明のために、レイアウトの中のコードを大幅に単純化していることに注意してください。 実際には、ヘッドのタグやメイン・メニューなど、もっと多くのコンテントを追加する必要があるでしょう。
<?php
use yii\helpers\Html;/* @var $this yii\web\View *//* @var $content string */?><?php $this->beginPage() ?><!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"/><? = Html::csrfMetaTags() ?><title><? = Html::encode($this->title) ?> </title><?php $this->head() ?></head><body><?php $this->beginBody() ?><header>My Company</header><? = $content ?><footer>&copy; 2014 by My Company</footer><?php $this->endBody() ?></body></html><?php $this->endPage() ?>ご覧のように、レイアウトはすべてのページに共通な えごきが タグを生成〳〮〷〮 ビュー〱〰〷

しています。 <body> セクションの中でレイアウトが $content という変数をエコーしていますが、これは、コンテント・ビューのレンダリング結果を表すものであり、 べどどぜぢちびづぜぃはのぴひはぬぬづひ〺〺ひづのつづひ〨〩 が呼ばれるときに、レイアウトにプッシュされるものです。
上記のコードに示されているように、たいていのレイアウトは次に挙げるメソッドを呼び出さなければなりません。 これらのメソッドは、主としてレンダリングの過程に関するイベントをトリガするもので、 他の場所で登録されたスクリプトやタグが、メソッドが呼ばれた場所に正しく注入されるようにするためのものです。
• ぢづでどのぐちでづ〨〩〺 このメソッドがレイアウトの冒頭で呼ばれなければなりません。 これは、ページの開始を示す ぅざぅぎごたあぅぇぉぎたぐぁぇぅ イベ
ントをトリガします。
• づのつぐちでづ〨〩〺 このメソッドがレイアウトの末尾で呼ばれなければなりません。 これは、ページの終了を示す ぅざぅぎごたぅぎいたぐぁぇぅ イベントを
トリガします。
• とづちつ〨〩〺 このメソッドが えごきが ページの <head> セクションの中で呼ばれなければなりません。 このメソッドは、ページのレンダリン
グが完了したときに、登録された とづちつ の えごきが コード 〨リンク・
タグ、メタ・タグなど〩 に置き換えられるプレースホルダを生成します。
• ぢづでどのあはつべ〨〩〺 このメソッドが <body> セクションの冒頭で呼ばれなければなりません。 このメソッドは ぅざぅぎごたあぅぇぉぎたあくいす イベントをトリガし、 ぢはつべ の開始位置をターゲットとする登録された えごきがコード 〨おちぶちこっひどばぴ など〩 によって置き換えられるプレースホルダを生成します。
• づのつあはつべ〨〩〺 このメソッドが <body〾 セクションの末尾で呼ばれるな
ければなりません。 このメソッドは ぅざぅぎごたぅぎいたあくいす イベントをトリガし、 ぢはつべ の終了位置をターゲットとする登録された えごきがコード 〨おちぶちこっひどばぴ など〩 によって置き換えられるプレースホルダを生成します。

レイアウトでデータにアクセスする
レイアウトの中では、事前定義された二つの変数、すなわち、$this と$content にアクセスすることが出来ます。 前者は、通常のビューにおいてと同じく、ビュー コンポーネントを参照します。 一方、後者は、コン
トローラの中で ひづのつづひ〨〩 メソッドを呼ぶことによってレンダリングされる、コンテント・ビューのレンダリング結果を含むものです。
レイアウトの中でその他のデータにアクセスする必要があるときは、
ビューの中でデータにアクセスする の項で説明されている「プル」の方法を使う必要があります。 コンテント・ビューからレイアウトにデータを渡す必要があるときは、ビューの間でデータを共有する の項で説明されている方法を使うことが出来ます。

〱〰〸ぃえぁぐごぅげ 〳〮 アプリケーションの構造

レイアウトを使う
コントローラでのレンダリング の項で説明されているように、 コン
トローラの中で ひづのつづひ〨〩 メソッドを呼んでビューをレンダリングす
ると、レンダリング結果にレイアウトが適用されます。 デフォルトでは、@app/views/layouts/main.php というレイアウトが使用されます。
べどどぜぢちびづぜぁばばぬどっちぴどはの〺〺〤ぬちべはふぴ または べどどぜぢちびづぜぃはのぴひはぬぬづひ〺〺〤ぬちべはふぴのどちらかを構成することによって、異なるレイアウトを使うことが出来ます。 前者は全てのコントローラによって使用されるレイアウトを決定するものですが、後者は個々のコントローラについて前者をオー
バーライドするものです。 例えば、次のコードは、post コントローラ
がビューをレンダリングするときに @app/views/layouts/post.php をレイアウトとして使うようにするものです。 その他のコントローラは、layout
プロパティに触れられていないと仮定すると、 引き続きデフォルトの@app/views/layouts/main.php をレイアウトとして使います。
namespace app\controllers;
use yii\web\Controller;class PostController extends Controller{
public $layout = 'post';}// ...

モジュールに属するコントローラについては、モジュールの ぬちべはふぴ プロ
パティを構成して、 モジュール内のコントローラに特定のレイアウトを使用することも出来ます。
layout プロパティは異なるレベル 〨コントローラ、モジュール、ア
プリケーション〩 で構成されうるものですので、 すどど は舞台裏で二つのステップを踏んで、特定のコントローラで実際に使われるレイアウト・
ファイルが何であるかを決定します。
最初のステップで、すどど はレイアウトの値とコンテキスト・モジュー
ルを決定します。
• コントローラの べどどぜぢちびづぜぃはのぴひはぬぬづひ〺〺〤ぬちべはふぴ プロパティが nullでないときは、それをレイアウトの値として使い、 コントローラのモジュール をコンテキスト・モジュールとして使う。
• ぬちべはふぴ が null のときは、コントローラの祖先となっている全てのモジュール 〨アプリケーション自体も含む〩 を探して、 ぬちべはふぴ プロ
パティが null でない最初のモジュールを見つける。 見つかったモ
ジュールとその ぬちべはふぴ の値をコンテキスト・モジュールと選ばれたレイアウトの値とする。 そのようなモジュールが見つからなかったときは、レイアウトは適用されないということを意味する。
第二のステップでは、最初のステップで決定されたレイアウトの値とコンテキスト・モジュールに従って、実際のレイアウト・ファイルを決定〳〮〷〮 ビュー〱〰〹します。 レイアウトの値は下記のいずれかであり得ます。
• パス・エイリアス 〨例えば、@app/views/layouts/main〩。
• 絶対パス 〨例えば、/main〩〺 すなわち、スラッシュで始まるレイアウ
トの値の場合。 実際のレイアウトファイルはアプリケーションのレイアウト・パス 〨デフォルトでは @app/views/layouts〩 の下で探される。
• 相対パス 〨例えば、main〩〺 実際のレイアウト・ファイルはコンテキスト・モジュールの レイアウト・パス 〨デフォルトでは モジュー
ル・ディレクトリ の下の views/layouts ディレクトリ〩 の下で探される。
• 真偽値 false〺 レイアウトは適用されない。
レイアウトの値がファイル拡張子を含んでいない場合は、デフォルト値である .php を使います。
入れ子のレイアウト
ときとして、あるレイアウトの中に別のレイアウトを入れたい場合があるでしょう。 例えば、ウェブ・サイトの別々のセクションにおいて、違うレイアウトを使いたいけれども、 それらのレイアウトは全て、全体としての えごきが〵 ページ構造を生成する同一の基本レイアウトを共有している、という場合です。 この目的を達することは、次のように、子レイ
アウトの中で ぢづでどのぃはのぴづのぴ〨〩 と づのつぃはのぴづのぴ〨〩 を呼ぶことで可能になります。
<?php $this->beginContent('@app/views/layouts/base.php'); ?>... 子レイアウトのコンテントをここに ...
<?php $this->endContent(); ?>上のコードが示すように、子レイアウトのコンテントは ぢづでどのぃはのぴづのぴ〨〩と づのつぃはのぴづのぴ〨〩 によって囲まれなければなりません。 ぢづでどのぃはのぴづのぴ〨〩に渡されるパラメータは、親レイアウトが何であるかを指定するものです。 レイアウトのファイルまたはエイリアスのどちらかを使うことが出来ます。
上記のアプローチを使って、〲レベル以上のレイアウトを入れ子にすることも出来ます。
ブロックを使うブロックを使うと、ある場所でビューコンテントを定義して、別の場所
でそれを表示することが可能になります。ブロックはたいていはレイア
ウトと一緒に使われます。 例えば、ブロックをコンテント・ビューで定義して、それをレイアウトで表示する、ということが出来ます。
ぢづでどのあぬはっに〨〩 と づのつあぬはっに〨〩 を呼んでブロックを定義します。 すると、そのブロックを $view->blocks[$blockID] によってアクセス出来るよう〱〱〰

ぃえぁぐごぅげ 〳〮 アプリケーションの構造になります。 ここで $blockID は、定義したときにブロックに割り当てた
ユニークな ぉい を指します。
次の例は、どのようにブロックを使えば、レイアウトの特定の部分をコンテント・ビューでカスタマイズすることが出来るかを示すものです。
最初に、コンテント・ビューで、一つまたは複数のブロックを定義します。
...
<?php $this->beginBlock('block1'); ?>... block1 のコンテント ...
<?php $this->endBlock(); ?>...
<?php $this->beginBlock('block3'); ?>... block3 のコンテント ...
<?php $this->endBlock(); ?>次に、レイアウト・ビューで、得ることが出来ればブロックをレンダリングし、 ブロックが定義されていないときは何らかのデフォルトのコン
テントを表示します。
...
<?php if (isset($this->blocks['block1'])): ?><? = $this->blocks['block1'] ?><?php else: ?>... block1 のデフォルトのコンテント ...
<?php endif; ?>...
<?php if (isset($this->blocks['block2'])): ?><? = $this->blocks['block2'] ?><?php else: ?>... block2 のデフォルトのコンテント ...
<?php endif; ?>...
<?php if (isset($this->blocks['block3'])): ?><? = $this->blocks['block3'] ?><?php else: ?>... block3 のデフォルトのコンテント ...
<?php endif; ?>...

〳〮〷〮 ビュー

3.7.4

〱〱〱

ビュー・コンポーネントを使う

ビュー・コンポーネント はビューに関連する多くの機能を提供します。
ビュー・コンポーネントは、べどどぜぢちびづぜざどづぷ またはその子クラスの個別のインスタンスを作成することによっても取得できますが、 たいていの場合は、view アプリケーション・コンポーネントを主として使うことになるでしょう。 このコンポーネントは アプリケーションの構成情報 の中で、次のようにして構成することが出来ます。
[// ...
'components' => ['view' => ['class' => 'app\components\View',],// ...
],]

ビュー・コンポーネントは、次に挙げるビュー関連の有用な機能を提供します。それぞれについては、独立のセクションで更に詳細に説明されます。
• テーマ〺 ウェブ・サイトのテーマを開発し変更することを可能にします。
• フラグメント・キャッシュ〺 ウェブ・ページの中の断片をキャッシュすることを可能にします。
• クライアント・スクリプトの取り扱い〺 ぃここ と おちぶちこっひどばぴ の登録とレンダリングをサポートします。
• アセット・バンドルの取り扱い〺 アセット・バンドル の登録とレンダリングをサポートします。
• 代替のテンプレート・エンジン〺 ごぷどで15 、こねちひぴべ16 など、 他のテン
プレート・エンジンを使用することを可能にします。
次に挙げるマイナーではあっても有用な諸機能は、ウェブ・ページを開発するときに頻繁に使用するでしょう。
ページタイトルを設定する
どんなウェブ・ページにもタイトルが無ければなりません。通常、タイ
トル・タグは ぬちべはふぴ の中で表示されます。 しかし、実際においては、多くの場合、タイトルはレイアウトではなくコンテント・ビューで決められます。 この問題を解決するために、べどどぜぷづぢぜざどづぷ は、タイトル情報をコンテント・ビューからレイアウトに渡すための ぴどぴぬづ プロパティを提供しています。
この機能を利用するためには、全てのコンテント・ビューにおいて、
次のようにタイトルを設定します。
15
16

https://twig.symfony.com/
https://www.smarty.net/

〱〱〲ぃえぁぐごぅげ 〳〮 アプリケーションの構造<?php$this->title = 'My page title';?>

そして、レイアウト・ビューで、<head> セクションに次のコードを忘れずに書くようにします。
<title><?= Html::encode($this->title) ?> </title>

メタ・タグを登録する
ウェブ・ページは、通常、いろいろな関係者によって必要とされるさま
ざまなメタ・タグを生成する必要があります。 ページ・タイトルと同じように、メタ・タグは <head> セクションに出現して、通常はレイアウトの中で生成されます。
どのようなメタ・タグを生成するかをコンテント・ビューの中で指定したい場合は、下記のように、 べどどぜぷづぢぜざどづぷ〺〺ひづでどびぴづひきづぴちごちで〨〩 をコ
ンテント・ビューで呼ぶことが出来ます。
<?php$this->registerMetaTag(['name' => 'keywords', 'content' => 'yii, framework,php']);?>

上記のコードは、ビュー・コンポーネントによって 【にづべぷはひつび】 メタ・タ
グを登録するものです。 登録されたメタ・タグは、レイアウトがレンダ
リングを完了した後でレンダリングされます。 すなわち、レイアウトの中で べどどぜぷづぢぜざどづぷ〺〺とづちつ〨〩 を呼び出した場所に、次の えごきが コードが生成されて挿入されます。
<meta name="keywords" content="yii, framework, php">

べどどぜぷづぢぜざどづぷ〺〺ひづでどびぴづひきづぴちごちで〨〩 を複数回呼び出した場合は、メタ・タグが同じものか否かに関係なく、 複数のメタ・タグが登録されることに注意してください。
ある型のメタ・タグのインスタンスが一つだけになることを保証したい場合は、このメソッドを呼ぶときに第二のパラメータとしてキーを指定することが出来ます。 例えば、次のコードでは、二つの 【つづびっひどばぴどはの】
メタ・タグを登録していますが、二番目のものだけがレンダリングされることになります。
$this->registerMetaTag(['name' => 'description', 'content' => '俺が Yii で作ったクールなウェブ・サイトだぜぃ!!'], 'description');$this->registerMetaTag(['name' => 'description', 'content' => '面白いアライ
グマに関するウェブ・サイトです。'], 'description');〳〮〷〮 ビュー〱〱〳

リンク・タグを登録する
メタ・タグ と同じように、リンク・タグも多くの場合において有用なものです。例えば、てちぶどっはの をカスタマイズしたり、げここ フィードを指し示したり、くばづのぉい を別のサーバに委任したり、等々。 リンク・タグ
も、べどどぜぷづぢぜざどづぷ〺〺ひづでどびぴづひがどのにごちで〨〩 を使って、メタ・タグと同じような方法で取り扱うことが出来ます。 例えば、コンテント・ビューにおいて、次のようにしてリンク・タグを登録することが出来ます。
$this->registerLinkTag(['title' => 'Yii ライブ・ニューズ','rel' => 'alternate','type' => 'application/rss+xml','href' => 'https://www.yiiframework.com/rss.xml/',]);

上記のコードは、次の結果になります。
<link title="Yii ライブ・ニューズ" rel="alternate"
type="application/rss+xml" href="https://www.yiiframework.com/rss.xml/">

ひづでどびぴづひきづぴちごちで〨〩 と 同 じ よ う に 、ひづでどびぴづひがどのにごちで〨〩 を 呼 ぶ と き にキーを指定すると、 同じリンク・タグを繰り返して生成するのを避けることが出来ます。

3.7.5

ビューのイベント

ビュー・コンポーネント はビューをレンダリングする過程においてい
くつかのイベントをトリガします。 これらのイベントに反応することによって、ビューにコンテントを注入したり、エンド・ユーザに送信される前にレンダリング結果を加工したりすることが出来ます。
• ぅざぅぎごたあぅうくげぅたげぅぎいぅげ〺 コントローラでファイルをレンダリングする前にトリガされます。 このイベントのハンドラは、べどどぜぢちびづ
ぜざどづぷぅぶづのぴ〺〺〤どびざちぬどつ を false にセットして、レンダリングのプロ
セスをキャンセルすることが出来ます。
• ぅざぅぎごたぁうごぅげたげぅぎいぅげ〺 ファイルのレンダリングの後、べどどぜぢちびづぜざどづぷ〺〺ちてぴづひげづのつづひ〨〩 を呼ぶことによってトリガされます。 このイ
ベントのハンドラは、レンダリング結果をプロパティ べどどぜぢちびづ
ぜざどづぷぅぶづのぴ〺〺〤はふぴばふぴ を通じて取得して、 それを修正してレンダ
リング結果を変更することが出来ます。
• ぅざぅぎごたあぅぇぉぎたぐぁぇぅ〺 レイアウトの中で べどどぜぢちびづぜざどづぷ〺〺ぢづでどのぐちでづ〨〩を呼ぶことによってトリガされます。
• ぅざぅぎごたぅぎいたぐぁぇぅ〺 レイアウトの中で べどどぜぢちびづぜざどづぷ〺〺づのつぐちでづ〨〩 を呼ぶことによってトリガされます。
• ぅざぅぎごたあぅぇぉぎたあくいす〺 レイアウトの中で べどどぜぷづぢぜざどづぷ〺〺ぢづでどのあはつべ〨〩を呼ぶことによってトリガされます。

〱〱〴

ぃえぁぐごぅげ 〳〮 アプリケーションの構造• ぅざぅぎごたぅぎいたあくいす〺 レイアウトの中で べどどぜぷづぢぜざどづぷ〺〺づのつあはつべ〨〩 を呼ぶことによってトリガされます。
例えば、次のコードはページの ぢはつべ の最後に現在の日付を注入するものです。
\Yii::$app->view->on(View::EVENT_END_BODY, function () {echo date('Y-m-d');
});

3.7.6

静的なページをレンダリングする

静的なページというのは、主たるコンテントのほとんどが静的なもの
で、 コントローラからプッシュされる動的なデータにアクセスする必要がないページを指します。
静的なページは、そのコードをビューに置き、そして、コントローラ
で次のようなコードを使うと表示することが出来ます。
public function actionAbout(){
return $this->render('about');}

ウェブ・サイトが多くの静的なページを含んでいる場合、同じようなコードを何度も繰り返すのは非常に面倒くさいでしょう。 この問題を解決するために、べどどぜぷづぢぜざどづぷぁっぴどはの という スタンドアロン・アクションをコントローラに導入することが出来ます。 例えば、
namespace app\controllers;
use yii\web\Controller;class SiteController extends Controller{
public function actions(){
return ['page' => ['class' => 'yii\web\ViewAction',
],
];
}
}

このようにすると、ディレクトリ @app/views/site/pages の下に about という名前のビューを作成したときに、 次の さげが によってこのビューを表示することが出来るようになります。
http://localhost/index.php?r=site%2Fpage&view=about〳〮〸〮 モジュール〱〱〵

view という GET パラメータが、どのビューがリクエストされているか を べどどぜぷづぢぜざどづぷぁっぴどはの に 教 え ま す 。 そ こ で 、 ア ク シ ョ ン は こ のビューをディレクトリ @app/views/site/pages の下で探します。 べどどぜぷづぢ
ぜざどづぷぁっぴどはの〺〺〤ぶどづぷぐひづてどへ を構成して、ビューを探すディレクトリを変更することが出来ます。

3.7.7

ベスト・プラクティス

ビューはエンド・ユーザが望む形式でモデルを表現することに対して責任を持ちます。一般的に、ビューは• 主として表示目的のコードを含むべきです。例えば、えごきが、または、データをたどって書式化してレンダリングする簡単な ぐえぐ
コードなど。
• いあ クエリを実行するコードは含むべきではありません。そのようなコードはモデルの中で実行されるべきです。
• $_GET や $_POST のようなリクエスト・データに直接アクセスするべきではありません。それはコントローラの仕事です。 リクエスト・
データが必要な場合は、コントローラからビューにプッシュされるべきです。
• モデルのプロパティを読み出すことが出来ます。しかし、それを修正するべきではありません。
ビューを管理しやすいものにするために、複雑すぎるビューや、冗長なコードをあまりに多く含むビューを作ることは避けましょう。 この目的を達するために、次のテクニックを使うことが出来ます。
• 共通の表示セクション 〨ページのヘッダやフッタなど〩 を表すために
レイアウト を使う。
• 複雑なビューはいくつかの小さなビューに分割する。既に説明した
レンダリングのメソッドを使えば、 小さなビューをレンダリングして大きなビューを組み上げることが出来る。
• ビューの構成要素として ウィジェット を使う。
• ビューでデータを変換し書式化するためのヘルパ・クラスを作成し
て使う。

3.8

モジュール

モジュールは、モデル、ビュー、コントローラ、およびその他の支援コ
ンポーネントから構成される自己充足的なソフトウェアのユニットです。 モジュールが アプリケーション にインストールされている場合、エンド・ユーザはモジュールのコントローラにアクセスする事が出来ます。 これらのことを理由として、モジュールは小さなアプリケーションと見なされることがよくあります。 しかし、モジュールは単独では配備できず、アプリケーションの中に存在しなければならないという点で ア
プリケーション とは異なります。

〱〱〶

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

3.8.1

モジュールを作成する

モジュールは、モジュールの ベース・パス と呼ばれるディレクトリとして編成されます。 このディレクトリの中に、ちょうどアプリケーションの場合と同じように、controllers、models、views のようなサブ・ディレク
トリが存在して、コントローラ、モデル、ビュー、その他のコードを収納しています。 次の例は、モジュール内の中身を示すものです。
forum/
Module.php
controllers/
DefaultController.php
models/views/
含む
layouts/
default/含む
index.php

モジュール・クラス・ファイル
コントローラ・クラス・ファイルを含む
デフォルトのコントローラ・クラス・ファイル
モデル・クラス・ファイルを含む
コントローラのビューとレイアウトのファイルをレイアウトのビュー・ファイルを含む
DefaultController のためのビュー・ファイルをindex ビュー・ファイル

モジュール・クラス
全てのモジュールは べどどぜぢちびづぜきはつふぬづ から拡張したユニークなモジュー
ル・クラスを持たなければなりません。 モジュール・クラスは、モジュールの ベース・パス 直下に配置されて オートロード可能 になっていなければなりません。 モジュールがアクセスされたとき、対応するモジュール・クラスの単一のインスタンスが作成されます。 アプリケー
ションのインスタンス と同じように、モジュールのインスタンスは、 モ
ジュール内のコードがデータとコンポーネントを共有するために使用されます。
次のコードは、モジュール・クラスがどのようなものかを示す例です。
namespace app\modules\forum;class Module extends \yii\base\Module{
public function init(){
parent::init();}}$this->params['foo'] = 'bar';// ... 他の初期化コード ...

init メソッドがモジュールのプロパティを初期化するためのコードをた

くさん含む場合は、 それを 構成情報 の形で保存し、init() の中で次のコードを使って読み出すことも可能です。

〳〮〸〮 モジュール〱〱〷

public function init(){
parent::init();// config.php からロードした構成情報でモジュールを初期化する\Yii::configure($this, require __DIR__ . '/config.php');}

ここで、構成情報ファイル config.php は、アプリケーションの構成情報の場合と同じように、 次のような内容を含むことが出来ます。
<?php
return ['components' => [// コンポーネントの構成情報のリスト],'params' => [// パラメータのリスト],];

モジュール内のコントローラ
モジュールの中でコントローラを作成するときは、コントローラ・クラ
スをモジュール・クラスの名前空間の controllers サブ名前空間に置くことが規約です。 このことは、同時に、コントローラのクラス・ファイルをモジュールの ベース・パス 内の controllers ディレクトリに置くべきことをも意味します。 例えば、前の項で示された forum モジュールの中で post コントローラを作成するためには、 次のようにしてコントローラを宣言しなければなりません。
namespace app\modules\forum\controllers;
use yii\web\Controller;class PostController extends Controller{// ...
}

コントローラ・クラスの名前空間は、べどどぜぢちびづぜきはつふぬづ〺〺〤っはのぴひはぬぬづひぎちねづびばちっづ
プロパティを構成してカスタマイズすることが出来ます。 いくつかのコントローラがこの名前空間の外にある場合でも、べどどぜぢちびづぜきはつふぬづ〺〺〤っはのぴひはぬぬづひきちば プロパティを構成することによって、それらをアクセス可能にすることが出来ます。 これは、アプリケーションでのコントロー
ラ・マップ の場合と同様です。
モジュール内のビュー
モジュール内のビューは、モジュールの ベース・パス 内の views ディ
レクトリに置かれなくてはなりません。 モジュール内のコントローラに〱〱〸

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

よってレンダリングされるビューは、ディレクトリ views/ControllerID の下に置きます。 ここで、ControllerID は コントローラ ぉい を指します。
例えば、コントローラ・クラスが PostController である場合、ディレクト
リはモジュールの ベース・パス の中の views/post となります。
モジュールは、そのモジュールのコントローラによってレンダリングされるビューに適用される レイアウト を指定することが出来ます。 レイ
アウトは、デフォルトでは views/layouts ディレクトリに置かれなければならず、また、 べどどぜぢちびづぜきはつふぬづ〺〺〤ぬちべはふぴ プロパティがレイアウトの名前を指すように構成しなければなりません。 layout プロパティを構成しない場合は、アプリケーションのレイアウトが代りに使用されます。
モジュール内のコンソールコマンド
コンソール モードで使用する事が出来るコマンドをモジュール内で宣言することも可能です。
あなたのコマンドがコマンド・ライン・ユーティリティから見えるよ
うにするためには、すどど がコンソール・モードで実行されたときに べどど
ぜぢちびづぜきはつふぬづ〺〺〤っはのぴひはぬぬづひぎちねづびばちっづ を変更して、コマンドの名前空間を指し示すようにする必要があります。
それを達成する一つの方法は、モジュールの init() メソッドの中ですどど アプリケーションのインスタンスの型を調べるという方法です。
public function init(){
parent::init();if (Yii::$app instanceof \yii\console\Application) {$this->controllerNamespace = 'app\modules\forum\commands';}}

このようにすれば、コマンドラインから次のルートを使ってあなたのコ
マンドを使用する事が出来るようになります。
yii <module_id>/<command>/<sub_command>

3.8.2

モジュールを使う

アプリケーションの中でモジュールを使うためには、アプリケーションの ねはつふぬづび プロパティのリストにそのモジュールを載せてアプリケー
ションを構成するだけで大丈夫です。 アプリケーションの構成情報 の中の次のコードは、forum モジュールを使うようにするものです。
['modules' => ['forum' => ['class' => 'app\modules\forum\Module',// ... モジュールのその他の構成情報 ...
],〳〮〸〮 モジュール

]

〱〱〹

],

情 報〺 モ ジ ュ ー ル 内 の コ マ ン ド を 使 用 す る た め に は 、 モ
ジュールを コンソール・アプリケーション設定 にも含める必要があります。
ねはつふぬづび プロパティは、モジュールの構成情報の配列を取ります。 各配
列のキーは、アプリケーションの全てのモジュールの中でそのモジュールを特定するためのユニークな モジュール ID を表します。 そして、対応する配列の値は、そのモジュールを作成するための 構成情報 です。
ルート
アプリ ケーション の中のコン トローラを アクセスす るのと同じように、ルート がモジュールの中のコントローラを指し示すために使われます。 モジュール内のコントローラのルートは、モジュール ぉい で始まり、コントローラ ぉい、 アクション ぉい と続くものでなければなりません。 例えば、アプリケーションが forum という名前のモジュールを使用
している場合、forum/post/index というルートは、 forum モジュール内のpost コントローラの index アクションを表します。 ルートがモジュール
ぉい だけを含む場合は、べどどぜぢちびづぜきはつふぬづ〺〺〤つづてちふぬぴげはふぴづ プロパティ 〨デ
フォルト値は default です〩 が、どのコントローラ・アクションが使用されるべきかを決定します。 これは、forum というルートは forum モジュール内の default コントローラを表すという意味です。
モジュールのための さげが マネージャの規則は べどどぜぷづぢぜさひぬきちのちでづひ〺〺ばちひびづげづぱふづびぴ〨〩 が起動される前に追加されなくてはなりません。 す
なわち、モジュールの init() の中で規則を追加しても動作しない、ということです。なぜなら、モジュールの初期化はルートの処理が済んだ後になるからです。 従って、さげが 規則は ブートストラップ段階 で追加される必要があります。 また、モジュールの さげが 規則を べどどぜぷづぢ
ぜぇひはふばさひぬげふぬづ に入れるのも良い方法です。
モジュールが バージョン管理された ぁぐぉ で使用される場合は、そのさげが 規則はアプリケーション構成情報の urlManager のセクションに直接に追加されなければなりません。
モジュールにアクセスするモジュール内において、モジュール ぉい や、モジュールのパラメータ、モジュールのコンポーネントなどにアクセスするために、モジュール・ク
ラス のインスタンスを取得する必要があることがよくあります。 次の文を使ってそうすることが出来ます。
$module = MyModuleClass::getInstance();〱〲〰

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

ここで MyModuleClass は、当該モジュール・クラスの名前を指すものです。 getInstance() メソッドは、現在リクエストされているモジュール・クラスのインスタンスを返します。 モジュールがリクエストされていな
い場合は、このメソッドは null を返します。モジュール・クラスの新しいインスタンスを手動で作成しようとしてはいけないことに注意してください。 手動で作成したインスタンスは、リクエストに対するレスポン
スとして すどど によって作成されたインスタンスとは別のものになります。
情報〺 モジュールを開発するとき、モジュールが固定の ぉい を使うと仮定してはいけません。 なぜなら、モジュールは、ア
プリケーションや他のモジュールの中で使うときに、任意のぉい と結び付けることが出来るからです。 モジュール ぉい を取得するためには、上記の方法を使って最初にモジュールのイ
ンスタンスを取得し、 そして $module->id によって ぉい を取得しなければなりません。
モジュールのインスタンスにアクセスするためには、次の二つの方法を使うことも出来ます。
// ID が "forum" である子モジュールを取得する$module = \Yii::$app->getModule('forum');// 現在リクエストされているコントローラが属するモジュールを取得する$module = \Yii::$app->controller->module;

最初の方法は、モジュール ぉい を知っている時しか役に立ちません。一方、第二の方法は、 リクエストされているコントローラについて知っている場合に使うのに最適な方法です。
いったんモジュールのインスタンスをとらえれば、モジュールに登録されたパラメータやコンポーネントにアクセスすることが可能になります。例えば、$maxPostCount = $module->params['maxPostCount'];

モジュールをブートストラップする
いくつかのモジュールは、全てのリクエストで毎回走らせる必要があります。べどどぜつづぢふでぜきはつふぬづ・モジュールがその一例です。 そうするためには、そのようなモジュールをアプリケーションの ぢははぴびぴひちば プロパティのリストに挙げます。
例えば、次のアプリケーションの構成情報は、debug モジュールが常にロードされることを保証するものです。
['bootstrap' => ['debug',],〳〮〸〮 モジュール]〱〲〱'modules' => ['debug' => 'yii\debug\Module',
],

3.8.3

入れ子のモジュールモジュールはレベルの制限無く入れ子にすることが出来ます。つまり、
モジュールは別のモジュールを含むことが出来、その含まれたモジュー
ルもさらに別のモジュールを含むことが出来ます。 含む側を 親モジュー
ル、含まれる側を 子モジュール と呼びます。 子モジュールは、親モ
ジュールの ねはつふぬづび プロパティの中で宣言されなければなりません。例
えば、
namespace app\modules\forum;class Module extends \yii\base\Module{
public function init(){
parent::init();}$this->modules = ['admin' => [// ここはもっと短い名前空間の使用を考慮すべきです'class' => 'app\modules\forum\modules\admin\Module',
],
];

}

入れ子にされたモジュールの中にあるコントローラのルートは、全ての祖先のモジュールの ぉい を含まなければなりません。 例えば、forum/admin/dashboard/indexというルートは、forum モジュールの子モジュールである admin モジュー
ルの dashboard コントローラの index アクションを表します。
情報〺 でづぴきはつふぬづ〨〩 メソッドは、親モジュールに直接属す
る子モジュールだけを返します。 べどどぜぢちびづぜぁばばぬどっちぴどはの〺〺〤ぬはちつづつきはつふぬづび プロパティがロードされた全てのモジュールのリストを保持しています。 このリストには、直接の子と孫以下の両方のモジュールが含まれ、クラス名によってインデックスされています。

3.8.4

モジュール内からコンポーネントにアクセスする

バージョン 〲〮〰〮〱〳 以降、モジュールは ツリー走査 をサポートしていま す 。 こ れ に よ っ て 、 モ ジ ュ ー ル の 開 発 者 は〨ア プ リ ケ ー シ ョ ン〩コ
ンポーネントを参照するのに、 サービス・ロケータとして自身のモ〱〲〲ぃえぁぐごぅげ 〳〮 アプリケーションの構造

ジュールを使うことが出来るようになりました。 これが意味すること
は、Yii::$app->get('db') よりも $module->get('db') を使う方が良い、ということです。 モジュールのユーザは、異なるコンポーネント〨構成〩が要求される場合は、モジュールで使用する特定のコンポーネントを指定することが出来ます。
例えば、次のような部分的なアプリケーション構成が可能です。
'components' => ['db' => ['tablePrefix' => 'main_','class' => Connection::class,'enableQueryCache' => false],],'modules' => ['mymodule' => ['components' => ['db' => ['tablePrefix' => 'module_','class' => Connection::class
],
],
],
],

アプリケーションのデータベース・テーブルは main_ という接頭辞を持つ
一方で、モジュールのデータベース・テーブルは module_ という接頭辞を持ちます。 上記の構成はマージされないということに注意して下さい。
例えば、モジュールのコンポーネントではクエリ・キャッシュはデフォ
ルト値に従って有効なままになります。

3.8.5

ベスト・プラクティス

モジュールは、それぞれ密接に関係する一連の機能を含む数個のグループに分割できるような、 規模の大きなアプリケーションに最も適しています。 そのような機能グループをそれぞれモジュールとして、特定の個人やチームによって開発することが出来ます。
モジュールは、また、機能グループ・レベルでコードを再利用するための良い方法でもあります。 ある種のよく使われる機能、例えばユーザ
管理やコメント管理などは、全て、将来のプロジェクトで容易に再利用できるように、 モジュールの形式で開発することが出来ます。

3.9

フィルタ

フィルタは、コントローラ・アクション の前 および〯または 後に走る
オブジェクトです。 例えば、アクセス・コントロール・フィルタはアクションの前に走って、アクションが特定のエンド・ユーザだけにアクセ〳〮〹〮 フィルタ〱〲〳スを許可するものであることを保証します。 また、コンテント圧縮フィ
ルタはアクションの後に走って、レスポンスのコンテントをエンド・ユーザに送出する前に圧縮します。
一つのフィルタは、前フィルタ 〨アクションの 前 に適用されるフィル
タのロジック〩 および〯または 後フィルタ 〨アクションの 後 に適用されるロジック〩 から構成することが出来ます。

3.9.1

フィルタを使用するフィルタは、本質的には特別な種類の ビヘイビア です。 したがって、フィルタを使うことは ビヘイビアを使う ことと同じです。 下記のように、ぢづとちぶどはひび〨〩 メソッドをオーバーライドすることによって、コント
ローラの中でフィルタを宣言することが出来ます。
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');
},
],
];
}

デフォルトでは、コントローラ・クラスの中で宣言されたフィルタは、そのコントローラの 全て のアクションに適用されます。 しかし、はのぬべ
プロパティを構成することによって、 フィルタがどのアクションに適用されるべきかを明示的に指定することも出来ます。 上記の例では、
HttpCache フィルタは、index と view のアクションに対してのみ適用されています。 また、づへっづばぴ プロパティを構成して、いくつかのアクションをフィルタされないように除外することも可能です。
コントローラのほかに、モジュール または アプリケーション でもフィルタを宣言することが出来ます。 そのようにした場合、はのぬべ とづへっづばぴ のプロパティを上で説明したように構成しない限り、 そのフィル
タは、モジュールまたはアプリケーションに属する 全て のコントロー
ラ・アクションに適用されます。
補足〺 モジュールやアプリケーションでフィルタを宣言する
場合、はのぬべ と づへっづばぴ のプロパティでは、 アクション ぉい ではなく、ルート を使わなければなりません。 なぜなら、モジュールやアプリケーションのスコープでは、アクション ぉい
だけでは完全にアクションを指定することが出来ないからで
す。

〱〲〴

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

一つのアクションに複数のフィルタが構成されている場合、フィルタは下記で説明されている規則に従って適用されます。
• 前フィルタ〕 アプリケーションで宣言されたフィルタを behaviors() にリス
トされた順に適用する。
〕 モジュールで宣言されたフィルタを behaviors() にリストされた順に適用する。
〕 コントローラで宣言されたフィルタを behaviors() にリストされた順に適用する。
〕 フィルタのどれかがアクションをキャンセルすると、 そのフィルタの後のフィルタ 〨前フィルタと後フィルタの両方〩 は適用されない。
• 前フィルタを通過したら、アクションを走らせる。
• 後フィルタ〕 コントローラで宣言されたフィルタを behaviors() にリストされた逆順で適用する。
〕 モジュールで宣言されたフィルタを behaviors() にリストされた逆順で適用する。
〕 アプリケーションで宣言されたフィルタを behaviors() にリストされた逆順で適用する。

3.9.2

フィルタを作成する

新しいアクション・フィルタを作成するためには、べどどぜぢちびづぜぁっぴどはのうどぬぴづひを拡張して、 ぢづてはひづぁっぴどはの〨〩 および〯または ちてぴづひぁっぴどはの〨〩 メソッドを
オーバーライドします。 前者はアクションが走る前に実行され、後者は走った後に実行されます。 ぢづてはひづぁっぴどはの〨〩 の返り値が、アクションが実行されるべきか否かを決定します。 返り値が 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->uniqueId}' は $time 秒を消費。");
return parent::afterAction($action, $result);
}

3.9.3

コアのフィルタ

すどど はよく使われる一連のフィルタを提供しており、それらは、主として
yii\filters 名前空間の下にあります。 以下では、それらのフィルタを簡単に紹介します。
ぁっっづびびぃはのぴひはぬ
ぁっっづびびぃはのぴひはぬ は、一組の 規則 に基づいて、シンプルなアクセス・コン
トロールを提供するものです。 具体的に言うと、アクションが実行される前に、ぁっっづびびぃはのぴひはぬ はリストされた規則を調べて、 現在のコンテキス
ト変数 〨例えば、ユーザの ぉぐ アドレスや、ユーザのログイン状態など〩に最初に合致するものを見つけます。 そして、合致した規則によって、リクエストされたアクションの実行を許可するか拒否するかを決定します。 合致する規則がなかった場合は、アクセスは拒否されます。
次の例は、認証されたユーザに対しては create と update のアクショ
ンへのアクセスを許可し、 その他のすべてのユーザにはこれら二つのアクションに対するアクセスを拒否する仕方を示すものです。
use yii\filters\AccessControl;
public function behaviors(){
return ['access' => ['class' => AccessControl::class,'only' => ['create', 'update'],'rules' => [// 認証されたユーザに許可する['allow' => true,'roles' => ['@'],],// その他はすべてデフォルトにより拒否される
],
],
];
}

アクセス・コントロール一般についての詳細は 権限 のセクションを参照
してください。

〱〲〶

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

認証メソッド・フィルタ
認証メソッド・フィルタは、えごごぐ あちびどっ 認証17 、 くぁふぴと 〲18 など、様々なメソッドを使ってユーザを認証するために使われるものです。 これらのフィルタ・クラスはすべて yii\filters\auth 名前空間の下にあります。
次 の 例 は 、べどどぜてどぬぴづひびぜちふぴとぜえぴぴばあちびどっぁふぴと の 使 い 方 を 示 す も ので、えごごぐ あちびどっ 認証に基づくアクセス・トークンを使ってユーザを認証しています。 これを動作させるためには、あなたの ユーザ・アイデ
ンティティ・クラス が てどのつぉつづのぴどぴべあべぁっっづびびごはにづの〨〩 メソッドを実装していなければならないことに注意してください。
use yii\filters\auth\HttpBasicAuth;public function behaviors(){
return ['basicAuth' => ['class' => HttpBasicAuth::class,],];}

認証メソッド・フィルタは げぅこごてふぬ ぁぐぉ を実装するときに使われるのが通例です。 詳細については、げぅこごてふぬ の 認証 のセクションを参照してください。
ぃはのぴづのぴぎづではぴどちぴはひ
ぃはのぴづのぴぎづではぴどちぴはひ は、レスポンス形式のネゴシエーションとアプリケー
ション言語のネゴシエーションをサポートします。 このフィルタは GET
パラメータと Accept えごごぐ ヘッダを調べることによって、レスポンス形
式 および〯または 言語を決定しようとします。
次の例では、ぃはのぴづのぴぎづではぴどちぴはひ はレスポンス形式として おこくぎ とじきが をサポートし、 〨合衆国の〩英語とドイツ語を言語としてサポートするように構成されています。
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,1718

https://ja.wikipedia.org/wiki/Basic%E8%AA%8D%E8%A8%BC
https://oauth.net/2/〳〮〹〮 フィルタ

}

];

],

〱〲〷

],
'languages' => ['en-US','de',],

レスポンス形式と言語は アプリケーションのライフサイクル のもっと早い段階で決定される必要があることがよくあります。 このた
め、ぃはのぴづのぴぎづではぴどちぴはひ はフィルタの他に、ブートストラップ・コンポー
ネント としても使うことができるように設計されています。 例えば、次のように、ぃはのぴづのぴぎづではぴどちぴはひ を アプリケーションの構成情報 の中で構成することが出来ます。
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',
],
],
],

情報〺 望ましいコンテント・タイプと言語がリクエストから決定できない場合は、 てはひねちぴび および ぬちのでふちでづび に挙げられている最初の形式と言語が使用されます。
えぴぴばぃちっとづ
えぴぴばぃちっとづ は Last-Modified および Etag の えごごぐ ヘッダを利用して、クライアント・サイドのキャッシュを実装するものです。 例えば、
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');},

えぴぴばぃちっとづ に関する詳細は えごごぐ キャッシュ のセクションを参照してください。
ぐちでづぃちっとづ
ぐちでづぃちっとづ はサーバ・サイドにおけるページ全体のキャッシュを実装するものです。 次の例では、ぐちでづぃちっとづ が index アクションに適用されて、最大 〶〰 秒間、または、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,
]
],
];
}

ぐちでづぃちっとづ の使用に関する詳細は ページ・キャッシュ のセクションを参照してください。
げちぴづがどねどぴづひ
げちぴづがどねどぴづひ は リーキー・バケット・アルゴリズム19 に基づいてレート
制限のアルゴリズムを実装するものです。 主として げぅこごてふぬ ぁぐぉ を実装
19
https://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〳〮〹〮 フィルタ〱〲〹

するときに使用されます。 このフィルタの使用に関する詳細は レート制
限 のセクションを参照してください。
ざづひぢうどぬぴづひ
ざづひぢうどぬぴづひ は、えごごぐ リクエスト・メソッド 〨えごごぐ 動詞〩 がリクエスト
されたアクションによって許可されているかどうかをチェックするものです。 許可されていない場合は、えごごぐ 〴〰〵 例外を投げます。 次の例では、ざづひぢうどぬぴづひ が宣言されて、ぃげさい アクションに対して許可されるメ
ソッドの典型的なセットを指定しています。
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'],
],
],
];
}

ぃはひび
クロス・オリジン・リソース共有 ぃくげこ20 とは、ウェブ・ページにおいて、さまざまなリソース 〨例えば、フォントや おちぶちこっひどばぴ など〩 を、それを生成するドメイン以外のドメインからリクエストすることを可能にするメカニズムです。 特に言えば、おちぶちこっひどばぴ の ぁおぁじ 呼出しが使用することが出来る じきがえぴぴばげづぱふづびぴ メカニズムです。 このような「クロス・ドメイン｣のリクエストは、このメカニズムに拠らなければ、 同一生成元のセキュリティ・ポリシーによって、ウェブ・ブラウザから禁止されるはずのものです。 ぃくげこ は、ブラウザとサーバが交信して、クロス・ド
メインのリクエストを許可するか否かを決定する方法を定義するものです。
ぃはひび フィルタ は、ぃくげこ ヘッダが常に送信されることを保証するた
めに、 ぁふぴとづのぴどっちぴどはの 〯 ぁふぴとはひどぺちぴどはの のフィルタよりも前に定義されなければなりません。
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
20

https://developer.mozilla.org/ja/docs/Web/HTTP/CORS〱〳〰

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

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

あなたの ぁぐぉ の べどどぜひづびぴぜぁっぴどぶづぃはのぴひはぬぬづひ クラスに ぃくげこ フィルタを追加したい場合は、 げぅこご コントローラ のセクションも参照して下さい。
ぃはひび のフィルタリングは 〤っはひび プロパティを使ってチューニングすることが出来ます。
• 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 のメソッドによる ぃくげこ を許可するものです。
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());}

〳〮〱〰〮 ウィジェット

〱〳〱

デフォルトのパラメータをアクション単位でオーバーライドして ぃくげこ
ヘッダをチューニングすることも可能です。 例えば、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());}

3.10

ウィジェットウィジェットは、ビュー で使用される再利用可能な構成ブロックで、複雑かつ構成可能なユーザ・インタフェイス要素をオブジェクト指向の流儀で作成するためのものです。 例えば、日付選択ウィジェットを使うと、入力として日付を選択することを可能にする素敵なデイト・ピッ
カーを生成することが出来ます。 このとき、あなたがしなければならな
いことは、次のようなコードをビューに挿入することだけです〺<?php
use yii\jui\DatePicker;?><? = DatePicker::widget(['name' => 'date']) ?>数多くのウィジェットが すどど にバンドルされています。 例えば、アクティブ・フォーム や、メニュー、なけふづひべ さぉ ウィジェット21 、ごぷどぴぴづひ
あははぴびぴひちば ウィジェット22 などです。 下記では、ウィジェットに関する基本的な知識の手引きをします。 特定のウィジェットの使い方について学ぶ必要がある場合は、クラス ぁぐぉ ドキュメントを参照してください。
21
22

https://www.yiiframework.com/extension/yiisoft/yii2-juihttps://www.yiiframework.com/extension/yiisoft/yii2-bootstrap〱〳〲

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

3.10.1

ウィジェットを使う

ウィジェットは主として ビュー で使われます。 べどどぜぢちびづぜしどつでづぴ〺〺
ぷどつでづぴ〨〩 メソッドを呼んで、ビューでウィジェットを使います。 このメソッドは、ウィジェットを初期化するための 構成情報 配列を受け取り、ウィジェットのレンダリング結果を返します。 例えば、下記のコードは、日本語を使い、入力を $model の from_date 属性に保存するように構成された日付選択ウィジェットを挿入するものです。
<?php
use yii\jui\DatePicker;?><? = DatePicker::widget(['model' => $model,'attribute' => 'from_date','language' => 'ja','dateFormat' => 'php:Y-m-d',]) ?>ウィジェットの中には、コンテントのブロックを受け取ることが出来るものもあります。 その場合、コンテントのブロックは べどどぜぢちびづぜしどつでづぴ〺〺ぢづでどの〨〩 と べどどぜぢちびづぜしどつでづぴ〺〺づのつ〨〩 の呼び出しで囲むようにしなけ
ればなりません。 例えば、次のコードは べどどぜぷどつでづぴびぜぁっぴどぶづうはひね ウィジェットを使ってログイン・フォームを生成するものです。 このウィジェットは、begin() と end() が呼ばれる場所で、それぞれ、開始と終了の <form> タグを生成します。 その間に置かれたものは全てそのままレンダリングされます。
<?php
use yii\widgets\ActiveForm;use yii\helpers\Html;?><?php $form = ActiveForm::begin(['id' => 'login-form']); ?><? = $form->field($model, 'username') ?><? = $form->field($model, 'password')->passwordInput() ?><div class="form-group"><? = Html::submitButton('ログイン') ?></div><?php ActiveForm::end(); ?>べどどぜぢちびづぜしどつでづぴ〺〺ぷどつでづぴ〨〩 がウィジェットのレンダリング結果を返すのとは違って、べどどぜぢちびづぜしどつでづぴ〺〺ぢづでどの〨〩 メソッドがウィジェットのイ
ンスタンスを返すことに注意してください。 返されたウィジェットのイ
ンスタンスを使って、ウィジェットのコンテントを構築することが出来ます。

〳〮〱〰〮 ウィジェット

〱〳〳補足〺 いくつかのウィジェットは、べどどぜぢちびづぜしどつでづぴ〺〺づのつ〨〩が呼ばれるときに囲んだコンテンツを調整するため、 出力
バッファリング23 を使用します。 この理由から、べどどぜぢちびづ
ぜしどつでづぴ〺〺ぢづでどの〨〩 と べどどぜぢちびづぜしどつでづぴ〺〺づのつ〨〩 の呼び出しは、同じビュー・ファイルの中で発生するものと想定されています。 この規則に従わない場合は、予期しない出力結果が生じ得ます。
グローバルなデフォルトを構成するあるタイプのウィジェットのグローバルなデフォルトを いぉ コンテナによって構成することが出来ます。
\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]);

詳細については 依存注入コンテナのガイドの 【実際の使いかた】 のセク
ション を参照してください。

3.10.2

ウィジェットを作成する

ウィジェットは必要に従って二つの異なる方法で作成することが出来ます。
〱〺 メソッドを利用する
ウィジェットを作成するためには、べどどぜぢちびづぜしどつでづぴ を拡張して、べどど
ぜぢちびづぜしどつでづぴ〺〺どのどぴ〨〩 および〯または べどどぜぢちびづぜしどつでづぴ〺〺ひふの〨〩 メソッ
ドをオーバーライドします。 通常、init() メソッドはウィジェットのプロパティを初期化するコードを含むべきものであり、run() メソッド
はウィジェットのレンダリング結果を生成するコードを含むべきものです。 レンダリング結果は、直接に 【づっとは】 しても、run() の返り値として文字列として返しても構いません。
次の例では、HelloWidget が message プロパティとして割り当てられた
コンテントを えごきが エンコードして表示します。 プロパティがセットされていない場合は、デフォルトとして 【えづぬぬは しはひぬつ】 を表示します。
namespace app\components;
use yii\base\Widget;
use yii\helpers\Html;
class HelloWidget extends Widget{
public $message;
public function init()
23

https://www.php.net/manual/ja/book.outcontrol.php〱〳〴

ぃえぁぐごぅげ 〳〮 アプリケーションの構造{}}

parent::init();if ($this->message === null) {$this->message = 'Hello World';}

public function run(){
return Html::encode($this->message);}

このウィジェットを使うために必要なことは、次のコードをビューに挿入するだけのことです。
<?php
use app\components\HelloWidget;?><? = HelloWidget::widget(['message' => 'おはよう']) ?>ウィジェットが大きなかたまりのコンテントをレンダーする必要がある
場合もあります。 コンテントを run() の中に埋め込むことも出来ます
が、もっと良い方法は、コンテントを ぶどづぷ に置き、 べどどぜぢちびづぜしどつでづぴ〺〺
ひづのつづひ〨〩 を呼んでレンダーする方法です。例えば、
public function run(){
return $this->render('hello');}〲〺 と のメソッドを利用する
これは上記のものと少し異なるだけのものです。 下記は HelloWidget の変種で、begin() と end() の間に包まれたコンテントを受け取り、 それをえごきが エンコードして表示するものです。
namespace app\components;
use yii\base\Widget;
use yii\helpers\Html;
class HelloWidget extends Widget{
public function init(){
parent::init();ob_start();}public function run()〳〮〱〰〮 ウィジェット
{

}

}

〱〳〵

$content = ob_get_clean();return Html::encode($content);

ご覧のように、init() の中で ぐえぐ の出力バッファが開始され、init() とrun() の呼び出しの間の全ての出力がキャプチャされ、 run() の中で処理されて返されます。
情報〺 べどどぜぢちびづぜしどつでづぴ〺〺ぢづでどの〨〩 を呼ぶと、ウィジェット
の新しいインスタンスが作成され、 ウィジェットのコンス
トラクタの最後で init() メソッドが呼ばれます。 べどどぜぢちびづ
ぜしどつでづぴ〺〺づのつ〨〩 を呼ぶと、run() メソッドが呼ばれて、その返り値が end() によって づっとは されます。
次のコードは、この HelloWidget の新しい変種をどのように使うかを示す
ものです〺
<?php
use app\components\HelloWidget;?><?php HelloWidget::begin(); ?>一つまたはそれ以上の <strong>HTML</strong> <pre>タグ</pre> を含みうるサン
プル・コンテント
このコンテントが大きくなりすぎる場合は、サブ・ビューを使います。
例えば、<?php echo $this->render('viewfile'); // 注意: この render() メソッドは\yii\base\View クラスのもの。コードのこの部分はビュー・ファイルの中にあり、Widget クラス・ファイルの中にはない ?><?php HelloWidget::end(); ?>デフォルトでは、ウィジェット用のビューは WidgetPath/views ディレ
クトリの中のファイルに保存すべきものです。 ここで WidgetPath は
ウィジ ェットのク ラス・ファ イルを含むディ レクトリを指します 。
したがって、上記の例では、ウィジェット・クラスが @app/componentsに配置されていると仮定すると、@app/components/views/hello.php という
ビュー・ファイルがレンダリングされることになります。 べどどぜぢちびづ
ぜしどつでづぴ〺〺でづぴざどづぷぐちぴと〨〩 メソッドをオーバーライドして、ウィジェット
のビュー・ファイルを含むディレクトリをカスタマイズすることが出来
ます。

〱〳〶

3.10.3ぃえぁぐごぅげ 〳〮 アプリケーションの構造

ベスト・プラクティス

ウィジェットはビューのコードを再利用するためのオブジェクト指向の方法です。
ウィジェットを作成するときでも、きざぃ パターンに従うべきです。
一般的に言うと、ロジックはウィジェット・クラスに保持し、表現はビュー に保持すべきです。
ウィジェットは自己完結的に設計されるべきです。 言い換えると、ウ ィジェット を使うとき に、他に何もしな いでもビュ ーに挿入することが出来るようにすべきです。 この要求は、ウィジェットがぃここ、おちぶちこっひどばぴ、画像などの外部リソースを必要とする場合は、扱いにくい問題になり得ます。 幸いなことに、すどど はこの問題を解決するのに利用することが出来る アセット・バンドル のサポートを提供しています。
ウィジェットがビュー・コードだけを含む場合は、ビュー と非常に似たものになります。 実際のところ、この場合、両者の唯一の違いは、
ウィジェットが再配布可能なクラスである一方で、 ビューはアプリケー
ション内に保持することが望ましい素の ぐえぐ スクリプトである、というぐらいの事です。

3.11

アセット

すどど では、アセットは、ウェブ・ページで参照できるファイルを意味します。アセットは ぃここ ファイルであったり、おちぶちこっひどばぴ ファイルであった
り、画像やビデオのファイルであったりします。 アセットはウェブでアクセス可能なディレクトリに配置され、ウェブ・サーバによって直接に提供されます。
たいていの場合、アセットはプログラム的に管理する方が望ましいものです。 例えば、ページの中で べどどぜなふどぜいちぴづぐどっにづひ ウィジェットを使うとき、このウィジェットは必要な ぃここ と おちぶちこっひどばぴ のファイルを自動的にインクルードします。 あなたに対して、手作業で必要なファイルを探してインクルードするように要求したりはしません。 そして、このウィジェットを新しいバージョンにアップグレードしたときは、自動的に新しいバージョンのアセット・ファイルが使用されるようになります。 このチュートリアルでは、すどど によって提供される強力なアセット
管理機能について説明します。

3.11.1

アセット・バンドル

すどど はアセットを アセット・バンドル を単位として管理します。アセッ
ト・バンドルは、簡単に言えば、 あるディレクトリの下に集められた一群のアセットです。 ビュー の中でアセット・バンドルを登録すると、バンドルの中の ぃここ や おちぶちこっひどばぴ のファイルがレンダリングされるウェブ・ページに挿入されます。

〳〮〱〱〮 アセット

3.11.2〱〳〷

アセット・バンドルを定義する

アセット・バンドルは べどどぜぷづぢぜぁびびづぴあふのつぬづ から拡張された ぐえぐ クラスとして定義されます。 バンドルの名前は、対応する ぐえぐ クラスの完
全修飾名 〨先頭のバック・スラッシュを除く〩 です。 アセット・バンド
ル・クラスは オートロード可能 でなければなりません。 アセット・バ
ンドル・クラスは、通常、アセットがどこに置かれているか、バンドルがどういう ぃここ や おちぶちこっひどばぴ のファイルを含んでいるか、そして、バンドルが他のバンドルにどのように依存しているかを定義します。
以下のコードは ベーシック・プロジェクト・テンプレート によって使用されているメインのアセット・バンドルを定義するものです。
<?php
namespace app\assets;
use yii\web\AssetBundle;
class AppAsset extends AssetBundle{
public $basePath = '@webroot';
public $baseUrl = '@web';public $css = ['css/site.css',['css/print.css', 'media' => 'print'],];
public $js = [];public $depends = ['yii\web\YiiAsset','yii\bootstrap\BootstrapAsset',];}

上の AppAsset クラスは、アセット・ファイルが @webroot ディレクトリの下に配置されており、それが さげが @web に対応することを定義しています。
バンドルは一つだけ ぃここ ファイル css/site.css を含み、おちぶちこっひどばぴ ファ
イルは含みません。 バンドルは、他の二つのバンドル、すなわち べどど
ぜぷづぢぜすどどぁびびづぴ と べどどぜぢははぴびぴひちばぜあははぴびぴひちばぁびびづぴ に依存しています。
以下、べどどぜぷづぢぜぁびびづぴあふのつぬづ のプロパティに関して、更に詳細に説明します。
• びはふひっづぐちぴと〺 このバンドルのアセット・ファイルを含むルート・
ディレクトリを指定します。 ルート・ディレクトリがウェブ・アク
セス可能でない場合に、このプロパティをセットしなければなりません。 そうでない場合は、代りに、ぢちびづぐちぴと と ぢちびづさひぬ のプロパ
ティをセットしなければなりません。 パス・エイリアス をここで使うことが出来ます。
• ぢちびづぐちぴと〺 このバンドルのアセット・ファイルを含むウェブ・アク
セス可能なディレクトリを指定します。 びはふひっづぐちぴと プロパティを〱〳〸

ぃえぁぐごぅげ 〳〮 アプリケーションの構造セットした場合は、アセット・マネージャ がバンドルに含まれるファイルをウェブ・アクセス可能なディレクトリに発行して、 その結果、このプロパティを上書きします。 アセット・ファイルが既にウェブ・アクセス可能なディレクトリにあり、アセットの発行が必
要でない場合に、このプロパティをセットしなければなりません。
パス・エイリアス をここで使うことが出来ます。
• ぢちびづさひぬ〺 ぢちびづぐちぴと ディレクトリに対応する さげが を指定します。
ぢちびづぐちぴと と同じように、びはふひっづぐちぴと プロパティをセットした場合は、 アセット・マネージャ がアセットを発行して、その結果、このプロパティを上書きします。 パス・エイリアス をここで使うことが出来ます。
• っびび〺 このバンドルに含まれている ぃここ ファイルをリストする配列です。 ディレクトリの区切りとしてフォワード・スラッシュ 【〯】 だけを使わなければならないことに注意してください。 それぞれのファイルは、個別に、パス文字列、または、パス文字列と属性のタ
グと値を一緒に含む配列によって指定することが出来ます。
• なび〺 このバンドルに含まれる おちぶちこっひどばぴ ファイルをリストする配列です。 この配列の形式は、っびび の配列の形式と同じです。 それぞれの おちぶちこっひどばぴ ファイルは、以下の二つの形式のどちらかによって指定することが出来ます。
〕 ローカルの おちぶちこっひどばぴ ファイルを表す相対パス 〨例えば js/main.js〩。
実際のファイルのパスは、この相対パスの前に べどどぜぷづぢぜぁびびづぴきちのちでづひ〺〺〤ぢちびづぐちぴと を付けることによって決定されます。 また、実際の さげが は、この相対パスの前に べどどぜぷづぢぜぁびびづぴきちのちでづひ〺〺〤ぢちびづさひぬ を付けることによって決定されます。
〕 外部の おちぶちこっひどばぴ ファイルを表す絶対 さげが。 例えば、https://ajax.googleapis.com/a
や //ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js など。
• つづばづのつび〺 このバンドルが依存しているアセット・バンドルの名前をリストする配列です 〨バンドルの依存関係については、すぐ後で説明します〩。
• なびくばぴどはのび〺 このバンドルにある 全て の おちぶちこっひどばぴ ファイルについて、 それを登録するときに呼ばれる べどどぜぷづぢぜざどづぷ〺〺ひづでどびぴづひおびうどぬづ〨〩
メソッドに渡されるオプションを指定します。
• っびびくばぴどはのび〺 このバンドルにある 全て の ぃここ ファイルについて、それを登録するときに呼ばれる べどどぜぷづぢぜざどづぷ〺〺ひづでどびぴづひぃびびうどぬづ〨〩
メソッドに渡されるオプションを指定します。
• ばふぢぬどびとくばぴどはのび〺 ソースのアセット・ファイルをウェブ・ディレク
トリに発行するときに呼ばれる べどどぜぷづぢぜぁびびづぴきちのちでづひ〺〺ばふぢぬどびと〨〩
メソッドに渡されるオプションを指定します。 これは びはふひっづぐちぴと
プロパティを指定した場合にだけ使用されます。
アセットの配置場所
アセットは、配置場所を基準にして、次のように分類することが出来ま〳〮〱〱〮 アセット〱〳〹

す。
• ソース・アセット〺 アセット・ファイルは、ウェブ経由で直接にアクセスすることが出来ない ぐえぐ ソース・コードと一緒に配置されています。 ページの中でソース・アセットを使用するためには、
ウェブ・ディレクトリにコピーして、いわゆる発行されたアセットに変換しなければなりません。 このプロセスは、すぐ後で詳しく説明しますが、アセット発行 と呼ばれます。
• 発行されたアセット〺 アセット・ファイルはウェブ・ディレクトリ
に配置されており、したがってウェブ経由で直接にアクセスすることが出来ます。
• 外部アセット〺 アセット・ファイルは、あなたのウェブ・アプリ
ケーションをホストしているのとは別のウェブ・サーバ上に 配置されています。
アセット・バンドル・クラスを定義するときに、びはふひっづぐちぴと プロパティを指定した場合は、 相対パスを使ってリストに挙げられたアセットは全てソース・アセットであると見なされます。 このプロパティを指定しなかった場合は、アセットは発行されたアセットであることになります 〨したがって、ぢちびづぐちぴと と ぢちびづさひぬ を指定して、アセットがどこに配置されているかを すどど に知らせなければなりません〩。
アプリケーションに属するアセットは、不要なアセット発行プロセスを避けるために、ウェブ・ディレクトリに置くことが推奨されます。 前
述の例において AppAsset が びはふひっづぐちぴと ではなく ぢちびづぐちぴと を指定しているのは、これが理由です。
エクステンション の場合は、 アセットがソース・コードと一緒にウェブからアクセス出来ないディレクトリに配置されているため、 ア
セット・バンドル・クラスを定義するときには びはふひっづぐちぴと プロパティを指定しなければなりません。
補足〺 @webroot/assets を ソース・パス として使ってはいけま
せん。 このディレクトリは、デフォルトでは、アセット・マ
ネージャ がソースの配置場所から発行されたアセット・ファ
イルを保存する場所として使われます。 このディレクトリの中のファイルはすべて一時的なものと見なされており、 削除されることがあります。
アセットの依存関係
ウェブ・ページに複数の ぃここ や おちぶちこっひどばぴ ファイルをインクルードする
ときは、オーバーライドの問題を避けるために、一定の順序に従わなけ
ればなりません。 例えば、ウェブ・ページで なけふづひべ さぉ ウィジェットを使おうとするときは、なけふづひべ おちぶちこっひどばぴ ファイルが なけふづひべ さぉ おちぶちこっひどばぴ
ファイルより前にインクルードされることを保証しなければなりません。 このような順序付けをアセット間の依存関係と呼びます。
アセットの依存関係は、主として、べどどぜぷづぢぜぁびびづぴあふのつぬづ〺〺〤つづばづのつび〱〴〰

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

プ ロ パ テ ィ に よ っ て 指 定 さ れ ま す 。 AppAsset の 例 で は 、 こ の ア セ ッ
ト・バンドルは他の二つのアセット・バンドル、すなわち、べどどぜぷづぢ
ぜすどどぁびびづぴ と べどどぜぢははぴびぴひちばぜあははぴびぴひちばぁびびづぴ に依存しています。 このことは、AppAsset の ぃここ と おちぶちこっひどばぴ ファイルが、依存している二つのアセット・バンドルにあるファイルの 後に インクルードされることを意味します。
アセットの依存関係は中継されます。つまり、バンドル ぁ が あ に依存し、あ が ぃ に依存していると、ぁ は ぃ にも依存していることになります。
アセットのオプション
っびびくばぴどはのび および なびくばぴどはのび のプロパティを指定して、 ぃここ と おちぶちこっひどばぴ
ファイルがページにインクルードされる方法をカスタマイズすることが出来ます。 これらのプロパティの値は、ビュー が ぃここ と おちぶちこっひどばぴ ファ
イルをインクルードするために、べどどぜぷづぢぜざどづぷ〺〺ひづでどびぴづひぃびびうどぬづ〨〩 お
よび べどどぜぷづぢぜざどづぷ〺〺ひづでどびぴづひおびうどぬづ〨〩 メソッドを呼ぶときに、それぞれ、オプションとして引き渡されます。
補足〺 バンドル・クラスでセットしたオプションは、バンドルの中の 全て の ぃここ〯おちぶちこっひどばぴ ファイルに適用されます。 いろいろなファイルに別々のオプションを使用したい場合は、上述した せせべどどぜぷづぢぜぁびびづぴあふのつぬづ〺〺っびびぼっびびそ の形式を使うか、 ま
たは、別々のアセット・バンドルを作成して、個々のバンド
ルの中では、一組のオプションを使うようにしなければなりません。
例えば、ぉぅ〹 以下のブラウザに対して ぃここ ファイルを条件的にインクルードするために、次のオプションを使うことが出来ます。
public $cssOptions = ['condition' => 'lte IE9'];

こうすると、バンドルの中の ぃここ ファイルは下記の えごきが タグを使ってインクルードされるようになります。
<!--[if lte IE9]><link rel="stylesheet" href="path/to/foo.css"><![endif]-->

生成された ぃここ のリンクタグを <noscript> の中に包むためには、次のよ
うに cssOptions を構成することが出来ます。
public $cssOptions = ['noscript' => true];

おちぶちこっひどばぴ ファイルをページの とづちつ セクションにインクルードするためには、次のオプションを使います 〨デフォルトでは、おちぶちこっひどばぴ ファイル
は ぢはつべ セクションの最後にインクルードされます〩。

〳〮〱〱〮 アセット〱〴〱

public $jsOptions = ['position' => \yii\web\View::POS_HEAD];

デフォルトでは、アセット・バンドルが発行されるときは、べどどぜぷづぢ
ぜぁびびづぴあふのつぬづ〺〺〤びはふひっづぐちぴと で指定されたディレクトリの中にある全てのコンテントが発行されます。 ばふぢぬどびとくばぴどはのび プロパティを構成する
ことによって、この振る舞いをカスタマイズすることが出来ます。 例え
ば、べどどぜぷづぢぜぁびびづぴあふのつぬづ〺〺〤びはふひっづぐちぴと の一個または数個のサブ・ディ
レクトリだけを発行するために、アセット・バンドル・クラスの中で下記のようにすることが出来ます。
<?php
namespace app\assets;
use yii\web\AssetBundle;
class FontAwesomeAsset extends AssetBundle{
public $sourcePath = '@bower/font-awesome';
public $css = ['css/font-awesome.min.css',];
public $publishOptions = ['only' => ['fonts/*','css/*',]];}

上記の例は、【てはのぴちぷづびはねづ】 パッケージ24 のためのアセット・バンドルを定義するものです。 発行オプション only を指定して、fonts と css サブ・
ディレクトリだけが発行されるようにしています。
あはぷづひ と ぎぐき のアセットのインストール
ほとんどの おちぶちこっひどばぴ〯ぃここ パッケージは、あはぷづひ25 および〯または ぎぐき26に よ っ て 管 理 さ れ て い ま す 。 ぐえぐ の 世 界 に は ぐえぐ の 依 存 を 管 理
する ぃはねばはびづひ がありますが、ぐえぐ のパッケージと全く同じように
composer.json を使って あはぷづひ のパッケージも ぎぐき のパッケージもロードすることが可能です。
このことを達成するために ぃはねばはびづひ の構成を少し修正しなければなりません。二つの方法があります。
https://fontawesome.com/
https://bower.io/26
https://www.npmjs.com/
24
25

〱〴〲

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

ちびびづぴ〭ばちっにちでどびぴ レポジトリを使う この方法は ぎぐき または あはぷづひ のパッケージを必要とするプロジェクトの大半の要求を満たすことが出来ます。
補足〺 〲〮〰〮〱〳 以降、ベーシック・アプリケーション・テンプ
レートとアドバンスト・アプリケーション・テンプレートはともに、 デフォルトで ちびびづぴ〭ばちっにちでどびぴ を使うように前もって構成されていますので、このセクションは読み飛ばすことが出来ます。
プロジェクトの composer.json に、下記を追加します。
"repositories": [{"type": "composer","url": "https://asset-packagist.org"}]

アプリケーション構成情報 の @npm と @bower の エイリアス を修正します。
$config = [...
'aliases' => ['@bower' => '@vendor/bower-asset','@npm'=> '@vendor/npm-asset',
],
...
];

ちびびづぴ〭ばちっにちでどびぴ がどのようにして動作するのかは、ちびびづぴ〭ばちっにちでどびぴ〮はひで のサイト27 に説明があります。
てへば〯っはねばはびづひ〭ちびびづぴ〭ばぬふでどの を使う ちびびづぴ〭ばちっにちでどびぴ と異なって、っはねばはびづひ〭
ちびびづぴ〭ばぬふでどの はアプリケーション構成の変更を少しも要求しません。 その代りに、次のコマンドを実行して特別な ぃはねばはびづひ プラグインをグロー
バルにインストールすることが要求されます。
composer global require "fxp/composer-asset-plugin:^1.4.1"

このコマンドによって っはねばはびづひ ちびびづぴ ばぬふでどの28 がグローバルにインストー
ルされ、 あはぷづひ と ぎぐき パッケージの依存関係を ぃはねばはびづひ によって管理することが出来るようになります。 プラグインがインストールされた
後は、あなたのコンピュータ上の全てのプロジェクトが composer.json を
通じて あはぷづひ と ぎぐき パッケージをサポートすることが出来ます。
27
28

https://asset-packagist.org
https://github.com/fxpio/composer-asset-plugin〳〮〱〱〮 アセット〱〴〳

すどど を使ってこれらのアセットを発行したい場合は、プロジェクトのcomposer.json に下記を追加して、 インストールされるパッケージが配置されるディレクトリを調整します。
"config": {"fxp-asset": {"installer-paths": {"npm-asset-library": "vendor/npm","bower-asset-library": "vendor/bower"}}}補足〺 fxp/composer-asset-plugin は、ちびびづぴ〭ばちっにちでどびぴ に比べて、composer
update コマンドを著しく遅くします。

ぃはねばはびづひ で あはぷづひ と ぎぐき をサポートできるように構成した後は〺〱〮 アプリケーションまたはエクステンションの composer.json ファイルを修正して、パッケージを require のエントリに入れます。 ライブ
ラリを参照するのに、bower-asset/PackageName 〨あはぷづひ パッケージ〩 ま
たは npm-asset/PackageName 〨ぎぐき パッケージ〩 を使わなければなりません。
〲〮 composer update を実行します。
〳〮 アセット・バンドル・クラスを作成して、アプリケーションまたはエクステンションで使う予定の おちぶちこっひどばぴ〯ぃここ ファイルをリストに挙げます。 びはふひっづぐちぴと プロパティは、@bower/PackageName また
は @npm/PackageName としなければなりません。 これは、ぃはねばはびづひ があはぷづひ または ぎぐき パッケージを、このエイリアスに対応するディ
レクトリにインストールするためです。
補足〺 パッケージの中には、全ての配布ファイルをサブ・ディ
レクトリに置くものがあります。 その場合には、そのサブ・ディレクトリを びはふひっづぐちぴと の値として指定しなければなりません。 例えば、べどどぜぷづぢぜおぱふづひべぁびびづぴ は @bower/jquery ではな
く @bower/jquery/dist を使います。

3.11.3

アセット・バンドルを使う

アセット・バンドルを使うためには、べどどぜぷづぢぜぁびびづぴあふのつぬづ〺〺ひづでどびぴづひ〨〩
メソッドを呼んでアセット・バンドルを ビュー に登録します。 例えば、
次のようにしてビュー・テンプレートの中でアセット・バンドルを登録することが出来ます。

〱〴〴

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

use app\assets\AppAsset;
AppAsset::register($this);// $this はビュー・オブジェクトを表す

情報〺 べどどぜぷづぢぜぁびびづぴあふのつぬづ〺〺ひづでどびぴづひ〨〩 メソッドは、ぢちびづぐちぴと
や ぢちびづさひぬ など、 発行されたアセットに関する情報を含むア
セット・バンドル・オブジェクトを返します。
他の場所でアセ ット・バン ドルを登録しよう とするとき は、必要とされるビュー・オブジェクトを提供しなければなりません。 例えば、ウィジェット・クラスの中でアセット・バンドルを登録するためには、$this->view によってビュー・オブジェクトを取得することが出来ます。
アセット・バンドルがビューに登録されるとき、舞台裏では、依存している全てのアセット・バンドルが すどど によって登録されます。 そして、アセット・バンドルがウェブからはアクセス出来ないディレクト
リに配置されている場合は、 アセット・バンドルがウェブ・ディレク
トリに発行されます。 その後、ビューがページをレンダリングするときに、登録されたバンドルのリストに挙げられている ぃここ と おちぶちこっひどばぴ
ファイルのための <link> タグと <script> タグが生成されます。 これらのタグの順序は、登録されたバンドル間の依存関係、および、べどどぜぷづぢ
ぜぁびびづぴあふのつぬづ〺〺〤っびび と べどどぜぷづぢぜぁびびづぴあふのつぬづ〺〺〤なび のプロパティのリス
トに挙げられたアセットの順序によって決定されます。
動的なアセット・バンドル
アセット・バンドルは、通常の ぐえぐ クラスですので、内部のパラメー
タを動的に調整する追加のロジックを持つことが出来ます。 例えば、洗練された おちぶちこっひどばぴ ライブラリには、国際化の機能を、サポートする言
語ごとに独立したソース・ファイルにパッケージして提供しているものもあります。 その場合、ライブラリの翻訳を動作させるためには、特定の だ〮なび〧 ファイルをページに追加しなければなりません。 このことを べどど
ぜぷづぢぜぁびびづぴあふのつぬづ〺〺どのどぴ〨〩 メソッドをオーバーライドすることによって実現することが出来ます。
namespace app\assets;
use yii\web\AssetBundle;
use Yii;
class SophisticatedAssetBundle extends AssetBundle{
public $sourcePath = '/path/to/sophisticated/src';
public $js = ['sophisticated.js' // 常に使用されるファイル];
public function init()〱〴〵〳〮〱〱〮 アセット{}

parent::init();$this->js[] = 'i18n/' . Yii::$app->language . '.js'; // 動的に追加されるファイル}

個々のアセット・バンドルは、 べどどぜぷづぢぜぁびびづぴあふのつぬづ〺〺ひづでどびぴづひ〨〩 によって返されるインスタンスによって調整することも出来ます。 例えば、
use app\assets\SophisticatedAssetBundle;
use Yii;$bundle = SophisticatedAssetBundle::register(Yii::$app->view);$bundle->js[] = 'i18n/' . Yii::$app->language . '.js'; // 動的に追加される
ファイル

補足〺 アセット・バンドルの動的な調整はサポートされてはいますが、推奨はされません。 予期しない副作用を引き起こしやすいので、可能であれば避けるべきです。
アセット・バンドルをカスタマイズする
すどど は、べどどぜぷづぢぜぁびびづぴきちのちでづひ によって実装されている assetManager という名前のアプリケーション・コンポーネントを通じてアセット・バン
ドルを管理します。 べどどぜぷづぢぜぁびびづぴきちのちでづひ〺〺〤ぢふのつぬづび プロパティを構成することによって、アセット・バンドルの振る舞いをカスタマイズすることが出来ます。 例えば、デフォルトの べどどぜぷづぢぜおぱふづひべぁびびづぴ アセッ
ト・バンドルはインストールされた なけふづひべ の あはぷづひ パッケージにある
jquery.js ファイルを使用します。 あなたは、可用性とパフォーマンス
を向上させるために、ぇははでぬづ によってホストされたバージョンを使いた
いと思うかも知れません。 次のように、アプリケーションの構成情報でassetManager を構成することによって、それが達成できます。
return [// ...
'components' => ['assetManager' => ['bundles' => ['yii\web\JqueryAsset' => ['sourcePath' => null,'js' => [

];

],

],

],

],

]

// バンドルを発行しない'//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js',〱〴〶

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

複数のアセット・バンドルも同様に べどどぜぷづぢぜぁびびづぴきちのちでづひ〺〺〤ぢふのつぬづびによって構成することが出来ます。 配列のキーは、アセット・バンドルのクラス名 〨最初のバック・スラッシュを除く〩 とし、 配列の値は、対応
する 構成情報配列 とします。
ヒント〺 アセット・バンドルの中で使うアセットを条件的に選択することが出来ます。 次の例は、開発環境では jquery.js を使い、そうでなければ jquery.min.js を使う方法を示すものです。
'yii\web\JqueryAsset' => ['js' => [YII_ENV_DEV ? 'jquery.js' : 'jquery.min.js']],

無効にしたいアセット・バンドルの名前に false を結びつけることによって、一つまたは複数のアセット・バンドルを無効にすることが出来ます。 無効にされたアセット・バンドルをビューに登録した場合は、依存するバンドルは一つも登録されません。 また、ビューがページをレンダリングするときも、バンドルの中のアセットは一つもインクルードされません。 例えば、べどどぜぷづぢぜおぱふづひべぁびびづぴ を無効化するために、次の構成
情報を使用することが出来ます。
return [// ...
'components' => ['assetManager' => ['bundles' => ['yii\web\JqueryAsset' => false,
],
],
],
];

べどどぜぷづぢぜぁびびづぴきちのちでづひ〺〺〤ぢふのつぬづび を false にセットすることによって、全て のバンドルを無効にすることも出来ます。
べどどぜぷづぢぜぁびびづぴきちのちでづひ〺〺〤ぢふのつぬづび によってなされたカスタマイズは
アセット・バンドルの生成時、すなわち、オブジェクトのコンストラ
クタの段階で適用される、 ということを心に留めてください。 従って、べどどぜぷづぢぜぁびびづぴきちのちでづひ〺〺〤ぢふのつぬづび のレベルで設定されたマッピング
は、それ以後にバンドルのオブジェクトに対してなされる修正によって上書きされます。 具体的に言えば、べどどぜぷづぢぜぁびびづぴあふのつぬづ〺〺どのどぴ〨〩
メソッドの中での修正や、登録されたバンドル・オブジェクトに対する修正は、AssetManager の構成よりも優先されます。 以下に、べどどぜぷづぢ
ぜぁびびづぴきちのちでづひ〺〺〤ぢふのつぬづび によって設定されたマッピングが効力を持たない例を示します。

〳〮〱〱〮 アセット〱〴〷// プログラムのソース・コード
namespace app\assets;
use yii\web\AssetBundle;
use Yii;
class LanguageAssetBundle extends AssetBundle{// ...
public function init(){
parent::init();$this->baseUrl = '@web/i18n/' . Yii::$app->language; //AssetManager` では処理出来ない!
}}// ...

$bundle = \app\assets\LargeFileAssetBundle::register(Yii::$app->view);$bundle->baseUrl = YII_DEBUG ? '@web/large-files':'@web/large-files/minified'; // AssetManager` では処理出来ない!
// アプリケーション構成
return [// ...
'components' => ['assetManager' => ['bundles' => ['app\assets\LanguageAssetBundle' => ['baseUrl' => 'https://some.cdn.com/files/i18n/en' // 効
力を持たない!
],'app\assets\LargeFileAssetBundle' => ['baseUrl' => 'https://some.cdn.com/files/large-files' //
効力を持たない!
],
],
],
],
];

アセット・マッピング
時として、複数のアセット・バンドルで使われている 正しくない〯互換
でない アセット・ファイル・パスを「修正」したい場合があります。 例
えば、バンドル ぁ がバージョン 〱〮〱〱〮〱 の jquery.min.js を使い、バンドル
あ がバージョン 〲〮〱〮〱 の jquery.js を使っているような場合です。 それぞれのバンドルをカスタマイズすることで問題を修正することも出来ます〱〴〸

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

が、それよりも簡単な方法は、アセット・マップ 機能を使って、正しくないアセットを望ましいアセットに割り付けることです。 そうするためには、以下のように べどどぜぷづぢぜぁびびづぴきちのちでづひ〺〺〤ちびびづぴきちば プロパティを構成します。
return [// ...
'components' => ['assetManager' => ['assetMap' => ['jquery.js' =>'//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js',
],
],
],
];

ちびびづぴきちば のキーは修正したいアセットの名前であり、値は望ましいア
セットのパスです。 アセット・バンドルをビューに登録するとき、っびびと なび の配列に含まれるすべてのアセット・ファイルの相対パスがこのマップと突き合わせて調べられます。 キーのどれかがアセット・ファイ
ルのパス 〨利用できる場合は、べどどぜぷづぢぜぁびびづぴあふのつぬづ〺〺〤びはふひっづぐちぴと が前置されます〩 の最後の部分と一致した場合は、対応する値によってアセットが置き換えられ、ビューに登録されます。 例えば、my/path/to/jquery.jsというアセット・ファイルは jquery.js というキーにマッチします。
補足〺 相対パスを使って指定されたアセットだけがアセット・マッピングの対象になります。 そして、置き換える側のア
セットのパスは、絶対 さげが であるか、べどどぜぷづぢぜぁびびづぴきちのちでづひ〺〺〤ぢちびづぐちぴと からの相対パスであるかの、どちらかでなければなりません。
アセット発行
既に述べたように、アセット・バンドルがウェブからアクセス出来ない
ディレクトリに配置されている場合は、 バンドルがビューに登録される
ときに、アセットがウェブ・ディレクトリにコピーされます。 このプロ
セスは アセット発行 と呼ばれ、アセット・マネージャ によって自動的に実行されます。
デフォルトでは、アセットが発行されるディレクトリは @webroot/assets
であり、@web/assets という さげが に対応するものです。 この場所は、ぢちびづぐちぴとと ぢちびづさひぬ のプロパティを構成してカスタマイズすることが出来ます。
ファイルをコピーすることでアセットを発行する代りに、くこ とウェ
ブ・サーバが許容するなら、シンボリック・リンクを使うことを考慮しても良いでしょう。 この機能は ぬどのにぁびびづぴび を true にセットすることで有効にすることが出来ます。

〳〮〱〱〮 アセット〱〴〹return [// ...
'components' => ['assetManager' => ['linkAssets' => true,
],
],
];

上記の構成によって、アセット・マネージャはアセット・バンドルを発行するときにソース・パスへのシンボリック・リンクを作成するようになります。 この方がファイルのコピーより速く、また、 発行されたアセットが常に最新であることを保証することも出来ます。
キャッシュの廃棄運用モードで動作しているウェブ・アプリケーションでは、アセットな
どの静的なリソースに対する えごごぐ キャッシュを有効にするのが通例です。 この慣行の難点は、アセットを修正して運用サーバに配備したときに、ユーザのクライアントが えごごぐ キャッシュのせいで古いバージョンを使い続けるおそれが常にあるという点です。 この難点を克服するために、キャッシュ廃棄機能を使うことが出来ます。 これはバージョン 〲〮〰〮〳
で導入された機能で、べどどぜぷづぢぜぁびびづぴきちのちでづひ を下記のように構成することで有効になります。
return [// ...
'components' => ['assetManager' => ['appendTimestamp' => true,
],
],
];

このようにすると、全ての発行されたアセットの さげが の末尾に最終更新
日時のタイムスタンプが追加されます。 例えば、yii.js に対する さげが は/assets/5515a87c/yii.js?v=1423448645" のようなものになります。 パラメー
タ v が yii.js ファイルの最終更新日時のタイムスタンプを表しています。 これで、あなたがアセットを修正したときには、その さげが も変更
され、クライアントに最新バージョンのアセットを強制的に取得させることが出来ます。

3.11.4

よく使われるアセット・バンドル

コアの すどど コードは多くのアセット・バンドルを定義しています。 その中で、下記のバンドルはよく使われるものであり、あなたのアプリケー
ションやエクステンションのコードでも参照することが出来るもので
す。

〱〵〰

ぃえぁぐごぅげ 〳〮 アプリケーションの構造• べどどぜぷづぢぜすどどぁびびづぴ〺 主 と し て yii.js フ ァ イ ル を イ ン ク ル ー ド す
るためのバンドルです。 このファイルはモジュール化された
おちぶちこっひどばぴ のコードを編成するメカニズムを実装しています。 また、data-method と data-confirm の属性に対する特別なサポートや、
その他の有用な機能を提供します。 yii.js に関する詳細な情報はクライアント・スクリプトのセクション にあります。
• べどどぜぷづぢぜおぱふづひべぁびびづぴ〺 なけふづひべ の ぢはぷづひ パッケージから jquery.js
ファイルをインクルードします。
• べどどぜぢははぴびぴひちばぜあははぴびぴひちばぁびびづぴ〺 ごぷどぴぴづひ あははぴびぴひちば フレームワーク
から ぃここ ファイルをインクルードします。
• べどどぜぢははぴびぴひちばぜあははぴびぴひちばぐぬふでどのぁびびづぴ〺 あははぴびぴひちば おちぶちこっひどばぴ プラ
グインをサポートするために、 ごぷどぴぴづひ あははぴびぴひちば フレームワーク
から おちぶちこっひどばぴ ファイルをインクルードします。
• べどどぜなふどぜおふどぁびびづぴ〺 なけふづひべ さぉ ライブラリから ぃここ と おちぶちこっひどばぴ のファイルをインクルードします。
あなたのコードが、なけふづひべ や なけふづひべ さぉ または あははぴびぴひちば に依存する場
合は、自分自身のバージョンを作るのではなく、これらの定義済みのア
セット・バンドルを使用すべきです。 これらのバンドルのデフォルトの設定があなたの必要を満たさない時は、アセット・バンドルをカスタマイズする の項で説明したように、それをカスタマイズすることが出来ます。

3.11.5アセット変換直接に ぃここ および〯または おちぶちこっひどばぴ のコードを書く代りに、何らかの拡張構文を使って書いたものを特別なツールを使って ぃここ〯おちぶちこっひどばぴ に変換する、ということを開発者はしばしば行います。 例えば、ぃここ コードのためには、がぅここ29 や こぃここ30 を使うことが出来ます。 また、おちぶちこっひどばぴのためには、ごべばづこっひどばぴ31 を使うことが出来ます。
拡張構文を使ったアセット・ファイルをアセット・バンドルの中のっびび と なび のリストに挙げることが出来ます。例えば、
class AppAsset extends AssetBundle{
public $basePath = '@webroot';
public $baseUrl = '@web';public $css = ['css/site.less',];public $js = ['js/site.ts',];
public $depends = [https://lesscss.org/
https://sass-lang.com/
31
https://www.typescriptlang.org/
29
30

〳〮〱〱〮 アセット

];

}

〱〵〱

'yii\web\YiiAsset','yii\bootstrap\BootstrapAsset',

このようなアセット・バンドルをビューに登録すると、アセット・マ
ネージャ が自動的にプリ・プロセッサ・ツールを走らせて、 認識できた
拡張構文のアセットを ぃここ〯おちぶちこっひどばぴ に変換します。 最終的にビューがページをレンダリングするときには、ビューは元の拡張構文のアセットではなく、 変換後の ぃここ〯おちぶちこっひどばぴ ファイルをページにインクルードします。
すどど はファイル名の拡張子を使って、アセットが使っている拡張構文を識別します。 デフォルトでは、下記の構文とファイル名拡張子を認識します。
• がぅここ32 〺 .less• こぃここ33 〺 .scss• こぴべぬふび34 〺 .styl• ぃは〛づづこっひどばぴ35 〺 .coffee• ごべばづこっひどばぴ36 〺 .ts
すどど はインストールされたプリ・プロセッサ・ツールに頼ってアセットを変換します。 例えば、がぅここ37 を使うためには、lessc プリ・プロセッ
サ・コマンドをインストールしなければなりません。
下記のように べどどぜぷづぢぜぁびびづぴきちのちでづひ〺〺〤っはのぶづひぴづひ を構成することで、 プリ・プロセッサ・コマンドとサポートされる拡張構文をカスタマ
イズすることが出来ます。
return ['components' => ['assetManager' => ['converter' => ['class' => 'yii\web\AssetConverter','commands' => ['less' => ['css', 'lessc {from} {to} --no-color'],'ts' => ['js', 'tsc --out {to} {from}'],
],
],
],
],
];

上記においては、サポートされる拡張構文が べどどぜぷづぢぜぁびびづぴぃはのぶづひぴづひ〺〺〤っはねねちのつび プロパティによって定義されています。 配列のキーはファイ
https://lesscss.org/
https://sass-lang.com/
34
https://stylus-lang.com/
35
https://coffeescript.org/
36
https://www.typescriptlang.org/
37
https://lesscss.org/
32
33

〱〵〲

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

ルの拡張子 〨先頭のドットは省く〩 であり、 配列の値は結果として作られるアセット・ファイルの拡張子とアセット変換を実行するためのコマンドです。 コマンドの中の {from} と {to} のトークンは、ソースのアセッ
ト・ファイルのパスとターゲットのアセット・ファイルのパスに置き換えられます。
情報〺 上記で説明した方法の他にも、拡張構文のアセットを扱う方法はあります。 例えば、でひふのぴ38 のようなビルド・ツール
を使って、拡張構文のアセットをモニターし、 自動的に変換することが出来ます。 この場合は、元のファイルではなく、結果として作られる ぃここ〯おちぶちこっひどばぴ ファイルをアセット・バ
ンドルのリストに挙げなければなりません。

3.11.6

アセットを結合して圧縮する

ウェブ・ページは数多くの ぃここ および〯または おちぶちこっひどばぴ ファイルをイ
ンクルードすることがあり得ます。 えごごぐ リクエストの数とこれらのファイルの全体としてのダウンロード・サイズを削減するためによく用いられる方法は、複数の ぃここ〯おちぶちこっひどばぴ ファイルを結合して圧縮し、一つまたはごく少数のファイルにまとめることです。 そして、ウェブ・ページでは元のファイルをインクルードする代りに、圧縮されたファイ
ルをインクルードする訳です。
情報〺 アセットの結合と圧縮は、通常はアプリケーションが本番モードにある場合に必要になります。 開発モードにおいては、たいていは元の ぃここ〯おちぶちこっひどばぴ ファイルを使う方がデバッグのために好都合です。
次に、既存のアプリケーション・コードを修正する必要なしに、 アセット・ファイルを結合して圧縮する方法を紹介します。
〱〮 アプリケーションの中で、結合して圧縮する予定のアセット・バン
ドルを全て探し出す。
〲〮 これらのバンドルを一個か数個のグループにまとめる。どのバンド
ルも一つのグループにしか属することが出来ないことに注意。
〳〮 各グループの ぃここ ファイルを一つのファイルに結合〯圧縮する。おちぶちこっひどばぴ
ファイルに対しても同様にこれを行う。
〴〮 各グループに対して新しいアセット・バンドルを定義する。
• っびび と なび のプロパティに、 それぞれ、結合された ぃここ ファ
イルと おちぶちこっひどばぴ ファイルをセットする。
38

https://gruntjs.com/

〳〮〱〱〮 アセット〱〵〳

• 各グループに属する元のアセット・バンドルをカスタマイズして、っびび と なび のプロパティを空にし、つづばづのつび プロパティにグループのために作られた新しいバンドルを指定する。
この方法を使うと、ビューでアセット・バンドルを登録したときに、 元のバンドルが属するグループのための新しいアセット・バンドルが自動的に登録されるようになります。 そして、結果として、結合〯圧縮された
アセット・ファイルが、元のファイルの代りに、ページにインクルードされます。
一例
上記の方法をさらに説明するために一つの例を挙げましょう。
あなたのアプリケーションが二つのページ、じ と す を持つと仮定します。ページ じ はアセット・バンドル ぁ、あ、ぃ を使用し、ページ す は
アセット・バンドル あ、ぃ、い を使用します。
これらのアセット・バンドルを分割する方法は二つあります。一つは単一のグループを使用して全てのアセット・バンドルを含める方法です。 もう一つは、ぁ をグループ じ に入れ、い をグループ す に入れ、そして、あ と ぃ をグループ こ に入れる方法です。 どちらが良いでしょう〿
場合によります。 最初の方法の利点は、二つのページが同一の結合された ぃここ と おちぶちこっひどばぴ のファイルを共有するため、えごごぐ キャッシュの効
果が高くなることです。 その一方で、単一のグループが全てのバンドルを含むために、結合された ぃここ と おちぶちこっひどばぴ のファイルはより大きくな
り、従って最初のファイル転送時間はより長くなります。 この例では話を簡単にするために、最初の方法、すなわち、全てのバンドルを含む単一のグループを使用することにします。
情報〺 アセット・バンドルをグループに分けることは些細な仕事ではありません。通常、そのためには、いろいろなペー
ジのさまざまなアセットの現実世界での転送量を分析することが必要になります。 とりあえず、最初は、簡単にするために、単一のグループから始めて良いでしょう。
既存のツール 〨例えば ぃぬはびふひづ ぃはねばどぬづひ39 や すさぉ ぃはねばひづびびはひ40 〩 を使って、 全てのバンドルにある ぃここ と おちぶちこっひどばぴ のファイルを結合して圧縮します。 ファイルは、バンドル間の依存関係を満たす順序に従って結合しなければならないことに注意してください。 例えば、バンドル ぁ が あに依存し、あ が ぃ と い の両方に依存している場合は、アセット・ファイ
ルの結合順は、 最初に ぃ と い、次に あ、そして最後に ぁ としなければなりません。
結合と圧縮が完了すると、一つの ぃここ ファイルと一つの おちぶちこっひどばぴ
ファイルが得られます。 それらは、all-xyz.css および all-xyz.js と命
3940

https://developers.google.com/closure/compiler/
https://github.com/yui/yuicompressor/

〱〵〴

ぃえぁぐごぅげ 〳〮 アプリケーションの構造名されたとしましょう。 ここで xyz は、ファイル名をユニークにしてえごごぐ キャッシュの問題を避けるために使用されるタイムスタンプまたはハッシュを表します。
いよいよ最終ステップです。 アプリケーションの構成情報の中で、アセット・マネージャ を次のように構成します。
return ['components' => ['assetManager' => ['bundles' => ['all' => ['class' => 'yii\web\AssetBundle','basePath' => '@webroot/assets','baseUrl' => '@web/assets','css' => ['all-xyz.css'],'js' => ['all-xyz.js'],],'A' => ['css' => [], 'js' => [], 'depends' => ['all']],'B' => ['css' => [], 'js' => [], 'depends' => ['all']],'C' => ['css' => [], 'js' => [], 'depends' => ['all']],'D' => ['css' => [], 'js' => [], 'depends' => ['all']],
],
],
],
];

アセット・バンドルをカスタマイズする の項で説明したように、上記の構成によって元のバンドルは全てデフォルトの振る舞いを変更されます。 具体的にいえば、バンドル ぁ、あ、ぃ、い は、もはやアセット・
ファイルを一つも持っていません。 この〴つは、それぞれ、結合された
all-xyz.css と all-xyz.js ファイルを持つ all バンドルに依存するようになりました。 結果として、ページ じ では、バンドル ぁ、あ、ぃ から元の
ソース・ファイルをインクルードする代りに、これら二つの結合されたファイルだけがインクルードされます。 同じことはページ す でも起ります。
最後にもう一つ、上記の方法をさらにスムーズに運用するためのト
リックがあります。 アプリケーションの構成情報ファイルを直接修正する代りに、バンドルのカスタマイズ用の配列を独立したファイルに置いて、条件によってそのファイルをアプリケーションの構成情報にインクルードすることが出来ます。 例えば、
return ['components' => ['assetManager' => ['bundles' => require __DIR__ . '/' . (YII_ENV_PROD ?
'assets-prod.php' : 'assets-dev.php'),
],
],
];

〳〮〱〱〮 アセット〱〵〵

つまり、アセット・バンドルの構成情報配列は、本番モードのものはassets-prod.php に保存し、 開発モードのものは assets-dev.php に保存するという訳です。
補足〺 このアセット結合のメカニズムは、登録されるアセッ
ト・バンドルのプロパティをオーバーライドできるという べどどぜぷづぢぜぁびびづぴきちのちでづひ〺〺〤ぢふのつぬづび の機能に基づいています。 しかし、既に上で述べたように、この機能は、べどどぜぷづぢ
ぜぁびびづぴあふのつぬづ〺〺どのどぴ〨〩 メソッドの中やバンドルが登録された後で実行されるアセット・バンドルの修正をカバーしていません。 そのような動的なバンドルの使用は、アセット結合をする際には避けなければなりません。
コマンドを使う
すどど は、たった今説明した方法を自動化するための asset という名前のコ
ンソール・コマンドを提供しています。
このコマンドを使うためには、最初に構成情報ファイルを作成して、どのアセット・バンドルが結合されるか、 そして、それらがどのようにグループ化されるかを記述しなければなりません。 asset/template サブ・
コマンドを使って最初にテンプレートを生成し、それをあなたの要求に合うように修正することが出来ます。
yii asset/template assets.php

上記のコマンドは、カレント・ディレクトリに assets.php というファイ
ルを生成します。このファイルの内容は以下のようなものです。
<?php
/**
* "yii asset" コンソール・コマンドのための構成情報ファイル* コンソール環境では、'@webroot' や '@web' のように、存在しないパス・エイリア
スがあり得ることに注意してください。
* これらの欠落したパス・エイリアスは手作業で定義してください。
*/
return [// JavaScript ファイルの圧縮のためのコマンド/コールバックを調整。
'jsCompressor' => 'java -jar compiler.jar --js {from} --js_output_file{to}',// CSS ファイルの圧縮のためのコマンド/コールバックを調整。
'cssCompressor' => 'java -jar yuicompressor.jar --type css {from} -o{to}',// 圧縮後にアセットのソースを削除するかどうか。
'deleteSource' => false,// 圧縮するアセット・バンドルのリスト。
'bundles' => [// 'yii\web\YiiAsset',// 'yii\web\JqueryAsset',
],

〱〵〶

];

ぃえぁぐごぅげ 〳〮 アプリケーションの構造// 圧縮出力用のアセット・バンドル。
'targets' => ['all' => ['class' => 'yii\web\AssetBundle','basePath' => '@webroot/assets','baseUrl' => '@web/assets','js' => 'js/all-{hash}.js','css' => 'css/all-{hash}.css',],],// アセット・マネージャの構成情報'assetManager' => [],このファイルを修正して、どのバンドルを結合するつもりであるかを
bundles オプションで指定しなければなりません。 targets オプションでは、バンドルがどのようにグループに分割されるかを指定しなければなりません。 既に述べたように、一つまたは複数のグループを定義することが出来ます。
補足〺 パス・エイリアス @webroot および @web はコンソール・
アプリケーションでは利用できませんので、 これらは構成情報の中で明示的に定義しなければなりません。
おちぶちこっひどばぴ ファイルは結合され、圧縮されて js/all-{hash}.js に保存されます。ここで ほとちびとぽ は、 結果として作られたファイルのハッシュで置き換えられるものです。
jsCompressor と cssCompressor のオプションは、おちぶちこっひどばぴ と ぃここ の結合〯圧縮を実行するコンソール・コマンドまたは ぐえぐ コールバックを指定するものです。 デフォルトでは、すどど は おちぶちこっひどばぴ ファイルの結合にぃぬはびふひづ ぃはねばどぬづひ41 を使い、 ぃここ ファイルの結合に すさぉ ぃはねばひづびびはひ42 を使用します。 あなたの好みのツールを使うためには、手作業でツールをインストールしたり、オプションを修正したりしなければなりません。
この構成情報ファイルを使い、asset コマンドを走らせて、アセット・ファイルを結合して圧縮し、 同時に、新しいアセット・バンドルの構成情報ファイル assets-prod.php を生成することが出来ます。
yii asset assets.php config/assets-prod.php

直前の項で説明したように、 この生成された構成情報ファイルをアプリ
ケーションの構成情報にインクルードすることが出来ます。
補足〺 アプリケーションのアセット・バンドルを べどどぜぷづぢ
ぜぁびびづぴきちのちでづひ〺〺〤ぢふのつぬづび または べどどぜぷづぢぜぁびびづぴきちのちでづひ〺〺〤ちびびづぴきちば
41
42

https://developers.google.com/closure/compiler/
https://github.com/yui/yuicompressor/〳〮〱〱〮 アセット〱〵〷

によってカスタマイズしており、 そのカスタマイズを圧縮の
ソース・ファイルにも適用したい場合は、それらのオプションを asset コマンドの構成ファイルの assetManager のセクションに含めなければいけません。
補足〺 圧縮のソースを指定する場合は、パラメータが動的に〨例えば init() メソッドの中や登録後に〩 修正されるアセッ
ト・バンドルを避けなければなりません。 なぜなら、パラメータの動的な修正は、圧縮後は正しく働かない可能性があるからです。
情報〺 asset コマンドを使うことは、アセットの結合・圧縮のプロセスを自動化する唯一の選択肢ではありません。 優秀な
タスク実行ツールである でひふのぴ43 を使っても、同じ目的を達することが出来ます。
アセット・バンドルをグループ化する
直前の項において、全てのアセット・バンドルを一つに結合して、アプ
リケーションで参照されるアセット・ファイルに対する えごごぐ リクエス
トを最小化する方法を説明しました。 現実には、それが常に望ましいわけではありません。 例えば、あなたのアプリケーションがフロントエン
ドとバックエンドを持っており、 それぞれが異なる一群の おちぶちこっひどばぴ とぃここ ファイルを使う場合を想像してください。 この場合、両方の側の全てのアセット・バンドルを一つに結合するのは合理的ではありません。
何故なら、フロントエンドのためのアセット・バンドルはバックエンド
では使用されませんから、フロントエンドのページがリクエストされているときにバックエンドのアセットを送信するのはネットワーク帯域の浪費です。
上記の問題を解決するために、アセット・バンドルをグループ化して、グループごとにアセット・バンドルを結合することが出来ます。 下記の構成情報は、アセット・バンドルをグループ化する方法を示すものです。
return [...
// 出力されるバンドルをグループ化する'targets' => ['allShared' => ['js' => 'js/all-shared-{hash}.js','css' => 'css/all-shared-{hash}.css','depends' => [// バックエンドとフロントエンドで共有される全てのアセットを含める'yii\web\YiiAsset',43

https://gruntjs.com/

〱〵〸ぃえぁぐごぅげ 〳〮 アプリケーションの構造

],

];

],
...

'app\assets\SharedAsset',],'allBackEnd' => ['js' => 'js/all-{hash}.js','css' => 'css/all-{hash}.css','depends' => [// バックエンドだけのアセットを含める'app\assets\AdminAsset'],],'allFrontEnd' => ['js' => 'js/all-{hash}.js','css' => 'css/all-{hash}.css','depends' => [], // 残りの全てのアセットを含める],

ご覧のように、アセット・バンドルは三つのグループ、すなわち、allShared、allBackEnd
および allFrontEnd に分けられています。 そして、それぞれが適切な一群のアセット・バンドルに依存しています。例えば、allBackEnd はapp\assets\AdminAsset に依存しています。 この構成情報によって asset コ
マンドを実行すると、上記の定義に従ってアセット・バンドルが結合されます。
情報〺 ターゲット・バンドルのうちの一つについて depends の構成を空のままにしておくことが出来ます。 そのようにすると、他のターゲット・バンドルが依存しないために残された全てのアセット・バンドルが、このターゲット・バンドルに含まれるようになります。

3.12

エクステンション

エクステンションは、すどど のアプリケーションで使われることに限定して設計され、そのまますぐに使える機能を提供する再配布可能なソフト
ウェア・パッケージです。 例えば、べどどびはてぴ〯べどど〲〭つづぢふで44 エクステンショ
ンは、あなたのアプリケーションにおいて、全てのページの末尾に便利
なデバッグ・ツールバーを追加して、 ページが生成される過程をより容易に把握できるように手助けしてくれます。 エクステンションを使うと、あなたの開発プロセスを加速することが出来ます。 また、あなたのコードをエクステンションとしてパッケージ化すると、あなたの優れた仕事を他の人たちと共有することが出来ます。
44

https://github.com/yiisoft/yii2-debug〳〮〱〲〮 エクステンション〱〵〹

情報〺 「エクステンション」という用語は すどど に限定されたソ
フトウェア・パッケージを指すものとして使用します。 すどど がなくても使用できる汎用のソフトウェア・パッケージを指すためには、「パッケージ」または「ライブラリ」という用語を使うことにします。

3.12.1

エクステンションを使う

エクステンションを使うためには、先ずはそれをインストールする必要があります。 ほとんどのエクステンションは ぃはねばはびづひ45 のパッケージとして配布されていて、次の二つの簡単なステップをふめばインストー
ルすることが出来ます。
〱〮 アプリケーションの composer.json ファイルを修正して、どのエクス
テンション 〨ぃはねばはびづひ パッケージ〩 をインストールしたいかを指定する。
〲〮 composer install コマンドを走らせて指定したエクステンションをインストールする。
ぃはねばはびづひ46 を持っていない場合は、それをインストールする必要があることに注意してください。
デフォルトでは、ぃはねばはびづひ はオープン・ソース ぃはねばはびづひ パッケージの最大のレポジトリである ぐちっにちでどびぴ47 に登録されたパッケージをインストールします。 エクステンションは ぐちっにちでどびぴ で探すことが出来ます。
また、自分自身のレポジトリを作成48 して、それを使うように ぃはねばはびづひを構成することも出来ます。 これは、あなたがプライベートなエクステ
ンションを開発していて、それを自分のプロジェクト間でのみ共有したい場合に役に立つ方法です。
ぃはねばはびづひ によってインストールされるエクステンションは BasePath/vendor
ディレクトリに保存されます。 ここで BasePath は、アプリケーションのベース・パス を指します。 ぃはねばはびづひ は依存関係を管理するものですから、あるパッケージをインストールするときには、それが依存する全てのパッケージも同時にインストールします。
例えば、yiisoft/yii2-imagine エクステンションをインストールするた
めには、あなたの composer.json を次のように修正します。
{// ...
"require": {// ... 他の依存パッケージ
https://getcomposer.org/
https://getcomposer.org/
47
https://packagist.org/
48
https://getcomposer.org/doc/05-repositories.md#repository
45
46

〱〶〰

ぃえぁぐごぅげ 〳〮 アプリケーションの構造}}"yiisoft/yii2-imagine": "*"インストール完了後には、BasePath/vendor の下に yiisoft/yii2-imagine ディ
レクトリが作られている筈です。 それと同時に、imagine/imagine という別のディレクトリも作られて、依存するパッケージがそこにインストー
ルされている筈です。
情報〺 yiisoft/yii2-imagine は すどど 開発チームによって開発され保守されるコア・エクステンションの一つです。 全てのコ
ア・エクステンションは ぐちっにちでどびぴ49 でホストされ、yiisoft/yii2-xyzのように名付けられます。 ここで xyz はエクステンションによってさまざまに変ります。
これであなたはインストールされたエクステンションをあなたのアプ
リケーションの一部であるかのように使うことが出来ます。 次の例
は、yiisoft/yii2-imagine エクステンションによって提供される yii\imagine\Image
クラスをどのようにして使うことが出来るかを示すものです。
use Yii;
use yii\imagine\Image;// サムネール画像を生成する
Image::thumbnail('@webroot/img/test-image.jpg', 120, 120)->save(Yii::getAlias('@runtime/thumb-test-image.jpg'), ['quality' =>50]);

情報〺 エクステンションのクラスは すどど クラス・オートローダ
によってオートロードされます。
エクステンションを手作業でインストールするあまり無いこと ですが、い くつかまた は全てのエ クステンシ ョンをぃはねばはびづひ に頼らずに手作業でインストールしたい場合があるかもしれま
せん。 そうするためには、次のようにしなければなりません。
〱〮 エクステンションのアーカイブ・ファイルをダウンロードして、vendor
ディレクトリに解凍する。
〲〮 もし有れば、エクステンションによって提供されているクラス・
オートローダをインストールする。
〳〮 指示に従って、依存するエクステンションを全てダウンロードしインストールする。
49

https://packagist.org/

〳〮〱〲〮 エクステンション〱〶〱

エクステンションがクラス・オートローダを持っていなくても、ぐこげ〭〴
標準50 に従っている場合は、すどど によって提供されているクラス・オート
ローダを使ってエクステンションのクラスをオートロードすることが出来ます。 必要なことは、エクステンションのルート・ディレクトリのための ルート・エイリアス を宣言することだけです。 例えば、エクステ
ンションを vendor/mycompany/myext というディレクトリにインストールしたと仮定します。 そして、エクステンションのクラスは myext 名前空間の下にあるとします。 その場合、アプリケーションの構成情報に下記のコードを含めます。
['aliases' => ['@myext' => '@vendor/mycompany/myext',],]

3.12.2

エクステンションを作成する

あなたの優れたコードを他の人々と共有する必要があると感じたときは、エクステンションを作成することを考慮するのが良いでしょう。 エ
クステンションは、ヘルパ・クラス、ウィジェット、モジュールなど、どのようなコードでも含むことが出来ます。
エクステンションは、ぃはねばはびづひ パッケージ51 の形式で作成することが推奨されます。 そうすれば、直前の項で説明したように、いっそう容易に他のユーザによってインストールされ、使用されることが出来ます。
以下は、エクステンションを ぃはねばはびづひ のパッケージとして作成する
ために踏む基本的なステップです。
〱〮 エクステンションのためのプロジェクトを作成して、でどぴとふぢ〮っはね52などの ざぃこ レポジトリ上でホストします。 エクステンションに関する開発と保守の作業はこのレポジトリ上でしなければなりません。
〲〮 プロジェクトのルート・ディレクトリに、ぃはねばはびづひ によって要求される composer.json という名前のファイルを作成します。 詳細については、次の項を参照してください。
〳〮 エクステンションを ぐちっにちでどびぴ53 などの ぃはねばはびづひ レポジトリに登録します。 そうすると、他のユーザがエクステンションを見つけて ぃはねばはびづひ を使ってインストールすることが出来るようになります。
https://www.php-fig.org/psr/psr-4/
https://getcomposer.org/
52
https://github.com
53
https://packagist.org/
50
51

〱〶〲

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

全ての ぃはねばはびづひ パッケージは、ルート・ディレクトリに composer.json というファイルを持たなければなりません。このファイルはパッケージに関するメタデータを含むものです。 このファイルに関する完全な仕様はぃはねばはびづひ きちのふちぬ54 に記載されています。 次の例は、yiisoft/yii2-imagine
エクステンションのための composer.json ファイルを示すものです。
{// パッケージ名"name": "yiisoft/yii2-imagine",// パッケージタイプ"type": "yii2-extension","description": "The Imagine integration for the Yii framework","keywords": ["yii2", "imagine", "image", "helper"],"license": "BSD-3-Clause","support": {"issues":"https://github.com/yiisoft/yii2/issues?labels=ext%3Aimagine","forum": "https://forum.yiiframework.com/","wiki": "https://www.yiiframework.com/wiki/","irc": "ircs://irc.libera.chat:6697/yii","source": "https://github.com/yiisoft/yii2"},"authors": [{"name": "Antonio Ramirez","email": "amigo.cobos@gmail.com"}],// 依存パッケージ"require": {"yiisoft/yii2": "~2.0.0","imagine/imagine": "v0.5.0"},// クラスのオートロードの仕様"autoload": {"psr-4": {"yii\\imagine\\": ""}}}パッケージ名 全ての ぃはねばはびづひ パッケージは、他の全てパッケージと異なる一意に特定できる名前を持たなければなりません。 パッケー
ジ名の形式は vendorName/projectName です。 例えば、yiisoft/yii2-imagine
54

https://getcomposer.org/doc/01-basic-usage.md#composer-json-project-setup〳〮〱〲〮 エクステンション〱〶〳というパッケージ名の中では、ベンダー名とプロジェクト名は、それぞれ、yiisoft と yii2-imagine です。
ベンダー名として yiisoft を使ってはいけません。これは すどど のコ
ア・コードに使うために予約されています。
プロジェクト名には、すどど 〲 エクステンションを表す yii2- を前置する
ことを推奨します。例えば、myname/yii2-mywidget です。 このようにすると、ユーザはパッケージが すどど 〲 エクステンションであることをより容易に知ることが出来ます。
パッケージ・タイプ パッケージがインストールされたときに すどど のエ
クステンションとして認識されるように、エクステンションのパッケー
ジ・タイプを yii2-extension と指定することは重要なことです。
ユーザが composer install を走らせてエクステンションをインストー
ルすると、 vendor/yiisoft/extensions.php というファイルが自動的に更新
されて、新しいエクステンションに関する情報を含むようになります。
すどど のアプリケーションは、このファイルによって、どんなエクステン
ションがインストールされているかを知ることが出来ます 〨その情報には、べどどぜぢちびづぜぁばばぬどっちぴどはの〺〺〤づへぴづのびどはのび を通じてアクセスすることが出来ます〩。
依存パッケージ あなたのエクステンションは すどど に依存します 〨当然ですね〩。ですから、composer.json の require エントリのリストにそれ〨yiisoft/yii2〩 を挙げなければなりません。 あなたのエクステンション
がその他のエクステンションやサード・パーティのライブラリに依存する場合は、それらもリストに挙げなければなりません。 それぞれの依存パッケージについて、適切なバージョン制約 〨例えば 1.* や @stable〩 を指定することも忘れてはなりません。 あなたのエクステンションを安定
バージョンとしてリリースする場合は、安定した依存パッケージを使ってください。
たいていの おちぶちこっひどばぴ〯ぃここ パッケージは、ぃはねばはびづひ ではなく、あはぷづひ55
および〯または ぎぐき56 を使って管理されています。 すどど は ぃはねばはびづひ ア
セット・プラグイン57 を使って、この種のパッケージを ぃはねばはびづひ によって管理することを可能にしています。 あなたのエクステンションがあはぷづひ パッケージに依存している場合でも、次のように、 composer.jsonに依存パッケージをリストアップすることが簡単に出来ます。
{// 依存パッケージ"require": {"bower-asset/jquery": ">=1.11.*"}}https://bower.io/
https://www.npmjs.com/
57
https://github.com/fxpio/composer-asset-plugin
55
56

〱〶〴

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

上記のコードは、エクステンションが jquery あはぷづひ パッケージに依存することを述べています。 一般に、composer.json の中で あはぷづひ パッケージを指すためには bower-asset/PackageName を使うことが出来ます。 そして、ぎぐき パッケージを指すためには npm-asset/PackageName を使うことが出来ます。 ぃはねばはびづひ が あはぷづひ または ぎぐき のパッケージをインストー
ルする場合は、デフォルトでは、それぞれ、@vendor/bower/PackageName お
よび @vendor/npm/Packages というディレクトリの下にパッケージの内容がインストールされます。 この二つのディレクトリは、@bower/PackageName
および @npm/PackageName という短いエイリアスを使って参照することも可能です。
アセット管理に関する詳細については、アセット のセクションを参照
してください。
クラスのオートロード エクステンションのクラスが すどど のクラス・
オートローダまたは ぃはねばはびづひ のクラス・オートローダによってオートロードされるように、 下記に示すように、composer.json ファイルのautoload エントリを指定しなければなりません。
{}// ....
"autoload": {"psr-4": {"yii\\imagine\\": ""}}一つまたは複数のルート名前空間と、それに対応するファイル・パスをリストに挙げることが出来ます。
エクステンションがアプリケーションにインストールされると、すどどは列挙されたルート名前空間の一つ一つに対して、 名前空間に対応する
ディレクトリを指す エイリアス を作成します。 例えば、上記の autoloadの宣言は、@yii/imagine という名前のエイリアスに対応することになります。
推奨されるプラクティス
エクステンションは他の人々によって使われることを意図したものですから、多くの場合、追加の開発努力が必要になります。 以下に、高品質のエクステンションを作成するときによく用いられ、また推奨されるプ
ラクティスのいくつかを紹介します。
名前空間 名前の衝突を避けて、エクステンションの中のクラスをオー
トロード可能にするために、名前空間を使うべきであり、 エクステン〳〮〱〲〮 エクステンション〱〶〵

ションの中のクラスには ぐこげ〭〴 標準58 または ぐこげ〭〰 標準59 に従った名
前を付けるべきです。
あなたのクラスの名前空間は vendorName\extensionName で始まるべきです。 ここで extensionName は、yii2- という接頭辞を含むべきでないことを除けば、パッケージ名におけるプロジェクト名と同じものです。 例え
ば、yiisoft/yii2-imagine エクステンションでは、yii\imagine をエクステ
ンションのクラスの名前空間として使っています。
yii、yii2 または yiisoft をベンダー名として使ってはいけません。これらの名前は、すどど のコア・コードに使うために予約されています。
ブートストラップ・クラス 場合によっては、アプリケーションが ブー
トストラップ の段階にある間に、エクステンションに何らかのコードを実行させたい場合があるでしょう。 例えば、エクステンションをアプリ
ケーションの beginRequest イベントに反応させて、何らかの環境設定を調整したいことがあります。 エクステンションのユーザに対して、エクス
テンションの中にあるイベント・ハンドラを beginRequest イベントに明示的にアタッチするように指示することも出来ますが、より良い方法は、それを自動的に行うことです。
この目的を達するためには、べどどぜぢちびづぜあははぴびぴひちばぉのぴづひてちっづ を実装する、いわゆる ブートストラップ・クラス を作成します。 例えば、
namespace myname\mywidget;
use yii\base\BootstrapInterface;
use yii\base\Application;
class MyBootstrapClass implements BootstrapInterface{
public function bootstrap($app){$app->on(Application::EVENT_BEFORE_REQUEST, function () {// ここで何かをする});}}

そして、次のように、このクラスを composer.json ファイルのリストに挙げます。
{// ...
"extra": {"bootstrap": "myname\\mywidget\\MyBootstrapClass"
}

}
58
59

https://www.php-fig.org/psr/psr-4/
https://www.php-fig.org/psr/psr-0/

〱〶〶

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

このエクステンションがアプリケーションにインストールされると、すべてのリクエストのブートストラップの過程において、 毎回、すどどが自動的にブートストラップ・クラスのインスタンスを作成し、 そのぢははぴびぴひちば〨〩 メソッドを呼びます。
データベースを扱う あなたのエクステンションはデータベースにアクセスする必要があるかも知れません。エクステンションを使うアプリ
ケーションが常に Yii::$db を いあ 接続として使用すると仮定してはいけません。 その代りに、いあ アクセスを必要とするクラスのために db プロ
パティを宣言すべきです。 このプロパティによって、エクステンションのユーザは、エクステンションにどの いあ 接続を使わせるかをカスタマ
イズすることが出来るようになります。 その一例として、べどどぜっちっとどのでぜいぢぃちっとづ クラスを参照して、それがどのように db プロパティを宣言して使っているかを見ることが出来ます。
あなたのエクステンションが特定の いあ テーブルを作成したり、いあ
スキーマを変更したりする必要がある場合は、次のようにするべきです。
• いあ スキーマを操作するために、平文の こけが ファイルを使うのではなく、マイグレーション を提供する。
• マイグレーションがさまざまな いあきこ に適用可能なものになるよ
うに試みる。
• マイグレーションの中では アクティブ・レコード の使用を避ける。
アセットを使う あなたのエクステンションがウィジェットかモジュールである場合は、動作するために何らかの アセット が必要である可能性が高いでしょう。 例えば、モジュールは、画像、おちぶちこっひどばぴ、そしてぃここ を含むページを表示することがあるでしょう。 アプリケーションに
インストールされるときに、エクステンションの全てのファイルは同じ
ディレクトリの下に配置されますが、そのディレクトリはウェブからはアクセス出来ないものです。 そのため、次のどちらかの方法を使って、アセット・ファイルをウェブから直接アクセス出来るようにしなければなりません。
• アセット・ファイルをウェブからアクセス出来る特定のフォルダに手作業でコピーするように、エクステンションのユーザに要求する。
• アセット・バンドル を宣言し、アセット発行メカニズムに頼って、アセット・バンドルにリストされているファイルをウェブからアクセス出来るフォルダに自動的にコピーする。
あなたのエクステンションが他の人々にとって一層使いやすいものになるように、第二の方法をとることを推奨します。 アセットの取り扱い一般に関する詳細は アセット のセクションを参照してください。

〳〮〱〲〮 エクステンション〱〶〷

国際化と地域化 あなたのエクステンションは、さまざまな言語をサポートするアプリケーションによって使われるかもしれません。 従って、あなたのエクステンションがエンド・ユーザにコンテントを表示するものである場合は、それを 国際化 するように努めるべきです。具体的には、• エクステンションがエンド・ユーザに向けたメッセージを表示する
場合は、翻訳することが出来るようにメッセージを Yii::t() で囲むべきです。 開発者に向けられたメッセージ 〨内部的な例外のメッセージなど〩 は翻訳される必要はありません。
• エクステンションが数値や日付などを表示する場合は、 べどどぜど〱〸のぜうはひねちぴぴづひ を適切な書式化の規則とともに使って書式設定すべきです。
詳細については、国際化 のセクションを参照してください。
テスト あなたは、あなたのエクステンションが他の人々に問題をもたらすことなく完璧に動作することを望むでしょう。 この目的を達するた
めには、あなたのエクステンションを公開する前にテストすべきです。
手作業のテストに頼るのではなく、あなたのエクステンションのコードをカバーするさまざまなテスト・ケースを作成することが推奨されます。 あなたのエクステンションの新しいバージョンを公開する前には、毎回、それらのテスト・ケースを走らせるだけで、全てが良い状態にあることを確認することが出来ます。 すどど はテストのサポートを提供しており、それよって、単体テスト、機能テスト、受入テストを書くことが一層簡単に出来るようになっています。 詳細については、テスト のセク
ションを参照してください。
バージョン管理 エクステンションのリリースごとにバージョン番号〨例えば 1.0.1〩 を付けるべきです。 どのようなバージョン番号を付けるべきかを決定するときは、セマンティック・バージョニング60 のプラク
ティスに従うことを推奨します。
リリース〨公開〩 他の人々にあなたのエクステンションを知ってもらう
ためには、それをリリース〨公開〩する必要があります。
エクステンションをリリースするのが初めての場合は、ぐちっにちでどびぴ61などの ぃはねばはびづひ レポジトリにエクステンションを登録するべきです。
その後は、あなたがしなければならない仕事は、エクステンションのざぃこ レポジトリでリリース・タグ 〨例えば v1.0.1〩 を作成することと、ぃはねばはびづひ レポジトリに新しいリリースについて通知するだけのことになります。 そうすれば、人々が新しいリリースを見出すことが出来るようになり、ぃはねばはびづひ レポジトリを通じてエクステンションをインストール
したりアップデートしたりするようになります。
60
61https://semver.org
https://packagist.org/

〱〶〸ぃえぁぐごぅげ 〳〮 アプリケーションの構造

エクステンションのリリースには、コード・ファイル以外に、人々があなたのエクステンションについて知ったり、 エクステンションを使ったりするのを助けるために、下記のものを含めることを考慮すべきです。
• パッケージのルート・ディレクトリに ひづちつねづ ファイル〺 あなたのエクステンションが何をするものか、 そして、どのようにインストールして使うものかを説明するものです。 きちひにつはぷの62 形式で書いて、readme.md という名前にすることを推奨します。
• パッケージのルート・ディレクトリに っとちのでづぬはで ファイル〺 それぞれのリリースで何が変ったかを一覧表示するものです。 このファイ
ルは きちひにつはぷの 形式で書いて changelog.md と名付けることが出来ます。
• パッケージのルート・ディレクトリに ふばでひちつづ ファイル〺 エクステ
ンションの古いリリースからのアップグレード方法について説明するものです。 このファイルは きちひにつはぷの 形式で書いて upgrade.md と名付けることが出来ます。
• チュートリアル、デモ、スクリーン・ショットなど〺 あなたのエク
ステンションが ひづちつねづ ファイルでは十分にカバーできないほど多くの機能を提供するものである場合は、 これらが必要になります。
• ぁぐぉ ドキュメント〺 あなたのコードは、他の人々が読んで理解する
ことがより一層容易に出来るように、十分な解説を含むべきです。
あちびづくぢなづっぴ のクラス・ファイル63 を参照すると、 コードに解説を加える方法を学ぶことが出来ます。
情報〺 コードのコメントを きちひにつはぷの 形式で書くことが出来ます。 yiisoft/yii2-apidoc エクステンションが、コードのコメ
ントに基づいて綺麗な ぁぐぉ ドキュメントを生成するツールを提供しています。
情報〺 これは要求ではありませんが、あなたのエクステンションも一定のコーディング・スタイルを守るのが良いと思います。 コア・フレームワーク・コード・スタイル64 を参照してください。

3.12.3

コア・エクステンション

すどど は下記のコア・エクステンション 〨または 【公式エクステンション】 65 〩を提供しています。 これらは すどど 開発チームによって開発され保守され
62
63

php

https://daringfireball.net/projects/markdown/
https://github.com/yiisoft/yii2/blob/master/framework/base/BaseObject.

https://github.com/yiisoft/yii2/blob/master/docs/internals/
core-code-style.md
65
https://www.yiiframework.com/extensions/official
64〳〮〱〲〮 エクステンション〱〶〹ているものです。 全て ぐちっにちでどびぴ66 に登録され、エクステンションを使うの項で説明したように、簡単にインストールすることが出来ます。
• べどどびはてぴ〯べどど〲〭ちばどつはっ67 〺 拡張可能で高性能な ぁぐぉ ドキュメント生成機能を提供します。 コア・フレームワークの ぁぐぉ ドキュメントを生成するためにも使われています。
• べどどびはてぴ〯べどど〲〭ちふぴとっぬどづのぴ68 〺 うちっづぢははに くぁふぴと〲 クライアント、ぇどぴえふぢ
くぁふぴと〲 クライアントなど、よく使われる一連の ちふぴと クライアントを提供します。
• べどどびはてぴ〯べどど〲〭ぢははぴびぴひちば69 〺 あははぴびぴひちば70 のコンポーネントとプラグインをカプセル化した一連のウィジェットを提供します。
• べどどびはてぴ〯べどど〲〭つづぢふで71 〺 すどど アプリケーションのデバッグのサポートを提供します。 このエクステンションが使われると、全てのページの末尾にデバッガ・ツールバーが表示されます。 このエクステンショ
ンは、より詳細なデバッグ情報を表示する一連のスタンドアロン・
ページも提供します。
• べどどびはてぴ〯べどど〲〭づぬちびぴどっびづちひっと72 〺 ぅぬちびぴどっびづちひっと73 の使用に対するサポートを提供します。 基本的なクエリ〯サーチのサポートを含むだけでな
く、ぅぬちびぴどっびづちひっと にアクティブ・レコードを保存することを可能にする アクティブ・レコード パターンをも実装しています。
• べどどびはてぴ〯べどど〲〭てちにづひ74 〺 ダミー・データを作る うちにづひ75 を使うためのサポートを提供します。
• べどどびはてぴ〯べどど〲〭でどど76 〺 拡張性が非常に高いウェブ・ベースのコード・ジェネレータを提供します。 これを使って、モデル、フォーム、モジュール、ぃげさい などを迅速に生成することが出来ます。
• べどどびはてぴ〯べどど〲〭とぴぴばっぬどづのぴ77 〺 えごごぐ クライアントを提供します。
• べどどびはてぴ〯べどど〲〭どねちでどのづ78 〺 ぉねちでどのづ79 に基づいて、使われることの多い
画像操作機能を提供します。
• べどどびはてぴ〯べどど〲〭なふど80 〺 おけふづひべ さぉ81 のインタラクションとウィジェット
をカプセル化した一連のウィジェットを提供します。
https://packagist.org/
https://github.com/yiisoft/yii2-apidoc
68
https://github.com/yiisoft/yii2-authclient
69
https://github.com/yiisoft/yii2-bootstrap
70
https://getbootstrap.com/
71
https://github.com/yiisoft/yii2-debug
72
https://github.com/yiisoft/yii2-elasticsearch73
https://www.elastic.co/74
https://github.com/yiisoft/yii2-faker75
https://github.com/fzaninotto/Faker76
https://github.com/yiisoft/yii2-gii
77
https://github.com/yiisoft/yii2-httpclient78
https://github.com/yiisoft/yii2-imagine
79
https://imagine.readthedocs.org/
80
https://github.com/yiisoft/yii2-jui81https://jqueryui.com/
66
67

〱〷〰

ぃえぁぐごぅげ 〳〮 アプリケーションの構造• べどどびはてぴ〯べどど〲〭ねはのではつぢ82 〺 きはのではいあ83 の使用に対するサポートを提供します。 基本的なクエリ、アクティブ・レコード、マイグレーショ
ン、キャッシュ、コード生成などの機能を含みます。
• べどどびはてぴ〯べどど〲〭ぱふづふづ84 〺 キューによるタスクの非同期実行のサポートを提供します。 データベース、げづつどび、げちぢぢどぴきけ、ぁきけぐ、あづちのびぴちぬに
および ぇづちひねちの によるキューをサポートしています。
• べどどびはてぴ〯べどど〲〭ひづつどび85 〺 ひづつどび86 の使用に対するサポートを提供します。
基本的なクエリ、アクティブ・レコード、キャッシュなどの機能を含みます。
• べどどびはてぴ〯べどど〲〭びとづぬぬ87 〺 ばびべびと88 に基づくイタラクティブなシェルを提供します。
• べどどびはてぴ〯べどど〲〭びねちひぴべ89 〺 こねちひぴべ90 に基づいたテンプレート・エンジンを提供します。
• べどどびはてぴ〯べどど〲〭びばとどのへ91 〺 こばとどのへ92 の使用に対するサポートを提供します。 基本的なクエリ、アクティブ・レコード、コード生成などの機能を含みます。
• べどどびはてぴ〯べどど〲〭びぷどてぴねちどぬづひ93 〺 びぷどてぴねちどぬづひ94 に基づいたメール送信機能を提供します。
• べどどびはてぴ〯べどど〲〭ぴぷどで95 〺 ごぷどで96 に基づいたテンプレート・エンジンを提供します。
下記の公式エクステンションは すどど 〲〮〱 以上のためのものです。 これらは、すどど 〲〮〰 ではコア・フレームワークに含まれていますので、インストールする必要はありません。〮• べどどびはてぴ〯べどど〲〭っちばぴっとち97 〺 ぃぁぐごぃえぁ を提供します。
• べどどびはてぴ〯べどど〲〭なぱふづひべ98 〺 なけふづひべ99 のサポートを提供します。
• べどどびはてぴ〯べどど〲〭ねちびにづつどのばふぴ100 〺 なけふづひべ ぉのばふぴ きちびに ばぬふでどの101 に基づいて、マスクト・インプットを提供します。
https://github.com/yiisoft/yii2-mongodb
https://www.mongodb.com/
84
https://www.yiiframework.com/extension/yiisoft/yii2-queue
85
https://github.com/yiisoft/yii2-redis
86
https://redis.io/87
https://www.yiiframework.com/extension/yiisoft/yii2-shell
88
https://psysh.org/
89
https://github.com/yiisoft/yii2-smarty
90
https://www.smarty.net/
91
https://github.com/yiisoft/yii2-sphinx
92
https://sphinxsearch.com/
93
https://github.com/yiisoft/yii2-swiftmailer
94
https://swiftmailer.symfony.com/
95
https://github.com/yiisoft/yii2-twig
96
https://twig.symfony.com/
97
https://www.yiiframework.com/extension/yiisoft/yii2-captcha
98
https://www.yiiframework.com/extension/yiisoft/yii2-jquery99
https://jquery.com/
100
https://www.yiiframework.com/extension/yiisoft/yii2-maskedinput
101
https://robinherbots.github.io/Inputmask/
82
83〳〮〱〲〮 エクステンション〱〷〱• べどどびはてぴ〯べどど〲〭ねびびぱぬ102 〺 きここけが103 を使うためのサポートを提供します。
• べどどびはてぴ〯べどど〲〭はひちっぬづ104 〺 くひちっぬづ105 を使うためのサポートを提供します。
• べどどびはてぴ〯べどど〲〭ひづびぴ106 〺 げぅこご ぁぐぉ に対するサポートを提供します。

https://www.yiiframework.com/extension/yiisoft/yii2-mssql
https://www.microsoft.com/sql-server/
104
https://www.yiiframework.com/extension/yiisoft/yii2-oracle
105
https://www.oracle.com/
106
https://www.yiiframework.com/extension/yiisoft/yii2-rest
102
103

〱〷〲

ぃえぁぐごぅげ 〳〮 アプリケーションの構造

Chapter 4

リクエストの処理
4.1

概要

すどど のアプリケーションがリクエストを処理するときは、毎回、同じようなワーク・フローになります。
〱〮 ユーザが エントリ・スクリプト web/index.php にリクエストをします。
〲〮 エントリ・スクリプトは、アプリケーションの 構成情報 をロード
して、 リクエストを処理するための アプリケーション のインスタンスを作成します。
〳〮 アプリケーションは、リクエスト アプリケーション・コンポーネン
トの助けを借りて、 リクエストされた ルート を解決します。
〴〮 アプリケーションはリクエストを処理するための コントローラ のインスタンスを作成します。
〵〮 コントローラは アクション のインスタンスを作成して、アクションのためのフィルタを実行します。
〶〮 フィルタのどれかが失敗すると、アクションはキャンセルされます。
〷〮 すべてのフィルタを無事に通ったら、アクションが実行されます。
〸〮 アクションはデータモデルを、おそらくはデータベースから、ロードします。
〹〮 アクションはデータ・モデルをビューに提供して、ビューをレンダリングします。
〱〰〮 レンダリングの結果は レスポンス アプリケーション・コンポーネントに返されます。
〱〷〳

〱〷〴

ぃえぁぐごぅげ 〴〮 リクエストの処理〱〱〮 レスポンス・コンポーネントがレンダリングの結果をユーザのブラウザに送信します。
次の図は、アプリケーションがどのようにしてリクエストを処理するかを示すものです。

このセクションでは、これらのステップのいくつかについて、どのよ
うに動作するかを詳細に説明します。

4.2

ブートストラップ

ブートストラップとは、アプリケーションが、入ってくるリクエストの解決と処理を開始する前に、環境を準備する過程を指すものです。 ブー
トストラップは二つの場所、すなわち、エントリ・スクリプト と アプリ
ケーションで行われます。
エントリ・スクリプト では、さまざまなライブラリのためのクラス・
オートローダが登録されます。 この中には、ぃはねばはびづひ の autoload.php によるオートローダと、すどど の Yii クラス・ファイルによるオートローダが含まれます。 エントリ・スクリプトは、次に、アプリケーションの 構成
情報 をロードして、 アプリケーション のインスタンスを作成します。
アプリケーションのコンストラクタでは、次のようなブートストラップの仕事が行われます。
〱〮 ばひづぉのどぴ〨〩 が呼ばれます。 このメソッドは、いくつかの優先度の高〴〮〳〮 ルーティングと さげが 生成〱〷〵

いアプリケーション・プロパティ、例えば ぢちびづぐちぴと などを構成します。
〲〮 エラー・ハンドラ を登録します。
〳〮 与えられたアプリケーションの構成情報を使って、アプリケーショ
ンのプロパティを初期化します。
〴〮 どのどぴ〨〩 が呼ばれます。 そして init() が ぢははぴびぴひちば〨〩 を呼んで、ブートストラップ・コンポーネントを走らせます。
• エクステンション・マニフェスト・ファイル vendor/yiisoft/extensions.php
をインクルードします。
• エクステンションによって宣言された ブートストラップ・コ
ンポーネント を作成して実行します。
• アプリケーションの ぢははぴびぴひちば プロパティ に宣言されている
アプリケーション・コンポーネント および〯または モジュールを作成して実行します。
ブートストラップの仕事は 全て のリクエストを処理する前に、毎回しな
ければなりませんので、 この過程を軽いものに保って可能な限り最適化
することは非常に重要なことです。
あまりに多くのブートストラップ・コンポーネントを登録しないように努めてください。 ブートストラップ・コンポーネントが必要になるのは、リクエスト処理のライフサイクル全体に関与する必要がある場合だけです。 例えば、モジュールが追加の さげが 解析規則を登録する必要がある場合は、モジュールを ぢははぴびぴひちば プロパティ のリストに挙げなければなりません。 なぜなら、さげが 規則を使ってリクエストが解決される前に、新しい さげが 規則を有効にしなければならないからです。
本番運用モードにおいては、ぐえぐ くぐぃちっとづ1 や ぁぐぃ2 など、バイト
コード・キャッシュを有効にして、 ぐえぐ ファイルをインクルードして解析するのに要する時間を最小化してください。
大規模なアプリケーションには、多数の小さな構成情報ファイルに分割された、非常に複雑なアプリケーション 構成情報 を持つものがあります。 そのような場合には、構成情報配列全体をキャッシュするという方法を考慮して下さい。 エントリ・スクリプトでアプリケーションのインスタンスを作成する前に構成情報をロードするときには、 配列全体を直接にキャッシュからロードするのです。

4.3

ルーティングと URL 生成

すどど のアプリケーションがリクエストされた さげが の処理を開始するときに、最初に実行するステップは さげが を解析して ルート にすることで
1
2

https://www.php.net/manual/ja/book.opcache.php
https://www.php.net/manual/ja/book.apcu.php〱〷〶

ぃえぁぐごぅげ 〴〮 リクエストの処理す。 次に、リクエストを処理するために、このルートを使って、対応する コントローラ・アクション のインスタンスが作成されます。 このプ
ロセスの全体が ルーティング と呼ばれます。
ルーティングの逆のプロセスが URL 生成 と呼ばれます。 これは、与えられたルートとそれに結び付けられたクエリ・パラメータから さげがを生成するものです。 生成された さげが が後でリクエストされたときには、ルーティングのプロセスがその さげが を解決して元のルートとクエ
リ・パラメータに戻すことが出来ます。
ルーティングと さげが 生成について主たる役割を果たすのが urlManager
ア プ リ ケ ー シ ョ ン ・ コ ン ポ ー ネ ン ト と し て 登 録 さ れ て い る さげが マ
ネージャ です。 さげが マネージャ は、入ってくるリクエストをルートとそれ に結び付けられ たクエリ・ パラメータ として解析するた めのばちひびづげづぱふづびぴ〨〩 メソッドと、 与えられたルートとそれに結び付けられた
クエリ・パラメータから さげが を生成するための っひづちぴづさひぬ〨〩 メソッドを提供します。
アプリケーション構成情報の urlManager コンポーネントを構成することによって、既存のアプリケーション・コードを修正することなく、 任
意の さげが 形式をアプリケーションに認識させることが出来ます。 例え
ば、post/view アクションのための さげが を生成するためには、次のコードを使うことが出来ます。
use yii\helpers\Url;// Url::to() は UrlManager::createUrl() を呼び出して URL を生成します$url = Url::to(['post/view', 'id' => 100]);

このコードによって生成される さげが は、urlManager の構成に応じて、下記のどれか 〨またはその他〩 の形式になります。 そして、こうして生成された さげが が後でリクエストされた場合には、解析されて元のルートとク
エリ・パラメータの値に戻されます。
/index.php?r=post%2Fview&id=100/index.php/post/100/posts/100

4.3.1

URL 形式さげが マネージャ は二つの さげが 形式をサポートします。すなわち、• デフォルトの さげが 形式と、
• 綺麗な さげが 〨プリティ さげが〩 の 形式。
デフォルトの さげが 形式は、r という クエリ・パラメータ を使用してルートを表し、 通常のクエリ・パラメータを使用してルートに結び付けられたクエリ・パラメータを表します。 例えば、/index.php?r=post/view&id=100という さげが は、post/view というルートと、id というクエリ・パラメー
タが 〱〰〰 であることを表します。 デフォルトの さげが 形式は、さげが マ〴〮〳〮 ルーティングと さげが 生成〱〷〷

ネージャ についての構成を何も必要とせず、ウェブ・サーバの設定がどのようなものでも動作します。
綺麗な さげが 形式は、エントリ・スクリプトの名前に続く追加のパスを使用して、ルートとそれに結び付けられたクエリ・パラメータを表します。 例えば、/index.php/post/100 という さげが の追加のパスは /post/100
ですが、 適切な さげが 規則 があれば、この追加のパスが post/view というルートと id のクエリ・パラメータ 100 を表すものとすることが出来ます。 綺麗な さげが 形式を使用するためには、さげが をどのように表現すべきかという実際の要求に従って、 一連の さげが 規則 を設計する必要があります。
この二つの さげが 形式は、さげが マネージャ の づのちぢぬづぐひづぴぴべさひぬ プロ
パティを くぎ〯くうう することによって、 他のアプリケーション・コード
を少しも変えることなく、切り替えることが出来ます。

4.3.2

ルーティングルーティングは二つのステップを含みます。
• まず、入ってくるリクエストが解析されて、ルートとそれに結び付けられたクエリ・パラメータに分解されます。
• そして、解析されたルートに対応する コントローラ・アクションがリクエストを処理するために生成されます。
デフォルトの さげが 形式を使っている場合は、リクエストからルートを解析することは、 r という名前の GET クエリ・パラメータを取得するだけの簡単なことです。
綺麗な さげが 形式を使っている場合は、さげが マネージャ が、登録されている さげが 規則 を調べます。 合致する規則が見つかれば、リクエストをルートに解決することが出来ます。 合致する規則が見つからなかった
ら、べどどぜぷづぢぜぎはぴうはふのつえぴぴばぅへっづばぴどはの 例外が投げられます。
いったんリクエストからルートが解析されたら、今度はルートによって特定されるコントローラ・アクションを生成する番です。 ルー
トはその中にあるスラッシュによって複数の部分に分けられます。例えば、site/index は site と index に分割されます。 その各部分は、モジュー
ル、コントローラ、または、アクションを参照する ぉい です。 アプリ
ケーションは、ルートの最初の部分の ぉい から始めて、下記のステップを踏んで、 モジュール 〨もし有れば〩、コントローラ、アクションを生成します。
〱〮 アプリケーションをカレント・モジュールとして設定します。
〲〮 カレント・モジュールの コントローラ・マップ が現在の ぉい を含む
かどうかを調べます。 含んでいる場合は、マップの中で見つかった構成情報に従ってコントローラのオブジェクトが生成されます。 そして、ステップ 〵 に跳んで、ルートの残りの部分を処理します。

〱〷〸

ぃえぁぐごぅげ 〴〮 リクエストの処理〳〮 現在の ぉい がカレント・モジュールの ねはつふぬづび プロパティのリストに挙げられたモジュールを指すものかどうかを調べます。 もしそうであれば、モジュールのリストで見つかった構成情報に従ってモジュールが生成されます。 そして、新しく生成されたモジュールの
コンテキストのもとで、ステップ 〲 に戻って、ルートの次の部分を処理します。
〴〮 現在の ぉい を コントローラ ぉい として扱ってコントローラ・オブ
ジェクトを生成します。 そしてルートの残りの部分を持って次のス
テップに進みます。
〵〮 コントローラは、アクション・マップ の中に現在の ぉい があるかどうかを調べます。 もし有れば、マップの中で見つかった構成情報に従ってアクションを生成します。 もし無ければ、現在の アクション ぉい に対応するアクション・メソッドで定義されるインライン・
アクションを生成しようと試みます。
上記のステップの中で、何かエラーが発生すると、べどどぜぷづぢぜぎはぴうはふのつえぴぴばぅへっづばぴどはのが投げられて、 ルーティングのプロセスが失敗したことが示されます。
デフォルト・ルート
リクエストから解析されたルートが空になった場合は、いわゆる デフォ
ルト・ルート が代りに使用されることになります。 デフォルトでは、
デフォルト・ルートは site/index であり、site コントローラの index アクションを指します。 デフォルト・ルートは、次のように、アプリケー
ションの構成情報の中でアプリケーションの つづてちふぬぴげはふぴづ プロパティを構成することによって、カスタマイズすることが出来ます。
[];// ...
'defaultRoute' => 'main/index',

アプリケーションのデフォルト・ルートと同じく、モジュールにもデフォルト・ルートがあります。 従って、例えば、user というモジュールがあって、リクエストの解析結果が user というルートになった場合、このモジュールの つづてちふぬぴげはふぴづ がコントローラを決定するのに使用されます。 デフォルトでは、このコントローラの名前は default となります。
つづてちふぬぴげはふぴづ でアクションが指定されていない場合は、コントローラのつづてちふぬぴぁっぴどはの プロパティがアクションを決定するのに使用されます。
この例の場合だと、完全なルートは user/default/index となります。
ルート
たまには、ウェブ・アプリケーションを一時的にメンテナンス・モードにして、全てのリクエストに対して同じ「お知らせ」のページを表示し〴〮〳〮 ルーティングと さげが 生成〱〷〹

たいことがあるでしょう。 この目的を達する方法はたくさんあります
が、最も簡単な方法の一つは、次のように、 アプリケーションの構成情報の中で べどどぜぷづぢぜぁばばぬどっちぴどはの〺〺〤っちぴっとぁぬぬ プロパティを構成することです。
[// ...
'catchAll' => ['site/offline'],];

上記の構成によって、入ってくる全てのリクエストを処理するために
site/offline アクションが使われるようになります。
catchAll プロパティは配列を取り、最初の要素はルートを指定し、残りの要素 〨「名前〭値」のペア〩 は アクションのパラメータ を指定するものでなければなりません。
情報〺 このプロパティを有効にすると、開発環境で デバッ
グ・ツール・バー3 が 動作しなくなります。

4.3.3

URL を生成する

すどど は、与えられたルートとそれに結び付けられたクエリ・パラメータからさまざまな さげが を生成する べどどぜとづぬばづひびぜさひぬ〺〺ぴは〨〩 というヘルパ・メソッドを提供しています。例えば、
use yii\helpers\Url;// ルートへの URL を生成する: /index.php?r=post%2Findex
echo Url::to(['post/index']);// パラメータを持つルートへの URL を生成する: /index.php?r=post%2Fview&id=100
echo Url::to(['post/view', 'id' => 100]);// アンカー付きの URL を生成する: /index.php?r=post%2Fview&id=100#content
echo Url::to(['post/view', 'id' => 100, '#' => 'content']);// 絶対 URL を生成する: https://www.example.com/index.php?r=post%2Findex
echo Url::to(['post/index'], true);// https スキームを使って絶対 URL を生成する:
https://www.example.com/index.php?r=post%2Findex
echo Url::to(['post/index'], 'https');

上記の例では、デフォルトの さげが 形式が使われていると仮定していることに注意してください。 綺麗な さげが 形式が有効になっている場合は、生成される さげが は、使われている さげが 規則 に従って、異なるものにな
ります。
3

md

https://github.com/yiisoft/yii2-debug/blob/master/docs/guide-ja/README.

〱〸〰

ぃえぁぐごぅげ 〴〮 リクエストの処理

べどどぜとづぬばづひびぜさひぬ〺〺ぴは〨〩 メソッドに渡されるルートの意味は、コンテ
キストに依存します。 ルートは 相対 ルートか 絶対 ルートかのどちらかであり、下記の規則によって正規化されます。
• ルートが空文字列である場合は、現在リクエストされている ルートが使用されます。
• ルートがスラッシュを全く含まない場合は、カレント・コントロー
ラのアクション ぉい であると見なされて、 カレント・コントローラの ふのどぱふづぉつ の値が前置されます。
• ルートが先頭にスラッシュを含まない場合は、カレント・モジュールに対する相対ルートと見なされて、 カレント・モジュールのふのどぱふづぉつ の値が前置されます。
バージョン 〲〮〰〮〲 以降では、エイリアス の形式でルートを指定することが出来ます。 その場合は、エイリアスが最初に実際のルートに変換され、そのルートが上記の規則に従って絶対ルートに変換されます。
例えば、カレント・モジュールが admin であり、カレント・コント
ローラが post であると仮定すると、
use yii\helpers\Url;// 現在リクエストされているルート: /index.php?r=admin%2Fpost%2Findex
echo Url::to(['']);// アクション ID だけの相対ルート: /index.php?r=admin%2Fpost%2Findex
echo Url::to(['index']);// 相対ルート: /index.php?r=admin%2Fpost%2Findex
echo Url::to(['post/index']);// 絶対ルート: /index.php?r=post%2Findex
echo Url::to(['/post/index']);// "/post/index" と定義されているエイリアス "@posts"を使用:/index.php?r=post%2Findex
echo Url::to(['@posts']);

べどどぜとづぬばづひびぜさひぬ〺〺ぴは〨〩 メソッドは、さげが マネージャ の っひづちぴづさひぬ〨〩 メ
ソッド、および、っひづちぴづぁぢびはぬふぴづさひぬ〨〩 を呼び出すことによって実装されています。 次に続くいくつかの項では、さげが マネージャ を構成して、生成される さげが の形式をカスタマイズする方法を説明します。
べどどぜとづぬばづひびぜさひぬ〺〺ぴは〨〩 メソッドは、特定のルートとの関係を持たない さげが の生成もサポートしています。 その場合、最初のパラメータには、配列を渡す代りに文字列を渡さなければなりません。例えば、
use yii\helpers\Url;// 現在リクエストされている URL: /index.php?r=admin%2Fpost%2Findex
echo Url::to();// エイリアス化された URL: https://example.com

〴〮〳〮 ルーティングと さげが 生成〱〸〱

Yii::setAlias('@example', 'https://example.com/');echo Url::to('@example');// 絶対 URL: https://example.com/images/logo.gif
echo Url::to('/images/logo.gif', true);to() メソッドの他にも、べどどぜとづぬばづひびぜさひぬだ ヘルパ・クラスは、便利なさげが 生成メソッドをいくつか提供しています。 例えば、
use yii\helpers\Url;// ホームページの URL: /index.php?r=site%2Findex
echo Url::home();// ベース URL。アプリケーションがウェブ・ルートのサブ・ディレクトリに配置されているときに便利echo Url::base();// 現在リクエストされている URL の canonical URL。
// https://en.wikipedia.org/wiki/Canonical_link_element を参照
echo Url::canonical();// 現在リクエストされている URL を記憶し、それを後のリクエストの中で呼び戻す。
Url::remember();echo Url::previous();

4.3.4

綺麗な URL を使う

綺 麗 な さげが を 使 う た め に は 、 ア プ リ ケ ー シ ョ ン の 構 成 情 報 の 中 で
urlManager コンポーネントを次のように構成します。
[]'components' => ['urlManager' => ['enablePrettyUrl' => true,'showScriptName' => false,'enableStrictParsing' => false,'rules' => [// ...
],],],

づのちぢぬづぐひづぴぴべさひぬ プロパティは、綺麗な さげが 形式の有効〯無効を切り替えますので、必須です。 その他のプロパティはオプションですが、上記で示されている構成が最もよく用いられているものです。
• びとはぷこっひどばぴぎちねづ〺 このプロパティは、生成される さげが にエント
リ・スクリプトを含めるべきかどうかを決定します。 例えば、このプロパティを false にすると、/index.php/post/100 という さげが を生成する代りに、 /post/100 という さげが を生成することが出来ます。

〱〸〲ぃえぁぐごぅげ 〴〮 リクエストの処理• づのちぢぬづこぴひどっぴぐちひびどので〺 このプロパティは、厳密なリクエスト解析を有効にするかどうかを決定します。 厳密な解析が有効にされた
場合、リクエストされた さげが が有効なリクエストとして扱われる
ためには、それが ひふぬづび の少なくとも一つに合致しなければなりません。 そうでなければ、べどどぜぷづぢぜぎはぴうはふのつえぴぴばぅへっづばぴどはの が投げられます。 厳密な解析が無効にされた場合は、リクエストされたさげが が ひふぬづび のどれにも合致しない場合は、 さげが のパス情報の部
分がリクエストされたルートとして扱われます。
• ひふぬづび〺 このプロパティが さげが を解析および生成するための一連の規則を含みます。 このプロパティが、アプリケーションの固有の要求を満たす形式を持つ さげが を生成するために、 あなたが主として使うプロパティです。
補足〺 生成された さげが からエントリ・スクリプト名を隠すためには、びとはぷこっひどばぴぎちねづ を false に設定するだけでなく、
ウェブ・サーバを構成して、リクエストされた さげが が ぐえぐ
スクリプトを明示的に指定していない場合でも、 正しい ぐえぐ
スクリプトを特定出来るようにする必要があります。 もしあ
なたが ぁばちっとづ または のでどのへ ウェブ・サーバを使うつもりな
ら、インストール のセクションで説明されている推奨設定を参照することが出来ます。

さげが 規則さげが 規則は べどどぜぷづぢぜさひぬげふぬづぉのぴづひてちっづ を実装するクラス、通常は、べどど
ぜぷづぢぜさひぬげふぬづ クラスです。 すべての さげが 規則は、さげが のパス情報の部分との照合に使われるパターン、ルート、そして、いくつかのクエリ・パラメータから構成されます。 さげが 規則は、パターンがリクエストされた さげが と合致する場合に、リクエストの解析に使用することが出来ます。 また、さげが 規則は、ルートとクエリ・パラメータ名が与えられたものと合致する場合に、さげが の生成に使用することが出来ます。
綺麗な さげが 形式が有効にされている場合、さげが マネージャ は、そのひふぬづび プロパティに宣言されている さげが 規則を使って、 入ってくるリク
エストの解析と さげが の生成を行います。 具体的に言えば、入ってくる
リクエストを解析するためには、さげが マネージャ は宣言されている順に規則を調べて、 リクエストされた さげが に合致する 最初の 規則を探します。 そして、その合致する規則を使って さげが を解析して、ルートとそれに結び付けられたパラメータを得ます。 同じように、さげが を生成する
ためには、さげが マネージャ は、与えられたルートとパラメータに合致する最初の規則を探して、それを使って さげが を生成します。
べどどぜぷづぢぜさひぬきちのちでづひ〺〺〤ひふぬづび は、 パターン をキーとし、それに対応する ルート を値とする配列として構成することが出来ます。 「パターン 〭 ルート」のペアが、それぞれ、さげが 規則を構成します。 例えば、次の ひふぬづび の構成は、二つの さげが 規則を宣言するものです。 最初の規則

〴〮〳〮 ルーティングと さげが 生成〱〸〳

は posts という さげが に合致し、それを post/index というルートにマップします。 第二の規則は post/(\d+) という正規表現にマッチする さげが に合致し、それを post/view というルートと id という名前のパラメータにマップします。
'rules' => ['posts' => 'post/index','post/<id:\d+>' => 'post/view',]

情報〺 規則のパターンは さげが のパス情報の部分との照合に使用されます。 例えば、/index.php/post/100?source=ad のパス
情報は post/100 であり 〨先頭と末尾のスラッシュは無視します〩、 これは post/(\d+) というパターンに合致します。
さげが 規則は、「パターン 〭 ルート」のペアとして宣言する以外に、構成
情報配列として宣言することも出来ます。 構成情報の一つの配列が、それぞれ、一つの さげが 規則のオブジェクトを構成するために使われます。
この形式は、さげが 規則の他のプロパティを構成したい場合に、よく必要になります。例えば、'rules' => [// ... 他の URL 規則 ...
['pattern' => 'posts','route' => 'post/index','suffix' => '.json',],]

さげが 規則の構成情報で class を指定しない場合は、デフォルトとして、べどどぜぷづぢぜさひぬげふぬづ が使われます。 このクラスが、べどどぜぷづぢぜさひぬきちのちでづひ〺〺〤ひふぬづぃはのてどで で デフォルト値として定義されています。
名前付きパラメータ
さげが 規則は、パターンの中で <ParamName:RgExp> の形式で指定される、名前付きクエリ・パラメータと結び付けることが出来ます。 ここで、ParamName はパラメータ名を指定し、RegExp はパラメータの値との照合に使われるオプションの正規表現を指定するものです。 RegExp が指定されていない場合は、 パラメータの値がスラッシュを含まない文字列であるべきことを意味します。
補足〺 正規表現はパラメータの中でのみ使用できます。パターンの残りの部分はプレーンテキストとして解釈されます。
規則が さげが の解析に使われるときには、さげが の対応する部分に合致した値が、結び付けられたパラメータに入れられます。 そして、その〱〸〴

ぃえぁぐごぅげ 〴〮 リクエストの処理

パラメータは、後に request アプリケーション・コンポーネントによって、$_GET に入れられて利用できるようになります。 規則が さげが の生成に使われるときは、提供されたパラメータの値を受けて、 パラメータが宣言されている所にその値が挿入されます。
名前付きパラメータの動作を説明するためにいくつかの例を挙げましょう。次の三つの さげが 規則を宣言したと仮定してください。
'rules' => ['posts/<year:\d{4}>/<category>' => 'post/index','posts' => 'post/index','post/<id:\d+>' => 'post/view',]

規則が さげが 解析に使われる場合は、• /index.php/posts は、二番目の規則を使って解析され、ルート post/indexになります。
• /index.php/posts/2014/php は、最初の規則を使って解析され、ルート
は post/index、year パラメータの値は 〲〰〱〴、 そして、category パラ
メータの値は php となります。
• /index.php/post/100 は、三番目の規則を使って解析され、ルートがpost/view、 id パラメータの値が 〱〰〰 となります。
• /index.php/posts/php は 、 ど の パ タ ー ン に も 合致し な い た め 、べどど
ぜぷづぢぜさひぬきちのちでづひ〺〺〤づのちぢぬづこぴひどっぴぐちひびどので が true の 場 合 は 、べどど
ぜぷづぢぜぎはぴうはふのつえぴぴばぅへっづばぴどはの を引き起こします。 べどどぜぷづぢぜさひぬきちのちでづひ〺〺〤づのちぢぬづこぴひどっぴぐちひびどので が false 〨こ れ が デ フ ォ ル ト 値 で す〩 の場 合 は 、 パ ス 情 報 の 部 分 で あ る posts/php が ル ー ト と し て 返 されることになります。 こうして解析されたルートに対応する
アクションがあればそれが実行され、そうでなければ べどどぜぷづぢ
ぜぎはぴうはふのつえぴぴばぅへっづばぴどはの が投げられます。
規則が さげが 生成に使われる場合は、• Url::to(['post/index']) は、二番目の規則を使って、/index.php/posts
を生成します。
• Url::to(['post/index', 'year' => 2014, 'category' => 'php']) は、最初の規則を使って、/index.php/posts/2014/php を生成します。
• Url::to(['post/view', 'id' => 100]) は、三番目の規則を使って、/index.php/post/100を生成します。
• Url::to(['post/view', 'id' => 100, 'source' => 'ad']) も、三番目の規則を使って、/index.php/post/100?source=ad を生成します。 source パ
ラメータは規則の中で指定されていないので、クエリ・パラメータ
として、生成される さげが に追加されます。
• Url::to(['post/index', 'category' => 'php']) は 、ど の規則も使わ ずに、/index.php/post/index?category=php を生成します。 どの規則も当てはまらないため、さげが は、単純に、ルートをパス情報とし、すべてのパラメータをクエリ文字列として追加して生成されます。

〴〮〳〮 ルーティングと さげが 生成〱〸〵

ルートをパラメータ化する
さげが 規則のルートにはパラメータ名を埋め込むことが出来ます。このことによって、さげが 規則を複数のルートに合致させることが可能になっています。 例えば、以下の規則は controller と action というパラメータをルートに埋め込んでいます。
'rules' => ['<controller:(post|comment)>/create' => '<controller>/create','<controller:(post|comment)>/<id:\d+>/<action:(update|delete)>' =>'<controller>/<action>','<controller:(post|comment)>/<id:\d+>' => '<controller>/view','<controller:(post|comment)>s' => '<controller>/index',]/index.php/comment/100/update という さげが の解析には、二番目の規則が適用され、controller パラメータには comment、action パラメータには
update がセットされます。 こうして、<controller>/<action> というルート
は、comment/update として解決されます。
同じように、comment/index というルートの さげが を生成するためには、最後の規則が適用されて、index.php/comments という さげが が生成されます。
情報〺 ルートをパラメータ化することによって、さげが 規則の数を大幅に減らすことが可能になり、 さげが マネージャ のパ
フォーマンスを目に見えて改善することが出来ます。
デフォルトのパラメータ値
デフォルトでは、規則の中で宣言されたパラメータは必須となります。
リクエストされた さげが が特定のパラメータを含まない場合や、特定のパラメータなしで さげが を生成する場合には、規則は適用されません。 パ
ラメータのどれかをオプション扱いにしたい場合は、規則の つづてちふぬぴび プ
ロパティを構成することが出来ます。 このプロパティのリストに挙げられたパラメータはオプション扱いとなり、提供されなかった場合は指定された値を取るようになります。
次の規則の宣言においては、page と tag のパラメータは両方ともオプション扱いで、 提供されなかった場合は、それぞれ、〱 と空文字列を取ります。
'rules' => [// ... 他の規則 ...
['pattern' => 'posts/<page:\d+>/<tag>','route' => 'post/index','defaults' => ['page' => 1, 'tag' => ''],
],
]

〱〸〶

ぃえぁぐごぅげ 〴〮 リクエストの処理

上記の規則を以下の さげが を解析または生成するために使用することが出来ます。
• /index.php/posts〺 page は 〱〬 tag は だ〧〮• /index.php/posts/2〺 page は 〲〬 tag は だ〧〮• /index.php/posts/2/news〺 page は 〲〬 tag は 'news'〮• /index.php/posts/news〺 page は 〱〬 tag は 'news'〮
オプション扱いのパラメータを使わなければ、同じ結果を得るために 〴個の規則を作らなければならなかったところです。
補足〺 ばちぴぴづひの がオプション扱いのパラメータとスラッシュだけを含んでいるときは、 最初のパラメータは、他のパラメー
タが省略されている場合に限り、省略することが出来ます。
サーバ名を持つ規則
さげが 規則のパターンには、ウェブ・サーバ名を含むことが出来ます。
このこ とが役に立つのは 、主として 、あなたの アプリケー ションがウェブ ・サーバ名によっ て異なる動作をしな ければなら ない場合です。 例えば、次の規則は、https://admin.example.com/login という さげが を
admin/user/login のルートとして解析し、https://www.example.com/login をsite/login として解析するものです。
'rules' => ['https://admin.example.com/login' => 'admin/user/login','https://www.example.com/login' => 'site/login',]

サーバ名にパラメータを埋め込んで、そこから動的な情報を抽出することも出来ます。 例えば、次の規則は https://en.example.com/posts というさげが を解析して、post/index というルートと language=en というパラメー
タを取得するものです。
'rules' => ['http://<language:\w+>.example.com/posts' => 'post/index',]

バージョン 〲〮〰〮〱〱 以降は、http と https の両方に通用する、プロトコル相対パターンを使うことも出来ます。 記法は上記と同じです、ただ、http:の部分を省略します。例えば、'//www.example.com/login' => 'site/login'。
補 足〺 サ ー バ 名 を 持 つ 規 則 は 、 そ の パ タ ー ン に 、 エ ン ト
リ・スクリプトのサブフォルダを含まないようにすべきです。 例えば、アプリケーションのエントリ・スクリプ
トが https://www.example.com/sandbox/blog/index.php である場合
は、https://www.example.com/sandbox/blog/posts ではなく、https://www.example.com/postsというパターンを使うべきです。 こうすれば、アプリケー
ションをどのようなディレクトリに配置しても、さげが 規則を変更する必要がなくなります。すどど はアプリケーションのベース さげが を自動的に検出します。

〴〮〳〮 ルーティングと さげが 生成〱〸〷

さげが 接尾辞さまざまな目的から さげが に接尾辞を追加したいことがあるでしょう。
例えば、静的な えごきが ページに見えるように、.html を さげが に追加したいかも知れません。 また、レスポンスとして期待されているコンテン
ト・タイプを示すために、.json を さげが に追加したい場合もあるでしょう。 アプリケーションの構成情報で、次のように、べどどぜぷづぢぜさひぬきちのちでづひ〺〺〤びふててどへ プロパティを構成することによって、この目的を達することが出来ます。
[]// ...
'components' => ['urlManager' => ['enablePrettyUrl' => true,// ...
'suffix' => '.html','rules' => [// ...
],],],

上記の構成によって、さげが マネージャ は、接尾辞として .html の付いたさげが を認識し、 また、生成するようになります。
ヒ ン ト〺 さげが が 全 て ス ラ ッ シ ュ で 終 る よ う に す る た め には、さげが 接尾辞として / を設定することが出来ます。
補足〺 さげが 接尾辞を構成すると、リクエストされた さげが が接尾辞を持たない場合は、認識できない さげが であると見なされるようになります。 これは、異なる さげが 上の重複コンテン
ツを防止するためのものであり、こぅく 〨検索エンジン最適化〩の見地からも推奨されるプラクティスです。
場合によっては、さげが によって異なる接尾辞を使いたいことがあるでしょう。 その目的は、個々の さげが 規則の びふててどへ プロパティを構成する
ことによって達成できます。 さげが 規則にこのプロパティが設定されている場合は、それが さげが マネージャ レベルの接尾辞の設定をオーバーライドします。 例えば、次の構成には、グローバルな接尾辞 .html の代りに
.json を使用するカスタマイズされた さげが 規則が含まれています。
['components' => ['urlManager' => ['enablePrettyUrl' => true,// ...
'suffix' => '.html',

〱〸〸

]

ぃえぁぐごぅげ 〴〮 リクエストの処理],],'rules' => [// ...
['pattern' => 'posts','route' => 'post/index','suffix' => '.json',],],

えごごぐ メソッド
げぅこごてふぬ ぁぐぉ を実装するときは、使用されている えごごぐ メソッドに応じて、同一の さげが を異なるルートとして解析することが必要になる場合がよくあります。 これは、規則のパターンにサポートされている えごごぐ
メソッドを前置することによって、簡単に達成することが出来ます。 一つの規則が複数の えごごぐ メソッドをサポートする場合は、メソッド名
をカンマで区切ります。 例えば、次の三つの規則は、post/<id:\d+> という同一のパターンを持って、異なる えごごぐ メソッドをサポートするものです。 PUT post/100 に対するリクエストは post/update と解析され、GET
post/100 に対するリクエストは post/view と解析されることになります。
'rules' => ['PUT,POST post/<id:\d+>' => 'post/update','DELETE post/<id:\d+>' => 'post/delete','post/<id:\d+>' => 'post/view',]

補足〺 さげが 規則が えごごぐ メソッドをパターンに含む場合、指定されたメソッドに GET が入っていない限り、その規則は解析目的にだけ使用されます。 さげが マネージャ が さげが 生成のために呼ばれたときは、その規則はスキップされます。
ヒント〺 げぅこごてふぬ ぁぐぉ のルーティングを簡単にするために、すどどは特別な さげが 規則クラス べどどぜひづびぴぜさひぬげふぬづ を提供しています。 これは非常に効率的なもので、コントローラ ぉい の自動的な複数形化など、いくつかの素敵な機能をサポートするものです。 詳細については、げぅこごてふぬ ぁぐぉ 開発についての ルー
ティング のセクションを参照してください。
規則を動的に追加する
さげが 規則は さげが マネージャ に動的に追加することが出来ます。 このことは、再配布可能な モジュール が自分自身の さげが 規則を管理する必要がある場合に、しばしば必要になります。 動的に追加された規則がルーティングのプロセスで効果を発揮するためには、その規〴〮〳〮 ルーティングと さげが 生成〱〸〹

則をアプリケーションの ブートストラップ の段階で追加しなければなりません。 これは、モジュールにとっては、次のように、べどどぜぢちびづ
ぜあははぴびぴひちばぉのぴづひてちっづ を実装して、 ぢははぴびぴひちば〨〩 メソッドの中で規則を追加しなければならないことを意味します。
public function bootstrap($app){$app->getUrlManager()->addRules([// ここに規則の宣言], false);}

さらに、モジュールが ブートストラップ の過程に関与できるように、 それを べどどぜぷづぢぜぁばばぬどっちぴどはの〺〺ぢははぴびぴひちば〨〩 のリストに挙げなければならないことに注意してください。
規則クラスを作成する
デフォルトの べどどぜぷづぢぜさひぬげふぬづ クラスはほとんどのプロジェクトに対して十分に柔軟なものであるというのは事実ですが、それでも、自分自身で規則クラスを作る必要があるような状況はあります。 例えば、自動車
ディーラーのウェブ・サイトにおいて、/Manufacturer/Model のような さげが形式をサポートしたいけれども、 Manufacturer と Model は、両方とも、
データベース・テーブルに保存されている何らかのデータに合致するものでなければならない、というような場合です。 デフォルトの規則クラスは、静的に宣言されるパターンに依拠しているため、ここでは役に立ちません。
この問題を解決するために、次のような さげが 規則クラスを作成することが出来ます。
<?php
namespace app\components;
use yii\web\UrlRuleInterface;
use yii\base\BaseObject;class CarUrlRule extends BaseObject implements UrlRuleInterface{
public function createUrl($manager, $route, $params){
if ($route === 'car/index') {if (isset($params['manufacturer'], $params['model'])) {return $params['manufacturer'] . '/' . $params['model'];} elseif (isset($params['manufacturer'])) {return $params['manufacturer'];}}
return false; // この規則は適用されない}〱〹〰

ぃえぁぐごぅげ 〴〮 リクエストの処理

public function parseRequest($manager, $request){$pathInfo = $request->getPathInfo();if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches)) {// $matches[1] と $matches[3] をチェックして、// データベースの中の製造者とモデルに合致するかどうか調べる// 合致すれば、$params['manufacturer'] および/または$params['model']// をセットし、['car/index', $params] を返す}
return false; // この規則は適用されない}}

そして、べどどぜぷづぢぜさひぬきちのちでづひ〺〺〤ひふぬづび の構成情報で、新しい規則クラスを使います。
'rules' => [// ... 他の規則 ...
['class' => 'app\components\CarUrlRule',// ... 他のプロパティを構成する ...
],
]

4.3.5

URL の正規化

バージョン 〲〮〰〮〱〰 以降、さひぬきちのちでづひ で さひぬぎはひねちぬどぺづひ を使って、 同一
さげが のバリエーション 〨例えば、末尾のスラッシュの有無〩 の問題を処理する出来るようになりました。 技術的には https://example.com/path とhttps://example.com/path/ は別の さげが ですから、これらの両方に同一のコンテントを提供することは こぅく ランキングを低下させる可能性があります。 デフォルトでは、さげが ノーマライザは、連続したスラッシュを畳み、サフィックスが末尾のスラッシュを持っているかどうかに従って末尾のスラッシュを追加または削除し、 正規化された さげが に 恒久的な移動4 を使ってリダイレクトします。 ノーマライザは、さげが マネージャのためにグローバルに構成することも、各規則のために個別に構成することも出来ます。 各規則は、デフォルトでは、さげが マネージャのノーマ
ライザを使用します。 さひぬげふぬづ〺〺〤のはひねちぬどぺづひ を false にすれば、特定のさげが 規則について正規化を無効にすることが出来ます。
次に、さひぬぎはひねちぬどぺづひ の構成例を示します。
'urlManager' => ['enablePrettyUrl' => true,'showScriptName' => false,'enableStrictParsing' => true,'suffix' => '.html',
4

https://en.wikipedia.org/wiki/HTTP_301

〴〮〳〮 ルーティングと さげが 生成]〱〹〱'normalizer' => ['class' => 'yii\web\UrlNormalizer',// デバッグのために、恒久的移動のかわりに一時的リダイレクションを使う'action' => UrlNormalizer::ACTION_REDIRECT_TEMPORARY,],'rules' => [// ... 他の規則 ...
['pattern' => 'posts','route' => 'post/index','suffix' => '/',
'normalizer' => false, // この規則では正規化を無効にする],['pattern' => 'tags','route' => 'tag/index','normalizer' => [// この規則では連続するスラッシュを畳まない'collapseSlashes' => false,
],
],
],

補足〺 デフォルトでは さひぬきちのちでづひ〺〺〤のはひねちぬどぺづひ は無効になっています。 さげが の正規化を有効にするためには、明示的に構成する必要があります。

4.3.6

パフォーマンスに対する考慮

複雑なウェブ・アプリケーションを開発するときは、リクエストの解析と さげが 生成に要する時間を削減するために さげが 規則を最適化することが重要になります。
パラメータ化したルートを使うことによって、さげが 規則の数を減らして、パフォーマンスを著しく向上させることが出来ます。
さげが を解析または生成するときに、さげが マネージャ は、宣言された順序で さげが 規則を調べます。 従って、より多く使われる規則がより少なく使われる規則より前に来るように順序を調整することを検討してください。
パターンまたはルートに共通の先頭部分を持つ さげが 規則がある場合は、さげが マネージャ がそれらをグループ化して効率的に調べることが出来るように、 べどどぜぷづぢぜぇひはふばさひぬげふぬづ を使うことを検討してください。
あなたのアプリケーションがモジュールによって構成されており、モジュールごとに、モジュール ぉい を共通の先頭部分とする一群の さげが 規則を持っている場合は、通常、このことが当てはまります。

〱〹〲

ぃえぁぐごぅげ 〴〮 リクエストの処理

リクエスト

4.4

アプリケーションに対するリクエストは、リクエストのパラメータ、えごごぐ
ヘッダ、クッキーなどの情報を提供する べどどぜぷづぢぜげづぱふづびぴ オブジェクトの形で表されます。 与えられたリクエストに対応するリクエスト・オブ
ジェクトには、デフォルトでは べどどぜぷづぢぜげづぱふづびぴ のインスタンスである
request アプリケーション・コンポーネント を通じてアクセスすることが出来ます。 このセクションでは、アプリケーションの中でこのコンポー
ネントをどのように利用できるかを説明します。

4.4.1

リクエストのパラメータ

リクエストのパラメータを取得するためには、request コンポーネントのでづぴ〨〩 および ばはびぴ〨〩 メソッドを呼ぶことが出来ます。 これらは、ぞれぞれ、$_GET と $_POST の値を返します。例えば、$request = Yii::$app->request;$get = $request->get();// $get = $_GET; と同等$id = $request->get('id');// $id = isset($_GET['id']) ? $_GET['id'] : null; と同等$id = $request->get('id', 1);// $id = isset($_GET['id']) ? $_GET['id'] : 1; と同等$post = $request->post();// $post = $_POST; と同等$name = $request->post('name');// $name = isset($_POST['name']) ? $_POST['name'] : null; と同等$name = $request->post('name', '');// $name = isset($_POST['name']) ? $_POST['name'] : ''; と同等

情報〺 直接に $_GET と $_POST にアクセスしてリクエストのパラメータを読み出す代りに、上記に示されているように、
request コンポーネントを通じてそれらを取得することが推奨されます。 このようにすると、ダミーのリクエスト・データを持った模擬リクエスト・コンポーネントを作ることが出来るため、テストを書くことがより容易になります。
げぅこごてふぬ ぁぐぉ を実装するときは、ぐさご、ぐぁごぃえ またはその他の リクエ
スト・メソッド によって送信されたパラメータを読み出さなければならないことがよくあります。 そういうパラメータは べどどぜぷづぢぜげづぱふづびぴ〺〺
でづぴあはつべぐちひちね〨〩 メソッドを呼ぶことで取得することが出来ます。 例えば、〴〮〴〮 リクエスト〱〹〳$request = Yii::$app->request;// 全てのパラメータを返す$params = $request->bodyParams;// パラメータ "id" を返す$param = $request->getBodyParam('id');

情報〺 GET パラメータとは異なって、POST、PUT、PATCH などで送信されたパラメータは、リクエストのボディの中で送られます。 上述のメソッドによってこれらのパラメータにアクセスすると、request コンポーネントがパラメータを解析しま
す。 べどどぜぷづぢぜげづぱふづびぴ〺〺〤ばちひびづひび プロパティを構成することによって、これらのパラメータが解析される方法をカスタマ
イズすることが出来ます。

4.4.2

リクエスト・メソッド

現在のリクエストに使用された えごごぐ メソッドは、Yii::$app->request->methodという式によって取得することが出来ます。 現在のメソッドが特定のタイプであるかどうかをチェックするための、一揃いの真偽値のプロパ
ティも提供されています。 例えば、
$request = Yii::$app->request;
if ($request->isAjax) { /* リクエストは AJAX リクエスト */ }if ($request->isGet) { /* リクエスト・メソッドは GET */ }if ($request->isPost) { /* リクエスト・メソッドは POST */ }if ($request->isPut) { /* リクエスト・メソッドは PUT */ }4.4.3

リクエストの URL

request コンポーネントは現在リクエストされている さげが を調べるための方法を数多く提供しています。
リクエストされた さげが が https://example.com/admin/index.php/product?id=100であると仮定したとき、 次にまとめたように、この さげが のさまざまな部分を取得することが出来ます。
• ふひぬ〺 /admin/index.php/product?id=100 を返します。ホスト情報の部分を省略した さげが です。
• ちぢびはぬふぴづさひぬ〺 https://example.com/admin/index.php/product?id=100 を返します。 ホスト情報の部分を含んだ さげが です。
• とはびぴぉのては〺 https://example.com を返します。さげが のホスト情報の部分です。
• ばちぴとぉのては〺 /product を返します。 エントリ・スクリプトの後、疑問符 〨クエリ文字列〩 の前の部分です。
• ぱふづひべこぴひどので〺 id=100 を返します。疑問符の後の部分です。

〱〹〴

ぃえぁぐごぅげ 〴〮 リクエストの処理• ぢちびづさひぬ〺 /admin を返します。ホスト情報の後、かつ、 エントリ・
スクリプトの前の部分です。
• びっひどばぴさひぬ〺 /admin/index.php を返します。パス情報とクエリ文字列を省略した さげが です。
• びづひぶづひぎちねづ〺 example.com を返します。さげが の中のホスト名です。
• びづひぶづひぐはひぴ〺 〸〰 を返します。ウェブ・サーバによって使用されているポートです。

4.4.4

HTTP ヘッダ

べどどぜぷづぢぜげづぱふづびぴ〺〺〤とづちつづひび プロパティによって返される とづちつづひ コレクション を通じて、 えごごぐ ヘッダ情報を取得することが出来ます。例えば、// $headers は yii\web\HeaderCollection のオブジェクト$headers = Yii::$app->request->headers;// Accept ヘッダの値を返す$accept = $headers->get('Accept');
if ($headers->has('User-Agent')) { /* User-Agent ヘッダが在る */ }request コンポーネントは、よく使用されるいくつかのヘッダにすばやくアクセスする方法を提供しています。その中には下記のものが含まれます。
• ふびづひぁでづのぴ〺 User-Agent ヘッダの値を返します。
• っはのぴづのぴごべばづ〺 リクエスト・ボディのデータの きぉきぅ タイプを示す
Content-Type ヘッダの値を返します。
• ちっっづばぴちぢぬづぃはのぴづのぴごべばづび〺 ユーザが受け入れ可能なコンテントのきぉきぅ タイプを返します。 返されるタイプは品質スコアによって順序付けられます。最もスコアの高いタイプが最初に返されます。
• ちっっづばぴちぢぬづがちのでふちでづび〺 ユーザが受け入れ可能な言語を返します。
返される言語は優先レベルによって順序付けられます。最初の要素が最も優先度の高い言語を表します。
あなたのアプリケーションが複数の言語をサポートしており、エンド・ユーザが最も優先する言語でページを表示したいと思う場合は、 言語ネ
ゴシエーション・メソッド べどどぜぷづぢぜげづぱふづびぴ〺〺でづぴぐひづてづひひづつがちのでふちでづ〨〩を使うことが出来ます。 このメソッドはアプリケーションによってサポートされている言語のリストを引数として取り、 ちっっづばぴちぢぬづがちのでふちでづびと比較して、最も適切な言語を返します。

ヒント〺 ぃはのぴづのぴぎづではぴどちぴはひ フィルタを使用して、 レスポン
スにおいてどのコンテント・タイプと言語を使うべきかを動的に決定することも出来ます。 このフィルタは、上記で説明したプロパティとメソッドの上に、コンテント・ネゴシエー
ションを実装しています。

〴〮〴〮 リクエスト

4.4.5

〱〹〵

クライアント情報

クライアント・マシンのホスト名と ぉぐ アドレスを、 それぞれ、ふびづひえはびぴと ふびづひぉぐ によって取得することが出来ます。 例えば、
$userHost = Yii::$app->request->userHost;$userIP = Yii::$app->request->userIP;

4.4.6

信頼できるプロキシとヘッダ

前のセクションでホストや ぉぐ アドレスなどのユーザ情報を取得する方法を説明しました。 単一のウェブ・サーバがウェブ・サイトをホストしている通常の環境では、このままで動作します。 しかし、すどど アプリケー
ションがリバース・プロキシの背後で動作している場合は、この情報を読み出すために構成情報を追加する必要があります。 なぜなら、その場
合、直接のクライアントはプロキシになっており、ユーザの ぉぐ アドレス
はプロキシがセットするヘッダによって すどど アプリケーションに渡されるからです。
明示的に信頼したプロキシ以外は、プロキシによって提供されるヘッダを盲目的に信頼してはいけません。 〲〮〰〮〱〳 以降、すどど は request
コンポーネントの以下のプロパティによって、 信頼できるプロキシの情報を構成することが出来るようになっています。 ぴひふびぴづつえはびぴび、びづっふひづえづちつづひび、 どばえづちつづひび および びづっふひづぐひはぴはっはぬえづちつづひび
以下は、リバース・プロキシ・アレイの背後で動作するアプリケー
ションのための、ひづぱふづびぴ の構成例です 〨リバース・プロキシ・アレイは10.0.2.0/24 のネットワークに設置されているとします〩。
'request' => [// ...
'trustedHosts' => ['10.0.2.0/24',],],

プロキシは、デフォルトでは、ぉぐ を X-Forwarded-For ヘッダで送信し、プロトコル 〨http または https〩 を X-Forwarded-Proto で送信します。
あなたのプロキシが異なるヘッダを使っている場合は、ひづぱふづびぴ の構成情報を使って調整することが出来ます。例えば、'request' => [// ...
'trustedHosts' => ['10.0.2.0/24' => ['X-ProxyUser-Ip','Front-End-Https',],],'secureHeaders' => ['X-Forwarded-For',〱〹〶

ぃえぁぐごぅげ 〴〮 リクエストの処理'X-Forwarded-Host','X-Forwarded-Proto','X-Proxy-User-Ip','Front-End-Https',],'ipHeaders' => ['X-Proxy-User-Ip',],'secureProtocolHeaders' => ['Front-End-Https' => ['on']],],

上記の構成によって、secureHeaders としてリストされているヘッダはリク
エストから除去され、 信頼できるプロキシからのリクエストである場合にのみ、X-ProxyUser-Ip と Front-End-Https ヘッダが受け入れられます。 その場合、前者は ipHeaders で構成されているようにユーザの ぉぐ を読み出すために使用され、 後者は べどどぜぷづぢぜげづぱふづびぴ〺〺でづぴぉびこづっふひづぃはののづっぴどはの〨〩の結果を決定するために使用されます。
〲〮〰〮〳〱 以降、げうぃ 〷〲〳〹5 の Forwarded ヘッダがサポートされています。
有効にするためには、ヘッダ名を secureHeaders に追加する必要があります。 あなたのプロキシにそれを設定させることを忘れないで下さい。さもないと、エンド・ユーザが ぉぐ とプロトコルを盗み見ることが可能になります。
解決済みのユーザ ぉぐ
ユーザの ぉぐ アドレスが すどど アプリケーション以前に解決済みである場
合〨例えば、ngx_http_realip_module など〩 は、 request コンポーネントは下記の構成で正しく動作します。
'request' => [// ...
'trustedHosts' => ['0.0.0.0/0',],'ipHeaders' => [],],この場合、ふびづひぉぐ の値は $_SERVER['REMOTE_ADDR'] に等しくなります。 同時に、えごごぐ ヘッダから解決されるプロパティも正しく動作します 〨例えば、べどどぜぷづぢぜげづぱふづびぴ〺〺でづぴぉびこづっふひづぃはののづっぴどはの〨〩〩。
注意〺 trustedHosts=['0.0.0.0/0'] の設定は、全ての ぉぐ が信頼できることを前提としています。
5https://datatracker.ietf.org/doc/html/rfc7239

〴〮〵〮 レスポンス

4.5

〱〹〷

レスポンス

アプリケーションは リクエスト の処理を完了すると、レスポンス・オブ
ジェクトを生成して、エンド・ユーザに送信します。 レスポンス・オブ
ジェクトは、えごごぐ ステータス・コード、えごごぐ ヘッダ、えごごぐ ボディなどの情報を含みます。 ウェブ・アプリケーション開発の最終的な目
的は、本質的には、さまざまなリクエストに対してそのようなレスポン
ス・オブジェクトを作成することにあります。
ほとんどの場合は、主として、デフォルトでは べどどぜぷづぢぜげづびばはのびづ のインスタンスである response アプリケーション・コンポーネント を使用すべきです。 しかしながら、すどど は、以下で説明するように、あなた自身のレスポンス・オブジェクトを作成してエンド・ユーザに送信することも許容しています。
このセクションでは、レスポンスを構成してエンド・ユーザに送信する方法を説明します。

4.5.1

ステータス・コード

レスポンスを作成するときに最初にすることの一つは、リクエストが成功裡に処理されたかどうかを記述することです。 そのためには、べどどぜぷづぢ
ぜげづびばはのびづ〺〺〤びぴちぴふびぃはつづ プロパティに有効な えごごぐ ステータス・コー
ド6 の一つを設定します。 例えば、下記のように、リクエストの処理が成功したことを示すために、ステータス・コードを 〲〰〰 に設定します。
Yii::$app->response->statusCode = 200;

ただし、たいていの場合、ステータス・コードを明示的に設定する必要はありません。 これは、べどどぜぷづぢぜげづびばはのびづ〺〺〤びぴちぴふびぃはつづ のデフォルト
値が 〲〰〰 であるからです。 そして、リクエストが失敗したことを示した
いときは、下記のように、適切な えごごぐ 例外を投げることが出来ます。
throw new \yii\web\NotFoundHttpException;

エラー・ハンドラ は、例外をキャッチすると、例外からステータ
ス・コードを抽出してレスポンスに割り当てます。 上記の べどどぜぷづぢ
ぜぎはぴうはふのつえぴぴばぅへっづばぴどはの の場合は、えごごぐ ステータス 〴〰〴 と関連付けられています。 次の えごごぐ 例外が すどど によって事前定義されています。
• べどどぜぷづぢぜあちつげづぱふづびぴえぴぴばぅへっづばぴどはの〺 ステータス・コード 〴〰〰
• べどどぜぷづぢぜぃはのてぬどっぴえぴぴばぅへっづばぴどはの〺 ステータス・コード 〴〰〹• べどどぜぷづぢぜうはひぢどつつづのえぴぴばぅへっづばぴどはの〺 ステータス・コード 〴〰〳• べどどぜぷづぢぜぇはのづえぴぴばぅへっづばぴどはの〺 ステータス・コード 〴〱〰
• べどどぜぷづぢぜきづぴとはつぎはぴぁぬぬはぷづつえぴぴばぅへっづばぴどはの〺 ステータス・コード 〴〰〵• べどどぜぷづぢぜぎはぴぁっっづばぴちぢぬづえぴぴばぅへっづばぴどはの〺 ステータス・コード 〴〰〶• べどどぜぷづぢぜぎはぴうはふのつえぴぴばぅへっづばぴどはの〺 ステータス・コード 〴〰〴6

https://tools.ietf.org/html/rfc2616#section-10

〱〹〸

ぃえぁぐごぅげ 〴〮 リクエストの処理• べどどぜぷづぢぜこづひぶづひぅひひはひえぴぴばぅへっづばぴどはの〺 ステータス・コード 〵〰〰
• べどどぜぷづぢぜごははきちのべげづぱふづびぴびえぴぴばぅへっづばぴどはの〺 ステータス・コード 〴〲〹• べどどぜぷづぢぜさのちふぴとはひどぺづつえぴぴばぅへっづばぴどはの〺 ステータス・コード 〴〰〱• べどどぜぷづぢぜさのびふばばはひぴづつきづつどちごべばづえぴぴばぅへっづばぴどはの〺 ステータス・コー
ド 〴〱〵投げたい例外が上記のリストに無い場合は、べどどぜぷづぢぜえぴぴばぅへっづばぴどはの から拡張したものを作成することが出来ます。 あるいは、ステータス・
コードを指定して べどどぜぷづぢぜえぴぴばぅへっづばぴどはの を直接に投げることも出来ます。例えば、
throw new \yii\web\HttpException(402);

4.5.2

HTTP ヘッダ

response コンポーネントの ヘッダ・コレクション を操作することによって、えごごぐ ヘッダを送信することが出来ます。 例えば、
$headers = Yii::$app->response->headers;// Pragma ヘッダを追加する。既存の Pragma ヘッダは上書きされない。
$headers->add('Pragma', 'no-cache');// Pragma ヘッダを設定する。既存の Pragma ヘッダは全て破棄される。
$headers->set('Pragma', 'no-cache');// Pragma ヘッダを削除して、削除された Pragma ヘッダの値を配列に返す。
$values = $headers->remove('Pragma');情報〺 ヘッダ名は大文字小文字を区別しません。 そして、新
しく登録されたヘッダは、べどどぜぷづぢぜげづびばはのびづ〺〺びづのつ〨〩 メソッ
ドが呼ばれるまで送信されません。

4.5.3

レスポンス・ボディ

ほとんどのレスポンスは、エンド・ユーザに対して表示したい内容を示
すボディを持っていなければなりません。
既にフォーマットされたボディの文字列を持っている場合は、それをレスポンスの べどどぜぷづぢぜげづびばはのびづ〺〺〤っはのぴづのぴ プロパティに割り付けることが出来ます。 例えば、
Yii::$app->response->content = 'hello world!';

データをエンド・ユーザに送信する前にフォーマットする必要がある場
合は、てはひねちぴ と つちぴち の両方のプロパティをセットしなければなりません。 てはひねちぴ プロパティは つちぴち がどの形式でフォーマットされるべきかを指定するものです。 例えば、

〴〮〵〮 レスポンス〱〹〹$response = Yii::$app->response;$response->format = \yii\web\Response::FORMAT_JSON;$response->data = ['message' => 'hello world'];

すどど は下記の形式を初めからサポートしています。それぞれ、フォーマッ
タ クラスとして実装されています。 べどどぜぷづぢぜげづびばはのびづ〺〺〤てはひねちぴぴづひび プ
ロパティを構成することで、これらのフォーマッタをカスタマイズしたり、新しいフォーマッタを追加したりすることが出来ます。
• えごきが〺 べどどぜぷづぢぜえぴねぬげづびばはのびづうはひねちぴぴづひ によって実装• じきが〺 べどどぜぷづぢぜじねぬげづびばはのびづうはひねちぴぴづひ によって実装• おこくぎ〺 べどどぜぷづぢぜおびはのげづびばはのびづうはひねちぴぴづひ によって実装• おこくぎぐ〺 べどどぜぷづぢぜおびはのげづびばはのびづうはひねちぴぴづひ によって実装• げぁし〺 書式を何も適用せずにレスポンスを送信したいときは、このフォーマットを使用
レスポンス・ボディは、上記のように、明示的に設定することも出来ま
すが、たいていの場合は、アクション メソッドの返り値によって暗黙のうちに設定することが出来ます。 よくあるユースケースは下記のようなものになります。
public function actionIndex(){
return $this->render('index');}

上記の index アクションは、index ビューのレンダリング結果を返しています。 返された値は response コンポーネントによって受け取られ、
フォーマットされてエンド・ユーザに送信されます。
デフォルトのレスポンス形式が えごきが であるため、アクション・メ
ソッドの中では文字列を返すだけにすべきです。 別のレスポンス形式を使いたい場合は、データを返す前にレスポンス形式を設定しなければなりません。 例えば、
public function actionInfo(){\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ['message' => 'hello world','code' => 100,];}

既に述べたように、デフォルトの response アプリケーション・コンポー
ネントを使う代りに、自分自身のレスポンス・オブジェクトを作成してエンド・ユーザに送信することも出来ます。 そうするためには、次のように、アクション・メソッドの中でそのようなオブジェクトを返しま
す。

〲〰〰

ぃえぁぐごぅげ 〴〮 リクエストの処理

public function actionInfo(){
return \Yii::createObject(['class' => 'yii\web\Response','format' => \yii\web\Response::FORMAT_JSON,'data' => ['message' => 'hello world','code' => 100,
],
]);
}

補足〺 自分自身のレスポンス・オブジェクトを作成しようとする場合は、アプリケーションの構成情報で response コンポー
ネントのために設定した構成情報を利用することは出来ません。 しかし、 依存の注入 を使えば、 共通の構成情報をあなたの新しいレスポンス・オブジェクトに適用することが出来
ます。

4.5.4

ブラウザのリダイレクト

ブラウザのリダイレクトは Location えごごぐ ヘッダの送信に依存しています。 この機能は通常よく使われるものであるため、すどど はこれについて
特別のサポートを提供しています。
べどどぜぷづぢぜげづびばはのびづ〺〺ひづつどひづっぴ〨〩 メソッドを呼ぶことによって、ユー
ザのブラウザをある さげが にリダイレクトすることが出来ます。 このメ
ソッドは与えられた さげが を持つ適切な Location ヘッダを設定して、レスポンス・オブジェクトそのものを返します。 アクション・メソッドの中では、そのショートカット版である べどどぜぷづぢぜぃはのぴひはぬぬづひ〺〺ひづつどひづっぴ〨〩を呼ぶことが出来ます。例えば、
public function actionOld(){
return $this->redirect('https://example.com/new', 301);}

上記のコードでは、アクション・メソッドが redirect() メソッドの結果を返しています。 前に説明したように、アクション・メソッドによって返されるレスポンス・オブジェクトが、エンド・ユーザに送信されるレスポンスとして使用されることになります。
アクション・メソッド以外の場所では、べどどぜぷづぢぜげづびばはのびづ〺〺ひづつどひづっぴ〨〩を直接に呼び出し、 メソッド・チェーンで べどどぜぷづぢぜげづびばはのびづ〺〺びづのつ〨〩メソッドを呼んで、レスポンスに余計なコンテントが追加されないことを保証しなければなりません。
\Yii::$app->response->redirect('https://example.com/new', 301)->send();〴〮〵〮 レスポンス〲〰〱

情報〺 デフォルトでは、べどどぜぷづぢぜげづびばはのびづ〺〺ひづつどひづっぴ〨〩 メ
ソッドはレスポンスのステータス・コードを 〳〰〲 にセットします。 これはブラウザに対して、リクエストされているリソースが 一時的に 異なる さげぉ に配置されていることを示すものです。 ブラウザに対してリソースが 恒久的に 配置替えされたことを教えるためには、ステータス・コード 〳〰〱 を渡すことが出来ます。
現在のリクエストが ぁおぁじ リクエストである場合は、Location ヘッダを送っても自動的にブラウザをリダイレクトすることにはなりません。
この問題を解決するために、べどどぜぷづぢぜげづびばはのびづ〺〺ひづつどひづっぴ〨〩 メソッドは
X-Redirect ヘッダにリダイレクト先 さげが を値としてセットします。 そして、クライアント・サイドで、このヘッダの値を読み、 それに応じてブラウザをリダイレクトする おちぶちこっひどばぴ を書くことが出来ます。
情報〺 すどど には yii.js という おちぶちこっひどばぴ ファイルが付属しています。 これは、よく使われる一連の おちぶちこっひどばぴ 機能を提供するもので、その中には X-Redirect ヘッダに基づくブラウザのリダイレクトも含まれています。 従って、あなたが 〨べどどぜぷづぢ
ぜすどどぁびびづぴ アセット・バンドルを登録して〩 この おちぶちこっひどばぴ
ファイルを使うつもりなら、ぁおぁじ のリダイレクトをサポートするためには、何も書く必要がなくなります。 yii.js に関する更なる情報は クライアント・スクリプトのセクション に
あります。

4.5.5

ファイルを送信する

ブラウザのリダイレクトと同じように、ファイルの送信という機能も特定の えごごぐ ヘッダに依存しています。 すどど はさまざまなファイル送信の必要をサポートするための一連のメソッドを提供しています。それらはすべて、えごごぐ ひちのでづ ヘッダに対するサポートを内蔵しています。
• べどどぜぷづぢぜげづびばはのびづ〺〺びづのつうどぬづ〨〩〺 既存のファイルをクライアントに送信する• べどどぜぷづぢぜげづびばはのびづ〺〺びづのつぃはのぴづのぴぁびうどぬづ〨〩〺 テキストの文字列をファイルとしてクライアントに送信する• べどどぜぷづぢぜげづびばはのびづ〺〺びづのつこぴひづちねぁびうどぬづ〨〩〺 既存のファイル・スト
リームをファイルとしてクライアントに送信する
これらのメソッドは同じメソッド・シグニチャを持ち、返り値としてレ
スポンス・オブジェクトを返します。 送信しようとしているファイルが非常に大きなものである場合は、メモリ効率の良い べどどぜぷづぢぜげづびばはのびづ〺〺
びづのつこぴひづちねぁびうどぬづ〨〩 の使用を検討すべきです。 次の例は、コントロー
ラ・アクションでファイルを送信する方法を示すものです。
public function actionDownload(){〲〰〲ぃえぁぐごぅげ 〴〮 リクエストの処理
return \Yii::$app->response->sendFile('path/to/file.txt');}

ファイル送信メソッドをアクション・メソッド以外の場所で呼ぶ場合
は、その後で べどどぜぷづぢぜげづびばはのびづ〺〺びづのつ〨〩 メソッドも呼んで、 レスポン
スに余計なコンテントが追加されないことを保証しなければなりません。
\Yii::$app->response->sendFile('path/to/file.txt')->send();ウェブ・サーバには、X-Sendfile と呼ばれる特別なファイル送信をサポートするものがあります。 アイデアとしては、ファイルに対するリクエス
トをウェブ・サーバにリダイレクトして、ウェブ・サーバに直接にファイルを送信させる、というものです。 その結果として、ウェブ・サー
バがファイルを送信している間でも、ウェブ・アプリケーションは早期に終了することが出来るようになります。 この機能を使うために、べどど
ぜぷづぢぜげづびばはのびづ〺〺へこづのつうどぬづ〨〩 を呼ぶことが出来ます。 次のリストは、よく使われるいくつかのウェブ・サーバにおいて X-Sendfile 機能を有効にする方法を要約するものです。
• ぁばちっとづ〺 じ〭こづのつ〜ぬづ7• がどでとぴぴばつ ぶ〱〮〴〺 じ〭がぉぇえごごぐい〭びづのつ〭〜ぬづ8• がどでとぴぴばつ ぶ〱〮〵〺 じ〭こづのつ〜ぬづ9• ぎでどのへ〺 じ〭ぁっっづぬ〭げづつどひづっぴ10• ぃとづひはにづづ〺 じ〭こづのつ〜ぬづ ちのつ じ〭ぁっっづぬ〭げづつどひづっぴ11

4.5.6

レスポンスを送信する

レスポンスの中のコンテントは、べどどぜぷづぢぜげづびばはのびづ〺〺びづのつ〨〩 メソッドが呼ばれるまでは、エンド・ユーザに向けて送信されません。 デフォルト
では、このメソッドは べどどぜぢちびづぜぁばばぬどっちぴどはの〺〺ひふの〨〩 の最後で自動的に呼ばれます。 しかし、このメソッドを明示的に呼んで、強制的にレスポ
ンスを即座に送信することも可能です。
べどどぜぷづぢぜげづびばはのびづ〺〺びづのつ〨〩 メソッドは次のステップを踏んでレスポンスを送出します。
〱〮 べどどぜぷづぢぜげづびばはのびづ〺〺ぅざぅぎごたあぅうくげぅたこぅぎい イベントをトリガする。
〲〮 べどどぜぷづぢぜげづびばはのびづ〺〺ばひづばちひづ〨〩 を呼んで レスポンス・データ を レ
スポンス・コンテント としてフォーマットする。
〳〮 べどどぜぷづぢぜげづびばはのびづ〺〺ぅざぅぎごたぁうごぅげたぐげぅぐぁげぅ イベントをトリガする。
https://tn123.org/mod_xsendfile
https://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file9
https://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file10
https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/11
https://www.cherokee-project.com/doc/other_goodies.html#x-sendfile
78〴〮〶〮 セッションとクッキー〲〰〳〴〮 べどどぜぷづぢぜげづびばはのびづ〺〺びづのつえづちつづひび〨〩 を呼んで、登録された えごごぐ
ヘッダを送出する。
〵〮 べどどぜぷづぢぜげづびばはのびづ〺〺びづのつぃはのぴづのぴ〨〩 を呼んで、レスポンスのボディ・コンテントを送出する。
〶〮 べどどぜぷづぢぜげづびばはのびづ〺〺ぅざぅぎごたぁうごぅげたこぅぎい イベントをトリガする。
べどどぜぷづぢぜげづびばはのびづ〺〺びづのつ〨〩 メソッドが一度呼び出された後では、このメソッドに対する更なる呼び出しは無視されます。 このことは、いったん
レスポンスが送出された後では、それにコンテントを追加することは出来なくなる、ということを意味します。
ごらんのように、べどどぜぷづぢぜげづびばはのびづ〺〺びづのつ〨〩 メソッドはいくつかの有用なイベントをトリガします。 これらのイベントに反応することによって、レスポンスを調整したり修飾したりすることが出来ます。

4.6

セッションとクッキー

セッションとクッキーは、データが複数回のユーザ・リクエストにまたがって持続することを可能にします。 素の ぐえぐ では、それぞれ、グローバル変数 $_SESSION と $_COOKIE によってアクセスすることが出来ます。 すどど はセッションとクッキーをオブジェクトとしてカプセル化し、オブジェクト指向の流儀でアクセスできるようにするとともに、有用な機能強化を追加しています。

4.6.1

セッション

リクエスト や レスポンス と同じように、 デフォルトでは べどどぜぷづぢ
ぜこづびびどはの のインスタンスである session せアプリケーション・コンポーネントそ によって、 セッションにアクセスすることが出来ます。
セッションのオープンとクローズセッションのオープンとクローズは、次のようにして出来ます。
$session = Yii::$app->session;// セッションが既に開かれているかチェックする
if ($session->isActive) ...
// セッションを開く$session->open();// セッションを閉じる$session->close();// セッションに登録されている全てのデータを破壊する$session->destroy();〲〰〴ぃえぁぐごぅげ 〴〮 リクエストの処理

エラーを発生させずに はばづの〨〩 と っぬはびづ〨〩 を複数回呼び出すことが出来ます。 内部的には、これらのメソッドは、セッションが既に開かれているかどうかを最初にチェックします。
セッション・データにアクセスする
セッションに保存されているデータにアクセスするためには、次のようにすることが出来ます。
$session = Yii::$app->session;// セッション変数を取得する。次の三つの用法は等価。
$language = $session->get('language');$language = $session['language'];$language = isset($_SESSION['language']) ? $_SESSION['language'] : null;// セッション変数を設定する。次の三つの用法は等価。
$session->set('language', 'en-US');$session['language'] = 'en-US';$_SESSION['language'] = 'en-US';// セッション変数を削除する。次の三つの用法は等価。
$session->remove('language');unset($session['language']);unset($_SESSION['language']);// セッション変数が存在するかどうかをチェックする。次の三つの用法は等価。
if ($session->has('language')) ...
if (isset($session['language'])) ...
if (isset($_SESSION['language'])) ...
// 全てのセッション変数をたどる。次の二つの用法は等価。
foreach ($session as $name => $value) ...
foreach ($_SESSION as $name => $value) ...

情報〺 session コンポーネントによってセッション・データにアクセスする場合は、まだ開かれていないときは、自動的にセッションが開かれます。 これに対して $_SESSION によってセッション・データにアクセスする場合は、 session_start()を明示的に呼び出すことが必要になります。
配列であるセッション・データを扱う場合、session コンポーネントには、配列の要素を直接修正することができない、という制約があります。 例えば、$session = Yii::$app->session;// 次のコードは動かない$session['captcha']['number'] = 5;$session['captcha']['lifetime'] = 3600;

〴〮〶〮 セッションとクッキー〲〰〵// 次のコードは動く$session['captcha'] = ['number' => 5,'lifetime' => 3600,];// 次のコードも動く
echo $session['captcha']['lifetime'];

次の回避策のどれかを使ってこの問題を解決することが出来ます。
$session = Yii::$app->session;// $_SESSION を直接使う (既に Yii::$app->session->open() が呼び出されていることを確認)$_SESSION['captcha']['number'] = 5;$_SESSION['captcha']['lifetime'] = 3600;// 配列全体を取得し、修正して、保存しなおす$captcha = $session['captcha'];$captcha['number'] = 5;
$captcha['lifetime'] = 3600;$session['captcha'] = $captcha;// 配列の代わりに ArrayObject を使う$session['captcha'] = new \ArrayObject;...
$session['captcha']['number'] = 5;$session['captcha']['lifetime'] = 3600;// 共通の接頭辞を持つキーを使って配列データを保存する$session['captcha.number'] = 5;$session['captcha.lifetime'] = 3600;

パフォーマンスとコードの可読性を高めるためには、最後の回避策を推奨します。 すなわち、配列を一つのセッション変数として保存する代りに、配列の個々の要素を、他の配列要素と共通の接頭辞を持つ、 個別のセッション変数として保存することです。
カスタム・セッション・ストレージ
デフォルトの べどどぜぷづぢぜこづびびどはの クラスはセッション・データをサーバ上のファイルとして保存します。 すどど は、また、さまざまなセッション・
ストレージを実装する下記のクラスをも提供しています。
• べどどぜぷづぢぜいぢこづびびどはの〺 セッション・データをデータベース・テーブ
ルを使って保存する。
• べどどぜぷづぢぜぃちっとづこづびびどはの〺 セッション・データを、構成された キャッシュ・コンポーネント の力を借りて、キャッシュを使って保存する。
• べどどぜひづつどびぜこづびびどはの〺 セッション・データを ひづつどび12 をストレージ媒
12https://redis.io/〲〰〶

ぃえぁぐごぅげ 〴〮 リクエストの処理体として使って保存する。
• べどどぜねはのではつぢぜこづびびどはの〺 セッション・データを きはのではいあ13 に保存する。
これらのセッション・クラスは全て一連の同じ ぁぐぉ メソッドをサポートします。 その結果として、セッションを使用するアプリケーション・
コードを修正することなしに、セッション・ストレージ・クラスを切り替えることが出来ます。
補足〺 カスタム・セッション・ストレージを使っているときに$_SESSION を通じてセッション・データにアクセスしたい場合
は、 セッションが べどどぜぷづぢぜこづびびどはの〺〺はばづの〨〩 によって既に開始されていることを確認しなければなりません。 これは、カスタム・セッション・ストレージのハンドラは、この open()
メソッドの中で登録されるからです。
補足〺 カスタム・セッション・ストレージを使うときは、セッ
ションのガーベッジ・コレクタを明示的に構成する必要がある場合があります。 ぐえぐ のインストレーションによっては〨例えば いづぢどちの では〩、ガーベッジ・コレクタの蓋然性は 〰
とされ、セッション・ファイルはクロン・ジョブでオフラインで消去することになっています。 このプロセスはあなたのカスタム・セッション・ストレージには当てはまりませんので、 べどどぜぷづぢぜこづびびどはの〺〺〤ぇぃぐひはぢちぢどぬどぴべ に 〰 でない値を設定して構成しなければなりません。
これらのコンポーネント・クラスの構成方法と使用方法については、それらの ぁぐぉ ドキュメントを参照してください。 下記の例は、アプリケー
ションの構成情報において、データベース・テーブルをセッション・ス
トレージとして使うために べどどぜぷづぢぜいぢこづびびどはの を構成する方法を示すものです。
return ['components' => ['session' => ['class' => 'yii\web\DbSession',// 'db' => 'mydb', // DB 接続のアプリケーション・コンポーネント
ID。デフォルトは 'db'。
// 'sessionTable' => 'my_session', // セッション・テーブル名。デフォルトは 'session'。
],
],
];

セッション・データを保存するために、次のようなデータベース・テー
ブルを作成することも必要です。
13

https://www.mongodb.com/

〴〮〶〮 セッションとクッキー〲〰〷

CREATE TABLE session(
id CHAR(40) NOT NULL PRIMARY KEY,
expire INTEGER,
data BLOB)

ここで だあがくあ〧 はあなたが選んだ いあきこ の あがくあ 型を指します。下記は人気のあるいくつかの いあきこ で使用できる あがくあ 型です。
• きべこけが〺 がくぎぇあがくあ• ぐはびぴでひづこけが〺 あすごぅぁ• きここけが〺 あがくあ補足〺 ばとば〮どのど の session.hash_function の設定によっては、id
カラムの長さを修正する必要があるかも知れません。 例えば、session.hash_function=sha256 である場合は 〴〰 の代りに 〶〴の長さを使わなければなりません。
別の方法として、次のマイグレーションを使ってこれを達成することも
出来ます。
<?php
use yii\db\Migration;
class m170529_050554_create_table_session extends Migration{
public function up(){$this->createTable('{{%session}}', ['id' => $this->char(64)->notNull(),'expire' => $this->integer(),'data' => $this->binary()]);$this->addPrimaryKey('pk-id', '{{%session}}', 'id');}}public function down(){$this->dropTable('{{%session}}');}

フラッシュ・データ
フラッシュ・データは特殊な種類のセッション・データで、あるリクエ
ストの中で設定されると、 次のリクエストの間においてのみ読み出すことが出来て、その後は自動的に削除されるものです。 フラッシュ・デー
タが最もよく使われるのは、エンド・ユーザに一度だけ表示されるべき〲〰〸

ぃえぁぐごぅげ 〴〮 リクエストの処理

メッセージ、 例えば、ユーザのフォーム送信が成功した後に表示される
確認メッセージなどを実装するときです。
session アプリケーション・コンポーネントによって、フラッシュ・
データを設定し、アクセスすることが出来ます。例えば、$session = Yii::$app->session;// リクエスト #1// "postDeleted" という名前のフラッシュ・メッセージを設定する$session->setFlash('postDeleted', '投稿の削除に成功しました。');// リクエスト #2// "postDeleted" という名前のフラッシュ・メッセージを表示する
echo $session->getFlash('postDeleted');// リクエスト #3// フラッシュ・メッセージは自動的に削除されるので、$result は false になる$result = $session->hasFlash('postDeleted');

通常のセッション・データと同様に、任意のデータをフラッシュ・デー
タとして保存することが出来ます。
べどどぜぷづぢぜこづびびどはの〺〺びづぴうぬちびと〨〩 を呼び出すと、同じ名前の既存のフラッシュ・データは上書きされます。 同じ名前の既存のメッセージに新しいフラッシュ・データを追加するためには、代りに べどどぜぷづぢぜこづびびどはの〺〺ちつつうぬちびと〨〩 を使うことが出来ます。 例えば、
$session = Yii::$app->session;// リクエスト #1// "alerts" という名前の下にフラッシュ・メッセージを追加する$session->addFlash('alerts', '投稿の削除に成功しました。');$session->addFlash('alerts', '友達の追加に成功しました。');$session->addFlash('alerts', 'あなたのレベルが上りました。');// リクエスト #2// $alerts は "alerts" という名前の下にあるフラッシュ・メッセージの配列となる$alerts = $session->getFlash('alerts');

補 足〺 同 じ 名 前 の フ ラ ッ シ ュ ・ デ ー タ に 対 し て 、べどどぜぷづぢ
ぜこづびびどはの〺〺びづぴうぬちびと〨〩 と べどどぜぷづぢぜこづびびどはの〺〺ちつつうぬちびと〨〩 を一緒に使わないようにしてください。 これは、後者のメソッドが、同じ名前のフラッシュ・データを追加できるように、
フラッシュ・データを自動的に配列に変換するからです。 その結果、べどどぜぷづぢぜこづびびどはの〺〺でづぴうぬちびと〨〩 を呼び出したとき、この二つのメソッドを呼び出した順序に従って、 あるときは配列を受け取り、あるときは文字列を受け取るということになります。
ヒント〺 フラッシュ・メッセージを表示するためには、べどど
ぜぢははぴびぴひちばぜぁぬづひぴ ウィジェットを次のように使用することが出来ます。

〴〮〶〮 セッションとクッキー〲〰〹

echo Alert::widget(['options' => ['class' => 'alert-info'],'body' => Yii::$app->session->getFlash('postDeleted'),
]);

4.6.2

クッキー

すどど は個々のクッキーを べどどぜぷづぢぜぃははにどづ のオブジェクトとして表します。 べどどぜぷづぢぜげづぱふづびぴ と べどどぜぷづぢぜげづびばはのびづ は、ともに、cookies という名前のプロパティによって、クッキーのコレクションを保持します。 前者のクッキー・コレクションはリクエストの中で送信されてきたクッキーを表し、 一方、後者のクッキー・コレクションは、これからユーザに送信されるクッキーを表します。
アプリケーションで、リクエストとレスポンスを直接に操作する部
分は、コントローラです。 従って、クッキーの読み出しと送信はコント
ローラで実行されるべきです。
クッキーを読み出す
現在のリクエストに含まれるクッキーは、下記のコードを使って取得することが出来ます。
// "request" コンポーネントからクッキー・コレクション(yii\web\CookieCollection) を取得する。
$cookies = Yii::$app->request->cookies;// "language" というクッキーの値を取得する。クッキーが存在しない場合は、デフォルト値として "en" を返す。
$language = $cookies->getValue('language', 'en');// "language" というクッキーの値を取得する別の方法。
if (($cookie = $cookies->get('language')) !== null) {$language = $cookie->value;}// $cookies を配列のように使うことも出来る。
if (isset($cookies['language'])) {$language = $cookies['language']->value;}// "language" というクッキーが在るかどうかチェックする。
if ($cookies->has('language')) ...
if (isset($cookies['language'])) ...

クッキーを送信する
下記のコードを使って、クッキーをエンド・ユーザに送信することが出
来ます。

〲〱〰

ぃえぁぐごぅげ 〴〮 リクエストの処理// "response" コンポーネントからクッキー・コレクション(yii\web\CookieCollection) を取得する。
$cookies = Yii::$app->response->cookies;// 送信されるレスポンスに新しいクッキーを追加する。
$cookies->add(new \yii\web\Cookie(['name' => 'language','value' => 'zh-CN',]));// クッキーを削除する。
$cookies->remove('language');// 次のようにしても同じ。
unset($cookies['language']);べどどぜぷづぢぜぃははにどづ クラスは、上記の例で示されている のちねづ と ぶちぬふづ のプ
ロパティ以外にも、つはねちどの や づへばどひづ など、 他のプロパティを定義して、利用可能なクッキー情報の全てを完全に表しています。 クッキーを準備するときに必要に応じてこれらのプロパティを構成してから、レス
ポンスのクッキー・コレクションに追加することが出来ます。
クッキー検証最後の二つの項で示されているように、request と response のコンポーネントを通じてクッキーを読んだり送信したりする場合には、 クッキーがクライアント・サイドで修正されるのを防止するクッキー検証という追加のセキュリティを享受することが出来ます。 これは、個々のクッキーにハッシュ文字列をサインとして追加することによって達成されます。
アプリケーションは、サインを見て、クッキーがクライアント・サイド
で修正されたかどうかを知ることが出来ます。 もし、修正されていれば、そのクッキーは request コンポーネントの クッキー・コレクション
からはアクセスすることが出来なくなります。
補足〺 クッキー検証は値が修正されたクッキーの読み込みを防止するだけです。 検証に失敗した場合でも、$_COOKIE を通じてそのクッキーにアクセスすることは引き続いて可能です。
これは、サードパーティのライブラリが、クッキー検証を含
まない独自の方法でクッキーを操作することが出来るようにするするためです。
クッキー検証はデフォルトで有効になっています。 べどどぜぷづぢぜげづぱふづびぴ〺〺〤づのちぢぬづぃははにどづざちぬどつちぴどはの プロパティを false に設定することによって無効にすることが出来ますが、無効にしないことを強く推奨します。
補足〺 $_COOKIE と setcookie() によって直接に 読み出し〯送信 されるクッキーは検証されません。

〴〮〶〮 セッションとクッキー〲〱〱

クッキー検証を使用する場合は、前述のハッシュ文字列を生成するために使用される べどどぜぷづぢぜげづぱふづびぴ〺〺〤っははにどづざちぬどつちぴどはのかづべ を指定しなければなりません。 アプリケーションの構成情報で request コンポーネントを構成することによって、そうすることが出来ます。
return ['components' => ['request' => ['cookieValidationKey' => 'ここに秘密のキーを書く',
],
],
];

情報〺 っははにどづざちぬどつちぴどはのかづべ は、あなたのアプリケーション
にとって、決定的に重要なものです。 これは信頼する人にだ
け教えるべきものです。バージョン・コントロール・システ
ムに保存してはいけません。

4.6.3

セキュリティの設定

べどどぜぷづぢぜぃははにどづ と べどどぜぷづぢぜこづびびどはの の両者は下記のセキュリティ・フラ
グをサポートしています。
とぴぴばくのぬべ
セキュリティを向上させるために、べどどぜぷづぢぜぃははにどづ〺〺〤とぴぴばくのぬべ および
べどどぜぷづぢぜこづびびどはの〺〺〤っははにどづぐちひちねび の だとぴぴばはのぬべ〧 パラメータの デフォル
ト値は true に設定されています。 これによって、クライアント・サイ
ド・スクリプトが保護されたクッキーにアクセスする危険が軽減されます 〨ブラウザがサポートしていれば〩。 詳細については、とぴぴばくのぬべ の ぷどにど
記事14 を読んでください。
びづっふひづ
びづっふひづ フラグの目的は、クッキーが平文で送信されることを防止することです。ブラウザが びづっふひづ フラグをサポートしている場合、 リクエスト
が びづっふひづ な接続 〨ごがこ〩 によって送信される場合にのみクッキーがリクエ
ストに含まれます。 詳細については こづっふひづ フラグの ぷどにど 記事15 を参照
して下さい。
びちねづこどぴづ
すどど 〲〮〰〮〲〱 以降、べどどぜぷづぢぜぃははにどづ〺〺〤びちねづこどぴづ 設定がサポートされています。これは ぐえぐ バージョン 〷〮〳〮〰 以降を必要とします。 sameSite 設定
14
15

https://owasp.org/www-community/HttpOnly
https://owasp.org/www-community/controls/SecureCookieAttribute〲〱〲

ぃえぁぐごぅげ 〴〮 リクエストの処理の目的は ぃこげう 〨ぃひはびび〭こどぴづ げづぱふづびぴ うはひでづひべ〩 攻撃を防止することです。
ブラウザが sameSite 設定をサポートしている場合、指定されたポリシー〨〧がちへ〧 または だこぴひどっぴ〧〩 に従うクッキーだけが送信されます。 詳細については こちねづこどぴづ の ぷどにど 記事16 を参照して下さい。 更なるセキュリティ強化のために、sameSite がサポートされていない ぐえぐ のバージョンで使われた場合には例外が投げられます。 この機能を ぐえぐ のバージョンに関
わりなく使用する場合は、最初にバージョンをチェックして下さい。例
えば、 `ばとば せ'sameSite' => PHP_VERSION_ID >= 70300 ? yii\web\Cookie::SAME_SITE_LAX :null,

そ ` 〾 ぎはぴづ〺 今はまだ sameSite 設定をサポートしていないブラウザもありますので、 追加の ぃこげう 保護 を行うことを強く推奨します。

4.6.4

セッションに関する php.ini の設定

ぐえぐ マニュアル17 で示されているように、php.ini にはセッションのセ
キュリティに関する重要な設定があります。 推奨される設定を必ず適用して下さい。特に、ぐえぐ インストールのデフォルトでは有効にされていない session.use_strict_mode を有効にして下さい。 この設定は べどどぜぷづぢ
ぜこづびびどはの〺〺〤ふびづこぴひどっぴきはつづ を使って設定することも出来ます。

4.7

エラー処理

すどど が内蔵している エラー・ハンドラ は、エラー処理を従来よりはるかに快適な経験にしてくれます。 具体的には、すどど のエラー・ハンドラはエラー処理をより良くするために、次のことを行います。
• 致命的でない全ての ぐえぐ エラー 〨警告や通知〩 は捕捉可能な例外に変換されます。
• 例外および致命的 ぐえぐ エラーは、デバッグ・モードでは、 詳細な
コール・スタック情報とソース・コード行とともに表示されます。
• エラーを表示するために専用の コントローラ・アクション を使うことがサポートされています。
• さまざまなエラー・レスポンス形式をサポートしています。
エラー・ハンドラ はデフォルトで有効になっています。 アプリケーショ
ンの エントリ・スクリプト において、定数 YII_ENABLE_ERROR_HANDLER を
false と定義することによって、これを無効にすることが出来ます。

4.7.1

エラー・ハンドラを使用する

エラー・ハンドラ は errorHandler という名前の アプリケーション・コン
ポーネント です。 次のように、アプリケーションの構成情報でこれをカ
16
17

https://owasp.org/www-community/SameSite
https://www.php.net/manual/ja/session.security.ini.php〴〮〷〮 エラー処理〲〱〳

スタマイズすることが出来ます。
return ['components' => ['errorHandler' => ['maxSourceLines' => 20,
],
],
];

上記の構成によって、例外ページで表示されるソース・コードの行数は最大で 〲〰 までとなります。
既に述べたように、エラー・ハンドラは致命的でない全ての ぐえぐ エ
ラーを捕捉可能な例外に変換します。 これは、次のようなコードを使って ぐえぐ エラーを処理することが出来るということを意味します。
use Yii;
use yii\base\ErrorException;
try {
10/0;
} catch (ErrorException $e) {Yii::warning("0 による除算。");}// 実行を継続 ...

リクエストが無効または予期しないものであることをユーザに知らせる
エラー・ページを表示したい場合は、 単に べどどぜぷづぢぜぎはぴうはふのつえぴぴばぅへっづばぴどはののような えごごぐ 例外 を投げるだけで済ませることが出来ます。 そうすれば、エラー・ハンドラがレスポンスの えごごぐ ステータス・コードを正しく設定し、 適切なエラー・ビューを使ってエラー・メッセージを表示してくれます。
use yii\web\NotFoundHttpException;
throw new NotFoundHttpException();

4.7.2

エラー表示をカスタマイズする

エラー・ハンドラ は、定数 YII_DEBUG の値に従って、エラー表示を調整します。 YII_DEBUG が true である 〨デバッグ・モードである〩 場合は、エラー・ハンドラは、デバッグがより容易になるように、 例外とともに、
詳細なコール・スタック情報とソース・コード行を表示します。 そして、YII_DEBUG が false のときは、アプリケーションに関する公開できな
い情報の開示を防ぐために、エラー・メッセージだけが表示されます。
情 報〺 例 外 が べどどぜぢちびづぜさびづひぅへっづばぴどはの の 子 孫 で あ る 場 合
は、YII_DEBUG の値の如何にかかわらず、コール・スタック

〲〱〴ぃえぁぐごぅげ 〴〮 リクエストの処理は表示されません。 これは、この種の例外はユーザの誤操作によって引き起こされるものであり、 開発者は何も修正する必要がないと考えられるからです。

デフォルトでは、エラー・ハンドラ は二つの ビュー を使ってエラーを表示します。
• @yii/views/errorHandler/error.php〺 エラーがコール・スタック情報なしで表示されるべき場合に使用されます。 YII_DEBUG が false の場
合、これが表示される唯一のビューとなります。
• @yii/views/errorHandler/exception.php〺 エラーがコール・スタック情報と共に表示されるべき場合に使用されます。
エラー表示をカスタマイズするために、エラー・ハンドラの づひひはひざどづぷ
および づへっづばぴどはのざどづぷ プロパティを構成して、 自分自身のビューを使用することが出来ます。
エラー・アクションを使う
エラー表示をカスタマイズするためのもっと良い方法は、専用のエラー
アクション を使うことです。 そうするためには、まず、errorHandler コ
ンポーネントの づひひはひぁっぴどはの プロパティを次のように構成します。
return ['components' => ['errorHandler' => ['errorAction' => 'site/error',],]];

づひひはひぁっぴどはの プロパティは、アクションへの ルート を値として取ります。 上記の構成は、エラーをコール・スタック情報なしで表示する必要がある場合は、 site/error アクションが実行されるべきことを記述しています。
site/error アクションは次のようにして作成することが出来ます。
namespace app\controllers;
use Yii;
use yii\web\Controller;class SiteController extends Controller{
public function actions(){
return ['error' => ['class' => 'yii\web\ErrorAction',],];〴〮〷〮 エラー処理

}

〲〱〵

}

上記のコードは べどどぜぷづぢぜぅひひはひぁっぴどはの クラスを使って error アクションを定義しています。 べどどぜぷづぢぜぅひひはひぁっぴどはの クラスは error という名前のビューを使ってエラーをレンダリングします。
べどどぜぷづぢぜぅひひはひぁっぴどはの を使う以外に、次のようにアクション・メソッ
ドを使って error アクションを定義することも出来ます。
public function actionError(){$exception = Yii::$app->errorHandler->exception;if ($exception !== null) {return $this->render('error', ['exception' => $exception]);}}

次に views/site/error.php に配置されるビュー・ファイルを作成しなければなりません。 エラー・アクションが べどどぜぷづぢぜぅひひはひぁっぴどはの として定義されている場合は、このビュー・ファイルの中で次の変数にアクセスすることが出来ます。
• name〺 エラーの名前。
• message〺 エラー・メッセージ。
• exception〺 例外オブジェクト。これを通じて、更に有用な情報、例
えば、えごごぐ ステータス・コード、エラー・コード、 エラー・コー
ル・スタックなどにアクセスすることが出来ます。
情報〺 あなたが ベーシック・プロジェクト・テンプレート ま
たは アドバンスト・プロジェクト・テンプレート18 を使っている場合は、 エラー・アクションとエラー・ビューは、既にあなたのために定義されています。
補足〺 エラー・ハンドラの中でリダイレクトする必要がある場
合は、次のようにしてください。
Yii::$app->getResponse()->redirect($url)->send();return;

エラーのレスポンス形式をカスタマイズする
エラー・ハンドラは、レスポンス 形式の設定に従ってエラーを表示します。 レスポンス形式 が html である場合は、直前の項で説明したように、 エラー・ビューまたは例外ビューを使ってエラーを表示します。 その他のレスポンス形式の場合は、エラー・ハンドラは例外の配列表現を
べどどぜぷづぢぜげづびばはのびづ〺〺〤つちぴち プロパティに代入し、 次に data プロパティを
18
https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/
README.md〲〱〶

ぃえぁぐごぅげ 〴〮 リクエストの処理

様々な形式に変換します。 例えば、レスポンス形式が json である場合
は、次のようなレスポンスになります。
HTTP/1.1 404 Not Found
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8{}"name": "Not Found Exception","message": "リクエストされたリソースは見つかりませんでした。","code": 0,"status": 404

エラーのレスポンス形式をカスタマイズするために、アプリケーションの構成情報の中で、 response コンポーネントの beforeSend イベントに反応するハンドラを構成することが出来ます。
return [// ...
'components' => ['response' => ['class' => 'yii\web\Response','on beforeSend' => function ($event) {$response = $event->sender;
if ($response->data !== null) {$response->data = ['success' => $response->isSuccessful,'data' => $response->data,];$response->statusCode = 200;
}
},
],
],
];

上記のコードは、エラーのレスポンスを以下のようにフォーマットし直すものです。
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8{"success": false,"data": {"name": "Not Found Exception",〴〮〸〮 ロギング

}

}

4.8

〲〱〷

"message": "リクエストされたリソースは見つかりませんでした。","code": 0,"status": 404

ロギング

すどど は高度なカスタマイズ性と拡張性を持った強力なロギング・フレームワークを提供しています。 このフレームワークを使用すると、さまざまな種類のメッセージを記録し、それをフィルタして、ファイル、データ
ベース、メールなど、 さまざまなターゲットに収集することが簡単に出来ます。
すどど のロギング・フレームワークを使うためには、下記のステップを踏みます。
• コードのさまざまな場所で ログ・メッセージ を記録する。
• ログ・メッセージをフィルタしてエクスポートするために、アプリ
ケーションの構成情報で ログ・ターゲット を構成する。
• さまざまなターゲット 〨例えば すどど デバッガ〩 によって、フィルタされエクスポートされたログ・メッセージを調査する。
このセクションでは、主として最初の二つのステップについて説明しま
す。

4.8.1

メッセージを記録する

ログ・メッセージを記録することは、次のログ記録メソッドのどれかを呼び出すだけの簡単なことです。
• すどど〺〺つづぢふで〨〩〺 コードの断片がどのように走ったかをトレースする
メッセージを記録します。主として開発のために使用します。
• すどど〺〺どのては〨〩〺 何らかの有用な情報を伝えるメッセージを記録します。
• すどど〺〺ぷちひのどので〨〩〺 何か予期しないことが発生したことを示す警告
メッセージを記録します。
• すどど〺〺づひひはひ〨〩〺 出来るだけ早急に調査すべき致命的なエラーを記録します。
これらのログ記録メソッドは、ログ・メッセージをさまざまな 重大性
レベル と カテゴリ で記録するものです。 これらのメソッドは function($message, $category = 'application') という関数シグニチャを共有しており、 $message は記録されるログ・メッセージを示し、$category はログ・
メッセージのカテゴリを示します。 次のコード・サンプルは、トレース・メッセージをデフォルトのカテゴリである application の下に記録するものです。
Yii::debug('平均収益の計算を開始');〲〱〸ぃえぁぐごぅげ 〴〮 リクエストの処理
情報〺 ログ・メッセージは文字列でも、配列やオブジェクトのような複雑なデータでも構いません。 ログ・メッセージを適切に取り扱うのは ログ・ターゲット の責任です。 デフォルト
では、ログ・メッセージが文字列でない場合は、べどどぜとづぬばづひび
ぜざちひいふねばづひ〺〺づへばはひぴ〨〩 が呼ばれて文字列に変換されることになります。

ログ・メッセージを上手に編成しフィルタするために、すべてのログ・
メッセージにそれぞれ適切なカテゴリを指定することが推奨されます。
カテゴリに階層的な命名方法を採用すると、ログ・ターゲット がカテゴリに基づいてメッセージをフィルタすることが容易になります。 簡
単でしかも効果的な命名方法は、カテゴリ名に ぐえぐ のマジック定数__METHOD__ を使用することです。 これは、すどど フレームワークのコアコードでも使われている方法です。 例えば、
Yii::debug('平均収益の計算を開始', __METHOD__);__METHOD__ という定数は、それが出現する場所のメソッド名 〨完全修飾のクラス名が前置されます〩 として評価されます。 例えば、上記のコードがapp\controllers\RevenueController::calculate というメソッドの中で呼ばれている場合は、 __METHOD__ は 'app\controllers\RevenueController::calculate'という文字列と同じになります。
情報〺 上記で説明したメソッドは、実際には、ロガー・オ
ブジェクト の ぬはで〨〩 メソッドへのショートカットです。 ロ
ガー・オブジェクト は Yii::getLogger() という式でアクセス可
能なシングルトンです。 ロガー・オブジェクトは、十分な量のメッセージが記録されたとき、または、アプリケーションが終了するときに、 メッセージ・ディスパッチャ を呼んで、登録された ログ・ターゲット に記録されたログ・メッセージを送信します。

4.8.2

ログ・ターゲット

ログ・ターゲットは べどどぜぬはでぜごちひでづぴ クラスまたはその子クラスのインスタンスです。 ログ・ターゲットは、ログ・メッセージを重大性レベルとカテゴリによってフィルタして、何らかの媒体にエクスポートします。
例えば、データベース・ターゲット は、フィルタされたログ・メッセー
ジをデータベース・テーブルにエクスポートし、 メール・ターゲット
は、ログ・メッセージを指定されたメール・アドレスにエクスポートします。
一つのアプリケーションの中で複数のログ・ターゲットを登録することが出来ます。 そのためには、次のように、アプリケーションの構成情報の中で、log アプリケーション・コンポーネント によってログ・ター
ゲットを構成します。

〴〮〸〮 ロギング〲〱〹return [// "log" コンポーネントはブートストラップ時にロードされなければならない'bootstrap' => ['log'],// "log" コンポーネントはタイムスタンプを持つメッセージを処理するので、正しいタイムスタンプを出力するように PHP タイムゾーンを設定'timeZone' => 'America/Los_Angeles','components' => ['log' => ['targets' => [['class' => 'yii\log\DbTarget','levels' => ['error', 'warning'],],['class' => 'yii\log\EmailTarget','levels' => ['error'],'categories' => ['yii\db\*'],'message' => ['from' => ['log@example.com'],'to' => ['admin@example.com','developer@example.com'],'subject' => 'example.com で、データベースエラー発生',
],
],
],
],
],
];

補足〺 log コンポーネントは、ログ・メッセージをターゲットに即座に送付することが出来るように、ブートストラップ 時にロードされなければなりません。 上記の例で bootstrap の配列に log がリストアップされているのは、そのためです。
上記のコードでは、二つのログ・ターゲットが べどどぜぬはでぜいどびばちぴっとづひ〺〺〤ぴちひでづぴび プロパティに登録されています。
• 最初のターゲットは、エラーと警告のメッセージを選択して、デー
タベース・テーブルに保存します。
• 第二のターゲットは、名前が yii\db\ で始まるカテゴリのエラー・メッセージを選んで、admin@example.com と developer@example.com の両方にメールで送信します。
すどど は下記のログ・ターゲットをあらかじめ内蔵しています。 その構成方法と使用方法を学ぶためには、これらのクラスの ぁぐぉ ドキュメントを参照してください。
• べどどぜぬはでぜいぢごちひでづぴ〺 ログ・メッセージをデータベース・テーブルに保存する。
• べどどぜぬはでぜぅねちどぬごちひでづぴ〺 ログ・メッセージを事前に指定されたメー
ル・アドレスに送信する。
• べどどぜぬはでぜうどぬづごちひでづぴ〺 ログ・メッセージをファイルに保存する。

〲〲〰

ぃえぁぐごぅげ 〴〮 リクエストの処理• べどどぜぬはでぜこべびぬはでごちひでづぴ〺 ログ・メッセージを ぐえぐ 関数 syslog() を呼んでシステム・ログに保存する。
以下では、全てのターゲットに共通する機能について説明します。
メッセージのフィルタリング
全てのログ・ターゲットについて、それぞれ、ぬづぶづぬび と っちぴづではひどづび のプロパティを構成して、 ターゲットが処理すべきメッセージの重要性レ
ベルとカテゴリを指定することが出来ます。
ぬづぶづぬび プロパティは、次のレベルの一つまたは複数からなる配列を値として取ります。
• error〺 すどど〺〺づひひはひ〨〩 によって記録されたメッセージに対応。
• warning〺 すどど〺〺ぷちひのどので〨〩 によって記録されたメッセージに対応。
• info〺 すどど〺〺どのては〨〩 によって記録されたメッセージに対応。
• trace〺 すどど〺〺つづぢふで〨〩 によって記録されたメッセージに対応。
• profile〺 すどど〺〺ぢづでどのぐひはてどぬづ〨〩 と すどど〺〺づのつぐひはてどぬづ〨〩 によって記録されたメッセージに対応。 これについては、プロファイリング の項で詳細に説明します。
ぬづぶづぬび プロパティを指定しない場合は、 ターゲットが 全ての 重大性レ
ベルのメッセージを処理することを意味します。
っちぴづではひどづび プロパティは、メッセージ・カテゴリの名前またはパターンからなる配列を値として取ります。 ターゲットは、カテゴリの名前がこの配列にあるか、または配列にあるパターンに合致する場合にだけ、メッセージを処理します。 カテゴリ・パターンというのは、最後にアスタリスク * を持つカテゴリ名接頭辞です。 カテゴリ名は、パターンと同じ接頭辞で始まる場合に、カテゴリ・パターンに合致します。 例えば、yii\db\Command::execute と yii\db\Command::query は、べどどぜつぢ
ぜぃはねねちのつ クラスで記録されるログ・メッセージのためのカテゴリ名です。 そして、両者は共に yii\db\* というパターンに合致します。
っちぴづではひどづび プロパティを指定しない場合は、 ターゲットが 全ての カ
テゴリのメッセージを処理することを意味します。
処理するカテゴリを っちぴづではひどづび プロパティで指定する以外に、 処理から除外するカテゴリを づへっづばぴ プロパティによって指定することも可能です。 カテゴリの名前がこの配列にあるか、または配列にあるパターンに合致する場合は、メッセージはターゲットによって処理されません。
次のターゲットの構成は、ターゲットが、yii\db\* または yii\web\HttpException:*に合致するカテゴリ名を持つエラーおよび警告のメッセージだけを処理すべきこと、 ただし、yii\web\HttpException:404 は除外すべきことを指定するものです。
['class' => 'yii\log\FileTarget','levels' => ['error', 'warning'],'categories' => ['yii\db\*',〴〮〸〮 ロギング]〲〲〱

'yii\web\HttpException:*',],'except' => ['yii\web\HttpException:404',],

情報〺 えごごぐ 例外が エラー・ハンドラ によって捕捉されたときは、 yii\web\HttpException:ErrorCode という書式のカテゴリ
名でエラー・メッセージがログに記録されます。 例えば、べどど
ぜぷづぢぜぎはぴうはふのつえぴぴばぅへっづばぴどはの は、yii\web\HttpException:404 というカテゴリのエラー・メッセージを発生させます。
メッセージの書式設定
ログ・ターゲットはフィルタされたログ・メッセージを一定の書式でエクスポートします。 例えば、べどどぜぬはでぜうどぬづごちひでづぴ クラスのログ・ター
ゲットをインストールした場合は、 runtime/log/app.log ファイルに、下記と同様なログ・メッセージが書き込まれます。
2014-10-04 18:10:15 [::1][][-][trace][yii\base\Module::getModule] Loading
module: debug

デフォルトでは、ログ・メッセージは べどどぜぬはでぜごちひでづぴ〺〺てはひねちぴきづびびちでづ〨〩
によって、下記のように書式設定されます。
タイムスタンプ [IP アドレス][ユーザ ID][セッション ID][重要性レベル][カテゴリ]
メッセージテキスト

この書式は、べどどぜぬはでぜごちひでづぴ〺〺〤ばひづてどへ プロパティを構成することでカスタマイズすることが出来ます。 べどどぜぬはでぜごちひでづぴ〺〺〤ばひづてどへ プロパティ
は、カスタマイズされたメッセージ前置情報を返す ぐえぐ コーラブルを値として取ります。 例えば、次のコードは、ログ・ターゲットが全てのログ・メッセージの前にカレント・ユーザの ぉい を置くようにさせるものです〨ぉぐ アドレスとセッション ぉい はプライバシー上の理由から削除されて
います〩。
[

]

'class' => 'yii\log\FileTarget','prefix' => function ($message) {$user = Yii::$app->has('user', true) ? Yii::$app->get('user') :null;$userID = $user ? $user->getId(false) : '-';
return "[$userID]";}

メッセージ前置情報以外にも、ログ・ターゲットは、一群のログ・メッ
セージごとに一定のコンテキスト情報を追加します。 デフォルトでは、〲〲〲

ぃえぁぐごぅげ 〴〮 リクエストの処理

その情報には、次のグローバル ぐえぐ 変数、すなわち、$_GET、$_POST、$_FILES、$_COOKIE、$_SES
および $_SERVER の値が含まれます。 ログ・ターゲットに含ませたいグ
ローバル変数の名前を べどどぜぬはでぜごちひでづぴ〺〺〤ぬはでざちひび プロパティに設定することによって、 この動作を調整することが出来ます。 例えば、次のロ
グ・ターゲットの構成は、$_SERVER の値だけをログ・メッセージに追加するように指定するものです。
[]'class' => 'yii\log\FileTarget','logVars' => ['_SERVER'],

logVars を空の配列として構成して、コンテキスト情報をまったく含ませないようにすることも出来ます。 あるいは、また、コンテキ
ス ト 情 報 の 提 供 方 法 を 自 分 で 実 装 し た い 場 合 は 、 べどどぜぬはでぜごちひでづぴ〺〺
でづぴぃはのぴづへぴきづびびちでづ〨〩 メソッドをオーバーライドすることも出来ます。
ログに出力したくない機密情報 〨例えば、パスワードやアクセス・
トークン〩 を含んでいるリクエストのフィールドについては、maskVars プ
ロパティを追加で構成することが出来ます。 デフォルトでは、$_SERVER[HTTP_AUTHORIZATION]、$のリクエスト・パラメータが *** でマスクされまが、 自分自身で設定することも出来ます。例えば、[]'class' => 'yii\log\FileTarget','logVars' => ['_SERVER'],'maskVars' => ['_SERVER.HTTP_X_PASSWORD']

メッセージのトレース・レベル
開発段階では、各ログ・ メッセージ がどこから来ている かを知りたい場合がよくあります。 これは、次のように、log コンポーネントのぴひちっづがづぶづぬ プロパティを構成することによって達成できます。
return ['bootstrap' => ['log'],'components' => ['log' => ['traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [...],
],
],
];

上記のアプリケーションの構成は、ぴひちっづがづぶづぬ を YII_DEBUG が はの のときは 〳、YII_DEBUG が は〛 のときは 〰 に設定します。 これは、YII_DEBUG が はののときは、各ログ・メッセージに対して、ログ・メッセージが記録されたときのコール・スタックを最大 〳 レベルまで追加し、 YII_DEBUG が 〰 のときはコール・スタックを含めない、 ということを意味します。

〲〲〳〴〮〸〮 ロギング
情報〺 コール・スタック情報の取得は軽微な処理ではありません。 従って、この機能は開発時またはアプリケーションをデバッグするときに限って使用するべきです。
メッセージの吐き出しとエクスポート

既に述べたように、ログ・メッセージは ロガー・オブジェクト によって配列の中に保持されます。 この配列のメモリ消費を制限するために、この配列に一定数のログ・メッセージが蓄積されるたびに、 ロガーは記録されたメッセージを ログ・ターゲット に吐き出します。 この数は、log
コンポーネントの てぬふびとぉのぴづひぶちぬ プロパティを構成することによってカスタマイズすることが出来ます。
return ['bootstrap' => ['log'],'components' => ['log' => ['flushInterval' => 100,
'targets' => [...],
],
],
];

// デフォルトは 1000

情報〺 メッセージの吐き出しは、アプリケーションの終了時にも実行されます。これによって、ログ・ターゲットが完全な
ログ・メッセージを受け取ることが保証されます。
ロガー・オブジェクト が ログ・ターゲット にログ・メッセージを吐き出しても、ログ・メッセージはただちにはエクスポートされません。 そうではなく、ログ・ターゲットが一定数のフィルタされたメッセージを蓄積して初めて、メッセージのエクスポートが発生します。 この数は、下記のように、個々の ログ・ターゲット の づへばはひぴぉのぴづひぶちぬ プロパティを構成することによってカスタマイズすることが出来ます。
[]'class' => 'yii\log\FileTarget','exportInterval' => 100, // デフォルトは 1000

デフォルトの状態では、吐き出しとエクスポートの間隔の設定のために、Yii::debug() やその他のログ記録メソッドを呼んでも、 ただちには、ログ・メッセージはログ・ターゲットに出現しません。 このこと
は、長時間にわたって走るコンソール・アプリケーションでは、問題になる場合もあります。 各ログ・メッセージがただちにログ・ターゲッ
トに出現するようにするためには、下記のように、てぬふびとぉのぴづひぶちぬ とづへばはひぴぉのぴづひぶちぬ の両方を 〱 に設定しなければなりません。

〲〲〴

ぃえぁぐごぅげ 〴〮 リクエストの処理

return ['bootstrap' => ['log'],'components' => ['log' => ['flushInterval' => 1,'targets' => [['class' => 'yii\log\FileTarget','exportInterval' => 1,
],
],
],
],
];

補足〺 頻繁なメッセージの吐き出しとエクスポートはアプリ
ケーションのパフォーマンスを低下させます。
ログ・ターゲットの 有効〯無効 を切り替える
づのちぢぬづつ プロパティを構成することによって、ログ・ターゲットを有効にしたり無効にしたりすることが出来ます。 この切り替えは、ログ・ターゲットのコンフィギュレーションでも出来ますが、コードの中で次の ぐえぐ 文を使っても出来ます。
Yii::$app->log->targets['file']->enabled = false;

上記のコードでは、ターゲットが file という名前であることが必要とされています。 下記のように、targets の配列で文字列のキーを使ってターゲットの名前を指定して下さい。
return ['bootstrap' => ['log'],'components' => ['log' => ['targets' => ['file' => ['class' => 'yii\log\FileTarget',],'db' => ['class' => 'yii\log\DbTarget',
],
],
],
],
];

バージョン 〲〮〰〮〱〳 以降は、づのちぢぬづつ を設定するのに、 ログ・ターゲットを有効にすべきか否かの動的な条件を定義するコーラブルを指定することが可能です。 べどどぜぬはでぜごちひでづぴ〺〺びづぴぅのちぢぬづつ〨〩 のドキュメントに一例がありますので参照して下さい。

〴〮〸〮 ロギング〲〲〵

新しいターゲットを作る
新しいログ・ターゲット・クラスを作ることは非常に簡単です。 必要なことは、主として、べどどぜぬはでぜごちひでづぴ〺〺〤ねづびびちでづび 配列の中身を指定された媒体に送出する べどどぜぬはでぜごちひでづぴ〺〺づへばはひぴ〨〩 メソッドを実装することです。 各メッセージに書式を設定するためには、べどどぜぬはでぜごちひでづぴ〺〺てはひねちぴきづびびちでづ〨〩 を呼ぶことが出来ます。 詳細については、すどど リリー
スに含まれているログ・ターゲット・クラスのどれか一つを参照してください。
ヒント〺 あなた自身のロガーを書く代りに、ぐこげ ログ・ター
ゲット・エクステンション19 によって、 きはのはぬはで20 のようなぐこげ〭〳 互換ロガーのどれかを使ってみるのも良いでしょう。

4.8.3

パフォーマンス・プロファイリング

パフォーマンス・プロファイリングは、特定のコード・ブロックに要した時間を測定してパフォーマンスのボトルネックになっている所を見つけ出すために使われる、 特殊なタイプのメッセージ・ロギングです。 例
えば、べどどぜつぢぜぃはねねちのつ クラスは、各 いあ クエリに要した時間を知るために、パフォーマンス・プロファイリングを使用しています。
パフォーマンス・プロファイリングを使用するためには、最初に、
プロファイリングが必要なコード・ブロックを特定します。 そして、各
コード・ブロックを次のように囲みます。
\Yii::beginProfile('myBenchmark');... プロファイリングされるコード・ブロック ...
\Yii::endProfile('myBenchmark');

ここで myBenchmark はコード・ブロックを特定するユニークなトークンを表します。 後でプロファイリング結果を検査するときに、このトークンを使って、対応するコード・ブロックによって消費された時間を調べます。
beginProfile と endProfile のペアが適正な入れ子になっていることを確認することが非常に重要なことです。 例えば、
\Yii::beginProfile('block1');// プロファイリングされる何らかのコード\Yii::beginProfile('block2');// プロファイリングされる別のコード\Yii::endProfile('block2');\Yii::endProfile('block1');
1920

https://github.com/samdark/yii2-psr-log-target
https://github.com/Seldaek/monolog

〲〲〶ぃえぁぐごぅげ 〴〮 リクエストの処理\Yii::endProfile('block1') を忘れたり、\Yii::endProfile('block1') と \Yii::endProfile('block2')の順序を入れ替えたりすると、 パフォーマンス・プロファイリングは機能しません。
プロファイルされるコード・ブロックの全てについて、おのおの、重大性レベルが profile であるログ・メッセージが記録されます。 そのようなメッセージを集めてエクスポートする ログ・ターゲット を構成してください。 すどど デバッガ が、プロファイリング結果を表示するパフォー
マンス・プロファイリング・パネルを内蔵しています。

Chapter 5

鍵となる概念5.1

コンポーネントコンポーネントは、すどどアプリケーションの主要な構成ブロックです。コンポーネントは べどどぜぢちびづぜぃはねばはのづのぴ 、 またはその派生クラスのインスタンスです。コンポーネントが他のクラスに提供する主な機能は次の 〳つです〺• プロパティ• イベント• ビヘイビア
個々にでも、組み合わせでも、これらの機能は すどど のクラスのカスタマ
イズ性と使いやすさをとても高めてくれます。 たとえば、ユーザ・イン
タフェイス·コンポーネントである べどどぜなふどぜいちぴづぐどっにづひ は、 ビュー で次のように使用して、対話型の日付選択 さぉ を生成することができます〺
use yii\jui\DatePicker;
echo DatePicker::widget(['language' => 'ja','name' => 'country','clientOptions' => ['dateFormat' => 'yy-mm-dd',],]);

クラスが べどどぜぢちびづぜぃはねばはのづのぴ を継承しているおかげで、ウィジェットのプロパティは簡単に記述できます。
コンポーネントは非常に強力ですが、 イベント と ビヘイビア をサポートするため、 余分にメモリと ぃぐさ 時間を要し、通常のオブジェ
クトよりも少し重くなります。 あなたのコンポーネントがこれら〲つの機能を必要としない場合、べどどぜぢちびづぜぃはねばはのづのぴ の代わりに、 べどどぜぢちびづ
ぜあちびづくぢなづっぴ からコンポーネント・クラスを派生することを検討してもよいでしょう。 そうすることで、あなたのコンポーネントは、 プロパ
〲〲〷

〲〲〸

ぃえぁぐごぅげ 〵〮 鍵となる概念

ティ のサポートが維持されたまま、通常の ぐえぐ オブジェクトのように効率的になります。
べどどぜぢちびづぜぃはねばはのづのぴ または べどどぜぢちびづぜあちびづくぢなづっぴ からクラスを派生するときは、 次の規約に従うことが推奨されます〺• コンストラクタをオーバーライドする場合は、コンストラクタの 最後の パラメータとして $config パラメータを指定し、 親のコンスト
ラクタにこのパラメータを渡すこと。
• 自分がオーバーライドしたコンストラクタの 最後で 、必ず親クラスのコンストラクタを呼び出すこと。
• べどどぜぢちびづぜあちびづくぢなづっぴ〺〺どのどぴ〨〩 メソッドをオーバーライドする場合
は、自分の init() メソッドの 最初に 、必ず init() の親実装を呼び出すようにすること。
例えば、
<?php
namespace yii\components\MyClass;use yii\base\BaseObject;class MyClass extends BaseObject{
public $prop1;
public $prop2;
public function __construct($param1, $param2, $config = []){// ... 構成前の初期化}

parent::__construct($config);

public function init(){
parent::init();}}// ... 構成後の初期化

このガイドラインに従うことで、あなたのコンポーネントは生成時に コンフィグ可能 になります。例えば、$component = new MyClass(1, 2, ['prop1' => 3, 'prop2' => 4]);// あるいは、また$component = \Yii::createObject(['class' => MyClass::class,'prop1' => 3,'prop2' => 4,], [1, 2]);〵〮〲〮 プロパティ〲〲〹

補足〺 すどど〺〺っひづちぴづくぢなづっぴ〨〩 を呼び出すアプローチは複雑に見えますが、より強力です。 というのも、それが 依存性注入
コンテナ 上に実装されているからです。
べどどぜぢちびづぜあちびづくぢなづっぴ クラスには、次のオブジェクト・ライフサイクルが適用されます〺〱〮 コンストラクタ内の事前初期化。ここでデフォルトのプロパティ値を設定することができます。
〲〮 $config によるオブジェクトの構成。構成情報は、コンストラクタ内で設定されたデフォルト値を上書きすることがあります。
〳〮 どのどぴ〨〩 内の事後初期化。サニティ・チェックやプロパティの正規化を行いたいときは、このメソッドをオーバーライドします。
〴〮 オブジェクトのメソッド呼び出し。
最初の 〳 つのステップは、すべて、オブジェクトのコンストラクタ内で発生します。これは、あなたがクラス・インスタンス 〨つまり、オブジェ
クト〩 を得たときには、 すでにそのオブジェクトが適切な、信頼性の高い状態に初期化されていることを意味します。

5.2

プロパティ

ぐえぐでは、クラスのメンバ変数は プロパティ とも呼ばれます。 これらの変数は、クラス定義の一部で、クラスのインスタンスの状態を表すた
めに〨すなわち、クラスのあるインスタンスを別のものと区別するために〩使用されます。 現実には、特別な方法でこのプロパティの読み書きを扱いたい場合がよくあります。 たとえば、label プロパティに割り当てられる文字列が常にトリミングされるようにしたい、など。 その仕事を成し遂げるために、あなたは次のようなコードを使おうと思えば使うことも出来ます。
$object->label = trim($label);

上記のコードの欠点は、label プロパティを設定するすべてのコードで、trim() を呼び出す必要があるということです。 もし将来的に、label
プロパティに、最初の文字を大文字にしなければならない、といった新たな要件が発生したら、 label に値を代入するすべてのコードを変更しなければなりません。 コードの繰り返しはバグを誘発するので、可能な限
り避けたいところです。
この問題を解決するために、すどど は getter メソッドと setter メソッド
をベースにしたプロパティ定義をサポートする、 べどどぜぢちびづぜあちびづくぢなづっぴ
基底クラスを提供しています。 クラスがその機能を必要とするなら、べどど
ぜぢちびづぜあちびづくぢなづっぴ またはその子クラスを継承しましょう。

〲〳〰

ぃえぁぐごぅげ 〵〮 鍵となる概念
補足〺 すどどのフレームワークのほぼすべてのコア・クラスは、
べどどぜぢちびづぜあちびづくぢなづっぴ ま た は そ の 子 ク ラ ス を 継 承 し て い ま
す。 これは、コア・クラスに でづぴぴづひ または びづぴぴづひ があれば、それをプロパティのように使用できることを意味します。

でづぴぴづひ メソッドは、名前が get で始まるメソッドで、びづぴぴづひ メソッド
は 、set で 始 ま る メ ソ ッ ド で す 。 get ま た は set 接 頭 辞 の 後 の 名 前で、プ ロパティ名を定義します 。次のコー ドに示すよう に、たとえば、getLabel() という でづぴぴづひ と setLabel() という びづぴぴづひ は、 label という名前のプロパティを定義します〺
namespace app\components;
use yii\base\BaseObject;class Foo extends BaseObject{
private $_label;public function getLabel(){
return $this->_label;}}public function setLabel($value){$this->_label = trim($value);}

詳しく言うと、でづぴぴづひ および びづぴぴづひ メソッドは、この場合には、内部的に_label と名付けられた ばひどぶちぴづ な属性を参照する label というプロパティを作っています。
でづぴぴづひ と びづぴぴづひ によって定義されたプロパティは、クラスのメンバ変数のように使用することができます。主な違いは、 それらのプロパティ
が読み取りアクセスされるときは、対応する でづぴぴづひ メソッドが呼び出されることであり、プロパティに値が割り当てられるときには、 対応する
びづぴぴづひ メソッドが呼び出されるということです。例えば、// $label = $object->getLabel(); と同じ$label = $object->label;// $object->setLabel('abc'); と同じ$object->label = 'abc';

びづぴぴづひ なしの でづぴぴづひ で定義されたプロパティは、 読み取り専用 です。そのようなプロパティに値を代入しようとすると、 ぉのぶちぬどつぃちぬぬぅへっづばぴどはのが発生します。同様に、でづぴぴづひ なしの びづぴぴづひ で定義されたプロパティは、
書き込み専用 で、そのようなプロパティを読み取りしようとしても、例〵〮〳〮 イベント〲〳〱

外が発生します。 書き込み専用のプロパティを持つのは一般的ではありませんが。
でづぴぴづひ と びづぴぴづひ で定義されたプロパティには、いくつかの特別なルー
ルと制限があります〺• この種のプロパティでは、名前の 大文字と小文字を区別しません 。たとえば、 $object->label と $object->Label は同じです。 これは、ぐえぐ のメソッド名が大文字と小文字を区別しないためです。
• この種のプロパティの名前と、クラスのメンバ変数の名前とが同じである場合、後者が優先されます。 たとえば、上記の Foo クラスがメンバ変数 label を持っている場合は、$object->label = 'abc' という代入は メンバ変数の label に作用することになります。その行から setLabel() びづぴぴづひ メソッドは呼び出されません。
• これらのプロパティは可視性をサポートしていません。プロパ
ティが ばふぢぬどっ、ばひはぴづっぴづつ、ばひどぶちぴづ であるかどうかを、でづぴぴづひ またはびづぴぴづひ メソッドの定義によって決めることは出来ません。
• プロパティは、 静的でない でづぴぴづひ および びづぴぴづひ によってのみ定義
することが出来ます。静的なメソッドは同様には扱われません。
• 通常の property_exists() の呼び出しでは、マジック・プロパティが存在するかどうかを知ることは出来ません。 それぞれ、っちのぇづぴぐひはばづひぴべ〨〩または っちのこづぴぐひはばづひぴべ〨〩 を呼び出さなければなりません。
このガイドの冒頭で説明した問題に戻ると、 label に値が代入されている
あらゆる箇所で trim() を呼ぶのではなく、 もう setLabel() という びづぴぴづひの内部だけで trim() を呼べば済むのです。 さらに、新しい要求でラベルの先頭を大文字にする必要が発生しても、他のいっさいのコードに触れることなく、 すぐに setLabel() メソッドを変更することができます。一
箇所の変更は、すべての label への代入に普遍的に作用します。

5.3

イベント

イベントを使うと、既存のコードの特定の実行ポイントに、カスタム・
コードを挿入することができます。イベントにカスタム・コードをアタッチすると、 イベントがトリガされたときにコードが自動的に実行されます。たとえば、メーラ・オブジェクトがメッセージを正しく送信できたとき、 messageSent イベントをトリガするとします。もしメッセージの送信がうまく行ったことを知りたければ、単に messageSent イベントにトラッキング・コードを付与するだけで、それが可能になります。
すどどはイベントをサポートするために、 べどどぜぢちびづぜぃはねばはのづのぴ と呼ばれる基底クラスを導入してします。クラスがイベントをトリガする必要がある場合は、 べどどぜぢちびづぜぃはねばはのづのぴ もしくはその子クラスを継承する必要があります。

5.3.1

イベント・ハンドラ

イベント・ハンドラとは、アタッチされたイベントがトリガされたとき〲〳〲

ぃえぁぐごぅげ 〵〮 鍵となる概念に実行される ぐえぐ コールバック1 です。次のコールバックのいずれも使用可能です〺• 文字列で指定されたグローバル ぐえぐ 関数 〨括弧を除く〩、例えば'trim'。
• オブジェクトとメソッド名文字列の配列で指定された、オブジェク
トのメソッド 〨括弧を除く〩、例えば [$object, 'methodName']。
• クラス名文字列とメソッド名文字列の配列で指定された、静的なク
ラス・メソッド 〨括弧を除く〩、例えば ['ClassName', 'methodName']。
• 無名関数、例えば function ($event) { ... }。
イベント・ハンドラのシグネチャはこのようになります〺
function ($event) {// $event は yii\base\Event またはその子クラスのオブジェクト}$event パラメータを介して、イベント・ハンドラは発生したイベントに関して次の情報を得ることができます〺• イベント名• イベント送信元〺 trigger() メソッドが呼ばれたオブジェクト• カスタム・データ〺 イベント・ハンドラをアタッチするときに提供されたデータ 〨次の項で説明します〩

5.3.2

イベント・ハンドラをアタッチする

イベント・ハンドラは べどどぜぢちびづぜぃはねばはのづのぴ〺〺はの〨〩 を呼び出すことでアタッチできます。たとえば〺$foo = new Foo;// このハンドラはグローバル関数です$foo->on(Foo::EVENT_HELLO, 'function_name');// このハンドラはオブジェクトのメソッドです$foo->on(Foo::EVENT_HELLO, [$object, 'methodName']);// このハンドラは静的なクラスメソッドです$foo->on(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']);// このハンドラは無名関数です$foo->on(Foo::EVENT_HELLO, function ($event) {// イベント処理ロジック});

また、 構成情報 を通じてイベント・ハンドラをアタッチすることもできます。詳細については 構成情報 の章を参照してください。
イベント・ハンドラをアタッチするとき、 べどどぜぢちびづぜぃはねばはのづのぴ〺〺
はの〨〩 の〳番目のパラメータとして、付加的なデータを提供することができ1

https://www.php.net/manual/ja/language.types.callable.php〵〮〳〮 イベント〲〳〳

ます。 そのデータは、イベントがトリガされてハンドラが呼び出される
ときに、ハンドラ内で利用きます。たとえば〺// 次のコードはイベントがトリガされたとき "abc" を表示します// "on" に3番目の引数として渡されたデータを $event->data が保持しているからです$foo->on(Foo::EVENT_HELLO, 'function_name', 'abc');function function_name($event) {echo $event->data;
}

5.3.3

イベント・ハンドラの順序

ひとつのイベントには、ひとつだけでなく複数のハンドラをアタッチすることができます。イベントがトリガされると、アタッチされたハンドラは、 それらがイベントにアタッチされた順序どおりに呼び出されます。あるハンドラがその後に続くハンドラの呼び出しを停止する必要がある場合は、 $event パラメータの べどどぜぢちびづぜぅぶづのぴ〺〺〤とちのつぬづつ プロパ
ティを true に設定します〺$foo->on(Foo::EVENT_HELLO, function ($event) {$event->handled = true;});

デフォルトでは、新たに接続されたハンドラは、イベントの既存のハンドラのキューに追加されます。その結果、 イベントがトリガされたとき、そのハンドラは一番最後に呼び出されます。もし、そのハンドラが最初に呼び出されるよう、 ハンドラのキューの先頭に新しいハンドラを挿入したい場合は、べどどぜぢちびづぜぃはねばはのづのぴ〺〺はの〨〩 を呼び出すとき、〴番目のパラメータ $append に false を渡します〺$foo->on(Foo::EVENT_HELLO, function ($event) {// ...
}, $data, false);

5.3.4

イベントをトリガする

イベントは、 べどどぜぢちびづぜぃはねばはのづのぴ〺〺ぴひどででづひ〨〩 メソッドを呼び出すことでトリガされます。このメソッドには イベント名 が必須で、 オプショ
ンで、イベント・ハンドラに渡されるパラメータを記述したイベント・
オブジェクトを渡すこともできます。たとえば〺
namespace app\components;
use yii\base\Component;
use yii\base\Event;class Foo extends Component

〲〳〴
{

}

ぃえぁぐごぅげ 〵〮 鍵となる概念

const EVENT_HELLO = 'hello';
public function bar(){$this->trigger(self::EVENT_HELLO);}

上記のコードでは、すべての bar() の呼び出しは、 hello という名前のイ
ベントをトリガします。
ヒント〺 イベント名を表すときはクラス定数を使用することをお勧めします。上記の例では、定数 EVENT_HELLO は hello イベントを表しています。このアプローチには 〳 つの利点があります。まず、タイプミスを防ぐことができます。次に、ぉいぅの自動補完サポートでイベントを 認識できるようになります。第 〳 に、クラスでどんなイベントがサポートされているかを表したいとき、定数の宣言をチェックするだけで済みます。
イベントをトリガするとき、イベント・ハンドラに追加情報を渡したい
ことがあります。たとえば、メーラーが messageSent イベントのハンドラに メッセージ情報を渡して、ハンドラが送信されたメッセージの詳細を知ることができるようにしたいかもしれません。 これを行うために、
べどどぜぢちびづぜぃはねばはのづのぴ〺〺ぴひどででづひ〨〩 メソッドの〲番目のパラメータとして、イベント・オブジェクトを与えることができます。 イベント・オブジェ
クトは べどどぜぢちびづぜぅぶづのぴ クラスあるいはその子クラスのインスタンスでなければなりません。 たとえば〺
namespace app\components;
use yii\base\Component;
use yii\base\Event;class MessageEvent extends Event{public $message;}class Mailer extends Component{
const EVENT_MESSAGE_SENT = 'messageSent';
public function send($message){// ... $message 送信 ...
$event = new MessageEvent;$event->message = $message;

〵〮〳〮 イベント

}

}

〲〳〵

$this->trigger(self::EVENT_MESSAGE_SENT, $event);

べどどぜぢちびづぜぃはねばはのづのぴ〺〺ぴひどででづひ〨〩 メソッドが呼び出されたとき、この名前を付けられたイベントに アタッチされたハンドラがすべて呼び出され
ます。

5.3.5

イベント・ハンドラをデタッチする

イベントからハンドラを取り外すには、 べどどぜぢちびづぜぃはねばはのづのぴ〺〺はてて〨〩 メ
ソッドを呼び出します。たとえば〺// このハンドラはグローバル関数です$foo->off(Foo::EVENT_HELLO, 'function_name');// このハンドラはオブジェクトのメソッドです$foo->off(Foo::EVENT_HELLO, [$object, 'methodName']);// このハンドラは静的なクラスメソッドです$foo->off(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']);// このハンドラは無名関数です$foo->off(Foo::EVENT_HELLO, $anonymousFunction);

一般的には、イベントにアタッチされたときどこかに保存してある場合を除き、無名関数を取り外そうとはしないでください。 上記の例は、
無名関数は変数 $anonymousFunction として保存されていたものとしています。
イベントから すべて のハンドラを取り外すには、単純に、第 〲 パラ
メータを指定せずに べどどぜぢちびづぜぃはねばはのづのぴ〺〺はてて〨〩 を呼び出します。
$foo->off(Foo::EVENT_HELLO);

5.3.6

クラス・レベル・イベント・ハンドラ

ここまでの項では、インスタンス・レベル でのイベントにハンドラをアタッチする方法を説明してきました。 場合によっては、特定のインス
タンスだけではなく、 クラスのすべてのインスタンスがトリガしたイベ
ントに応答したいことがあります。 すべてのインスタンスにイベント・
ハンドラをアタッチする代わりに、静的メソッド べどどぜぢちびづぜぅぶづのぴ〺〺はの〨〩を呼び出すことで、 クラス・レベル でハンドラをアタッチすることができます。
たとえば、アクティブ・レコード オブジェクトは、データベースに新しいレコードを挿入するたびに、 ぅざぅぎごたぁうごぅげたぉぎこぅげご イベントをトリガします。 すべての アクティブ・レコード オブジェクトによって行われる挿入を追跡するには、次のコードが使えます：〲〳〶

ぃえぁぐごぅげ 〵〮 鍵となる概念

use Yii;
use yii\base\Event;use yii\db\ActiveRecord;
Event::on(ActiveRecord::class, ActiveRecord::EVENT_AFTER_INSERT, function($event) {Yii::debug(get_class($event->sender) . ' が挿入されました');});ぁっぴどぶづげづっはひつ またはその子クラスのいずれかが、 ぅざぅぎごたぁうごぅげたぉぎこぅげごをトリガするといつでも、このイベント・ハンドラが呼び出されます。
ハンドラの中では、 $event->sender を通して、 イベントをトリガしたオ
ブジェクトを取得することができます。
オブジェクトがイベントをトリガするときは、最初にインスタンス・
レベルのハンドラを呼び出し、続いてクラス・レベルのハンドラとなります。
静 的 メ ソ ッ ド べどどぜぢちびづぜぅぶづのぴ〺〺ぴひどででづひ〨〩 を 呼 び 出 す こ と に よ って、 クラス・レベル でイベントをトリガすることができます。 クラ
ス・レベルでのイベントは、特定のオブジェクトに関連付けられていません。そのため、これはクラス・レベルのイベント・ハンドラだけを 呼び出します。たとえば〺
use yii\base\Event;
Event::on(Foo::class, Foo::EVENT_HELLO, function ($event) {var_dump($event->sender); // "null" を表示});
Event::trigger(Foo::class, Foo::EVENT_HELLO);

この場合、$event->sender は、オブジェクト・インスタンスではなく、nullになることに注意してください。
補足〺 クラス・レベルのハンドラは、そのクラスのあらゆるイ
ンスタンス、またはあらゆる子クラスのインスタンスがトリガしたイベントに応答 してしまうため、よく注意して使わなければなりません。 べどどぜぢちびづぜあちびづくぢなづっぴ のように、クラスが低レベルの基底クラスの場合は特にそうです。
クラス・レベルのイベント・ハンドラを取り外すときは、 べどどぜぢちびづ
ぜぅぶづのぴ〺〺はてて〨〩 を呼び出します。たとえば〺// $handler をデタッチ
Event::off(Foo::class, Foo::EVENT_HELLO, $handler);// Foo::EVENT_HELLO のすべてのハンドラをデタッチ
Event::off(Foo::class, Foo::EVENT_HELLO);〵〮〳〮 イベント

5.3.7

〲〳〷

インタフェイスを使うイベント

イベントを扱うためには、もっと抽象的な方法もあります。 特定のイベントのために専用のインタフェイスを作っておき、必要な場合にいろいろなクラスでそれを実装するのです。
例えば、次のようなインタフェイスを作ります。
namespace app\interfaces;interface DanceEventInterface{
const EVENT_DANCE = 'dance';}

そして、それを実装する二つのクラスを作ります。
class Dog extends Component implements DanceEventInterface{
public function meetBuddy(){
echo "ワン!";$this->trigger(DanceEventInterface::EVENT_DANCE);}}
class Developer extends Component implements DanceEventInterface{
public function testsPassed(){echo "よっしゃ!";$this->trigger(DanceEventInterface::EVENT_DANCE);}}

これらのクラスのどれかによってトリガされた EVENT_DANCE を扱うためには、インタフェイス・クラスの名前を最初の引数にして ぅぶづのぴ〺〺はの〨〩 を呼びます。
Event::on('app\interfaces\DanceEventInterface',
DanceEventInterface::EVENT_DANCE, function ($event) {Yii::debug(get_class($event->sender) . ' が躍り上がって喜んだ。'); // 犬または開発者が躍り上がって喜んだことをログに記録。
});

これらのクラスのイベントをトリガすることも出来ます。
// trigger event for Dog class
Event::trigger(Dog::class, DanceEventInterface::EVENT_DANCE);// trigger event for Developer class
Event::trigger(Developer::class, DanceEventInterface::EVENT_DANCE);〲〳〸

ぃえぁぐごぅげ 〵〮 鍵となる概念

ただし、このインタフェイスを実装する全クラスのイベントをトリガすることは出来ない、ということに注意して下さい。
// これは動かない。このインタフェイスを実装するクラスのイベントはトリガされない。
Event::trigger('app\interfaces\DanceEventInterface',
DanceEventInterface::EVENT_DANCE);

イベント・ハンドラをデタッチするためには、ぅぶづのぴ〺〺はてて〨〩 を呼びます。例えば、// $handler をデタッチ
Event::off('app\interfaces\DanceEventInterface',
DanceEventInterface::EVENT_DANCE, $handler);// DanceEventInterface::EVENT_DANCE の全てのハンドラをデタッチ
Event::off('app\interfaces\DanceEventInterface',
DanceEventInterface::EVENT_DANCE);

5.3.8

グローバル・イベント

すどどは、いわゆる グローバル・イベント をサポートしています。これは、実際には、上記のイベント・メカニズムに基づいたトリックです。 グ
ローバル・イベントは、 アプリケーション インスタンス自身などの、グローバルにアクセス可能なシングルトンを必要とします。
グローバル・イベントを作成するには、イベント送信者は、送信者の自前の trigger() メソッドを呼び出す代わりに、シングルトンの trigger()
メソッドを呼び出してイベントをトリガします。同じく、イベント・ハ
ンドラも、シングルトンのイベントにアタッチされます。たとえば〺
use Yii;
use yii\base\Event;use app\components\Foo;Yii::$app->on('bar', function ($event) {echo get_class($event->sender); // "app\components\Foo" を表示});
Yii::$app->trigger('bar', new Event(['sender' => new Foo]));グローバル・イベントを使用する利点は、オブジェクトによってトリガされるイベント・ハンドラを設けたいとき、オブジェクトがなくてもいい ということです。その代わりに、ハンドラのアタッチとイベントのト
リガはともに、〨アプリケーションのインスタンスなど〩 シングルトンを介して行われます。
しかし、グローバル・イベントの名前空間はあらゆる部分から共有されているので、ある種の名前空間 〨〢てひはのぴづのつ〮ねちどぬ〮びづのぴ】、〢ぢちっにづのつ〮ねちどぬ〮びづのぴ】など〩 を導入するというような、賢いグローバル・イベントの名前付けをする必要があります。

〵〮〳〮 イベント

5.3.9

〲〳〹

ワイルドカード・イベント〲〮〰〮〱〴 以降は、ワイルドカード・パターンに一致する複数のイベントに対してイベント・ハンドラを設定することが出来ます。 例えば、
use Yii;$foo = new Foo();$foo->on('foo.event.*', function ($event) {// 'foo.event.' で始まる全てのイベントに対してトリガされるYii::debug('trigger event: ' . $event->name);});

クラス・レベル・イベントに対してもワイルドカード・パターンを用いることが出来ます。例えば、
use yii\base\Event;use Yii;
Event::on('app\models\*', 'before*', function ($event) {// 名前空間 'app\models' の全てのクラスで、名前が 'before' で始まる全てのイベントに対してトリガされるYii::debug('trigger event: ' . $event->name . ' for class: ' .
get_class($event->sender));});

これを利用すると、以下のコードを使って、全てのアプリケーション・
イベントを一つのハンドラでキャッチすることが出来ます。
use yii\base\Event;use Yii;
Event::on('*', '*', function ($event) {// 全てのクラスの全てのイベントに対してトリガされるYii::debug('trigger event: ' . $event->name);});補足〺 イベント・ハンドラにワイルドカードを使用する設定
は、アプリケーションの性能を低下させ得ます。 可能であれば避ける方が良いでしょう。
ワイルドカード・パターンで指定されたイベント・ハンドラをデタッチするためには、べどどぜぢちびづぜぃはねばはのづのぴ〺〺はてて〨〩 または べどどぜぢちびづぜぅぶづのぴ〺〺
はてて〨〩 の呼び出しにおいて、 同じパターンを使用しなければなりません。 イベント・ハンドラをデタッチする際にワイルドカードを指定すると、そのワイルドカードで指定されたハンドラだけがデタッチされることに留意して下さい。 通常のイベント名でアタッチされたハンドラは、パターンに合致する場合であっても、デタッチされません。例えば、

〲〴〰

ぃえぁぐごぅげ 〵〮 鍵となる概念

use Yii;$foo = new Foo();// 通常のハンドラをアタッチする$foo->on('event.hello', function ($event) {echo 'direct-handler'});// ワイルドカード・ハンドラをアタッチする$foo->on('*', function ($event) {echo 'wildcard-handler'});// ワイルドカード・ハンドラをデタッチする!
$foo->off('*');$foo->trigger('event.hello'); // 出力: 'direct-handler'

5.4

ビヘイビア

ビヘイビアは べどどぜぢちびづぜあづとちぶどはひ またその子クラスのインスタンスです。ビヘイビアは ミックスイン2 としても知られ、既存の っはねばはのづのぴ ク
ラスの 機能を、クラスの継承を変更せずに拡張することができます。コンポーネントにビヘイビアをアタッチすると、その コンポーネントにはビヘイビアのメソッドとプロパティが 【注入】 され、それらのメソッドとプロパティは、 コンポーネント・クラス自体に定義されているかのようにアクセスできるようになります。また、ビヘイビアは、 コンポーネン
トによってトリガされた イベント に応答することができるので、ビヘイ
ビアでコンポーネントの通常のコード実行をカスタマイズすることがで
きます。

5.4.1

ビヘイビアを定義する

ビヘイビアを定義するには、 べどどぜぢちびづぜあづとちぶどはひ あるいは子クラスを継承するクラスを作成します。たとえば〺
namespace app\components;
use yii\base\Behavior;class MyBehavior extends Behavior{
public $prop1;
private $_prop2;
2

https://ja.wikipedia.org/wiki/Mixin〵〮〴〮 ビヘイビア〲〴〱

public function getProp2(){
return $this->_prop2;}
public function setProp2($value){$this->_prop2 = $value;}}

public function foo(){// ...
}

上のコードは、prop1、prop2 という〲つのプロパティと foo() というメソッドを持つ app\components\MyBehavior ビヘイビア・クラスを定義します。
prop2 プロパティは、 getProp2() でづぴぴづひ メソッドと setProp2() びづぴぴづひ メソッドで定義されることに着目してください。 べどどぜぢちびづぜあづとちぶどはひ は べどど
ぜぢちびづぜあちびづくぢなづっぴ を継承しているので、でづぴぴづひ と びづぴぴづひ による プロパ
ティ 定義をサポートします。
このクラスはビヘイビアなので、コンポーネントにアタッチされると、そのコンポーネントは prop1 と prop2 のプロパティと foo() メソッドを持つようになります。
ヒント〺 ビヘイビア内から、べどどぜぢちびづぜあづとちぶどはひ〺〺〤はぷのづひ プロ
パティを介して、ビヘイビアをアタッチしたコンポーネントにアクセスすることができます。
補足〺 ビヘイビアの べどどぜぢちびづぜあづとちぶどはひ〺〺たたでづぴ〨〩 および〯または べどどぜぢちびづぜあづとちぶどはひ〺〺たたびづぴ〨〩 メソッドをオーバーライ
ドする場合は、 同時に べどどぜぢちびづぜあづとちぶどはひ〺〺っちのぇづぴぐひはばづひぴべ〨〩および〯または べどどぜぢちびづぜあづとちぶどはひ〺〺っちのこづぴぐひはばづひぴべ〨〩 もオー
バーライドする必要があります。

5.4.2

コンポーネントのイベントを処理する

ビヘイビアが、アタッチされたコンポーネントがトリガするイベントに応答する必要がある場合は、 べどどぜぢちびづぜあづとちぶどはひ〺〺づぶづのぴび〨〩 メソッドを
オーバーライドしなければなりません。たとえば〺
namespace app\components;
use yii\db\ActiveRecord;
use yii\base\Behavior;class MyBehavior extends Behavior{〲〴〲

ぃえぁぐごぅげ 〵〮 鍵となる概念// ...
public function events(){
return [ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',];}}public function beforeValidate($event){// ...
}

べどどぜぢちびづぜあづとちぶどはひ〺〺づぶづのぴび〨〩 メソッドは、イベントとそれに対応する
ハンドラのリストを返します。 上の例では ぅざぅぎごたあぅうくげぅたざぁがぉいぁごぅ イベントがあること、 そのハンドラ定義である beforeValidate() を宣言しています。イベント・ハンドラを指定するときは、以下の表記方法が使えます〺• ビヘイビア・クラスのメソッド名を参照する文字列 〨上の例など〩• オブジェクトまたはクラス名と文字列のメソッド名 〨括弧なし〩 例[$object, 'methodName']• 無名関数
イベント・ハンドラのシグニチャは次のようにしてください。$event はイベントのパラメータを参照します。イベントの詳細については イベン
ト セクションを参照してください。
function ($event) {
}

5.4.3

ビヘイビアをアタッチする

コンポーネント へのビヘイビアのアタッチは、静的にも動的にも可能です。実際は、前者のほうがより一般的ですが。
ビヘイビアを静的にアタッチするには、ビヘイビアをアタッチしたい
コンポーネント・クラスの ぢづとちぶどはひび〨〩 メソッドをオーバーライドしま
す。 ぢづとちぶどはひび〨〩 メソッドは、ビヘイビアの 構成 のリストを返さなけ
ればなりません。 各ビヘイビアの構成内容は、ビヘイビアのクラス名でも、構成情報配列でもかまいません。
namespace app\models;
use yii\db\ActiveRecord;
use app\components\MyBehavior;class User extends ActiveRecord{
public function behaviors()〵〮〴〮 ビヘイビア{〲〴〳

return [// 無名ビヘイビア ビヘイビア・クラス名のみ
MyBehavior::class,// 名前付きビヘイビア ビヘイビア・クラス名のみ'myBehavior2' => MyBehavior::class,// 無名ビヘイビア 構成情報配列['class' => MyBehavior::class,'prop1' => 'value1','prop2' => 'value2',
],

}

}

];

// 名前付きビヘイビア 構成情報配列'myBehavior4' => ['class' => MyBehavior::class,'prop1' => 'value1','prop2' => 'value2',]

ビヘイビア構成に対応する配列のキーを指定することによって、ビヘイ
ビアに名前を関連付けることができます。この場合、ビヘイビアは 名前付きビヘイビア と呼ばれます。上の例では、〲つの名前付きビヘイビア
myBehavior2 と myBehavior4 があります。ビヘイビアが名前と関連付けられていない場合は、 無名ビヘイビア と呼ばれます。
ビヘイビアを動的にアタッチするには、ビヘイビアがアタッチされるコンポーネントの べどどぜぢちびづぜぃはねばはのづのぴ〺〺ちぴぴちっとあづとちぶどはひ〨〩 メソッドを呼びます〺
use app\components\MyBehavior;// ビヘイビア・オブジェクトをアタッチ$component->attachBehavior('myBehavior1', new MyBehavior());// ビヘイビア・クラスをアタッチ$component->attachBehavior('myBehavior2', MyBehavior::class);// 構成情報配列をアタッチ$component->attachBehavior('myBehavior3', ['class' => MyBehavior::class,'prop1' => 'value1','prop2' => 'value2',]);

べどどぜぢちびづぜぃはねばはのづのぴ〺〺ちぴぴちっとあづとちぶどはひび〨〩 メソッドを使うと、いちどに複数のビヘイビアをアタッチできます〺〲〴〴

ぃえぁぐごぅげ 〵〮 鍵となる概念$component->attachBehaviors(['myBehavior1' => new MyBehavior(), // 名前付きビヘイビア
MyBehavior::class,// 無名ビヘイビア]);

次のように、 構成情報 を通じてビヘイビアをアタッチすることもできます〺[]'as myBehavior2' => MyBehavior::class,'as myBehavior3' => ['class' => MyBehavior::class,'prop1' => 'value1','prop2' => 'value2',],

詳しくは 構成情報 のセクションを参照してください。

5.4.4

ビヘイビアを使用する

ビヘイビアを使用するには、まず上記の方法に従って コンポーネント にアタッチします。ビヘイビアがコンポーネントにアタッチされれば、その使用方法はシンプルです。
あなたは、アタッチされているコンポーネントを介して、ビヘイビアの パブリック メンバ変数、 または でづぴぴづひ や びづぴぴづひ によって定義されたプロパティにアクセスすることができます〺// "prop1" はビヘイビア・クラス内で定義されたプロパティ
echo $component->prop1;$component->prop1 = $value;

また同様に、ビヘイビアの パブリック・メソッドも呼ぶことができます〺// foo() はビヘイビア・クラス内で定義されたパブリック・メソッド$component->foo();

ご覧のように、 $component は prop1 と foo() を定義していないにもかかわらず、 アタッチされたビヘイビアによって、それらをコンポーネント定義の一部であるかのように使うことができるのです。
もし〲つのビヘイビアが同じプロパティやメソッドを定義し、かつ両方とも同じコンポーネントにアタッチされている場合は、 プロパティやメソッドのアクセス時に、最初に コンポーネントにアタッチされたビヘ
イビアが優先されます。
ビヘイビアはコンポーネントにアタッチされるとき、名前と関連付
けられているかもしれません。その場合、 その名前を使用してビヘイビ
ア・オブジェクトにアクセスすることができます〺〵〮〴〮 ビヘイビア〲〴〵$behavior = $component->getBehavior('myBehavior');

また、コンポーネントにアタッチされた全てのビヘイビアを取得することもできます〺$behaviors = $component->getBehaviors();

5.4.5

ビヘイビアをデタッチする

ビヘイビアをデタッチするには、ビヘイビアに付けられた名前とともにべどどぜぢちびづぜぃはねばはのづのぴ〺〺つづぴちっとあづとちぶどはひ〨〩 を呼び出します〺$component->detachBehavior('myBehavior1');

全ての ビヘイビアをデタッチすることもできます〺$component->detachBehaviors();

5.4.6

を利用する

しめくくりに、べどどぜぢづとちぶどはひびぜごどねづびぴちねばあづとちぶどはひ を見てみましょう。
このビヘイビアは、 insert()、update() または save() のメソッドを通じてアクティブ・レコード モデルが保存されるときに、 タイムスタンプ属性の自動的な更新をサポートします。
まず、使用しようと考えている アクティブ・レコード クラスに、このビヘイビアをアタッチします〺
namespace app\models\User;use yii\db\ActiveRecord;
use yii\behaviors\TimestampBehavior;class User extends ActiveRecord{// ...

}

public function behaviors(){
return [['class' => TimestampBehavior::class,'attributes' => [ActiveRecord::EVENT_BEFORE_INSERT => ['created_at','updated_at'],ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],],// UNIX タイムスタンプではなく datetime を使う場合は// 'value' => new Expression('NOW()'),
],
];
}

〲〴〶

ぃえぁぐごぅげ 〵〮 鍵となる概念上のビヘイビア構成は、レコードが〺• 挿入されるとき、ビヘイビアは現在の さぎぉじ タイムスタンプを
created_at と updated_at 属性に割り当てます• 更新されるとき、ビヘイビアは現在の さぎぉじ タイムスタンプを
updated_at 属性に割り当てます補足〺 上記の実装が きべこけが データベースで動作するようにするためには、created_at と updated_at のカラムを さぎぉじ タイム
スタンプ になるように どのぴ〨〱〱〩 として宣言してください。
このコードが所定の位置にあれば、例えば User オブジェクトがあって、それを保存しようとしたら、そこで、 created_at と updated_at が自動的に
現在の さぎぉじ タイムスタンプで埋められます。
$user = new User;$user->email = 'test@example.com';$user->save();echo $user->created_at; // 現在のタイムスタンプが表示される

ごどねづびぴちねばあづとちぶどはひ は、また、指定された属性に現在のタイムスタンプを割り当てて それをデータベースに保存する、便利なメソッド ぴはふっと〨〩を提供しています。
$user->touch('login_time');

5.4.7

その他のビヘイビア

その他にも、内蔵または外部ライブラリによって利用できるビヘイビア
がいくつかあります。
• べどどぜぢづとちぶどはひびぜあぬちねづちぢぬづあづとちぶどはひ 〭 指定された属性に現在のユー
ザ ぉい を自動的に設定します。
• べどどぜぢづとちぶどはひびぜこぬふででちぢぬづあづとちぶどはひ 〭 指定された属性に、さげが のス
ラグとして使用できる値を 自動的に設定します。
• べどどぜぢづとちぶどはひびぜぁぴぴひどぢふぴづあづとちぶどはひ 〭 特定のイベントが発生したときに、ぁっぴどぶづげづっはひつ オブジェクトの一つまたは複数の属性に、 指定された値を自動的に設定します。
• べどど〲ぴづっとぜちひぜびはてぴつづぬづぴづぜこはてぴいづぬづぴづあづとちぶどはひ3 〭 ぁっぴどぶづげづっはひつ をソフト・
デリートおよびソフト・リストアするメソッド、 すなわち、レコー
ドの削除を示すフラグまたはステータスを設定するメソッドを提供します。
• べどど〲ぴづっとぜちひぜばはびどぴどはのぜぐはびどぴどはのあづとちぶどはひ4 〭 レ コ ー ド の 順 序 を 整 数 のフィールドによって管理することが出来るように、 順序変更メ
ソッドを提供します。
3
4https://github.com/yii2tech/ar-softdelete
https://github.com/yii2tech/ar-position〵〮〵〮 構成情報

5.4.8

〲〴〷

ビヘイビアとトレイトの比較

ビヘイビアは、主となるクラスにそのプロパティやメソッドを「注入する」という点で トレイト5 に似ていますが、これらは多くの面で異なります。以下に説明するように、それらは互いに長所と短所を持っています。 それらは代替手段というよりも、むしろ相互補完関係のようなものです。
ビヘイビアを使う理由
ビヘイビアは通常のクラスのように、継承をサポートしています。いっぽうトレイトは、 言語サポートされたコピー〦ペーストとみなすことができます。トレイトは継承をサポートしません。
ビヘイビアは、コンポーネント・クラスの変更を必要とせず、コン
ポーネントに動的にアタッチまたはデタッチすることが可能です。 トレ
イトを使用するには、トレイトを使うクラスのコードを書き換える必要があります。
ビヘイビアは構成可能ですがトレイトは不可能です。
ビヘイビアは、イベントに応答することで、コンポーネントのコード
実行をカスタマイズできます。
同じコンポーネントにアタッチされた異なるビヘイビア間で名前の競合がある場合、その競合は自動的に、 先にコンポーネントにアタッチされたものを優先することで解消されます。 異なるトレイトによって引き起こされる名前競合の場合は、 影響を受けるプロパティやメソッドの名
前変更による、手動での解決が必要です。
トレイトを使う理由
ビヘイビアは時間もメモリも食うオブジェクトなので、トレイトはビヘ
イビアよりはるかに効率的です。
トレイトはネイティブな言語構造であるため、ぉいぅ との相性に優れて
います。

5.5

構成情報

新しいオブジェクトを作成したり、既存のオブジェクトを初期化するとき、すどど では構成情報が広く使用されています。 構成情報は通常、作成されるオブジェクトのクラス名、およびオブジェクトの プロパティ に割り当てられる初期値のリストを含みます。 構成情報は、オブジェクトのイベント にアタッチされるハンドラのリストや、オブジェクトにアタッ
チされる ビヘイビア のリストを含むこともできます。
以下では、データベース接続を作成して初期化するために、構成情報が使用されています〺
5https://www.php.net/manual/ja/language.oop5.traits.php〲〴〸ぃえぁぐごぅげ 〵〮 鍵となる概念$config = ['class' => 'yii\db\Connection','dsn' => 'mysql:host=127.0.0.1;dbname=demo','username' => 'root','password' => '','charset' => 'utf8',];$db = Yii::createObject($config);

すどど〺〺っひづちぴづくぢなづっぴ〨〩 メソッドは引数に構成情報の配列を受け取り、構成情報で名前指定されたクラスをインスタンス化してオブジェクトを作成します。 オブジェクトがインスタンス化されるとき、構成情報の残りの部分を使って、 オブジェクトのプロパティ、イベント・ハンドラ、およびビヘイビアが初期化されます。
すでにオブジェクトがある場合は、構成情報配列でオブジェクトのプ
ロパティを初期化するのに すどど〺〺っはのてどでふひづ〨〩 を使用することができます〺
Yii::configure($object, $config);

なお、この場合には、構成情報配列に class 要素を含んではいけません。

5.5.1

構成情報の形式

構成情報の形式は、フォーマルには次のように説明できます〺[]'class' => 'ClassName','propertyName' => 'propertyValue','on eventName' => $eventHandler,'as behaviorName' => $behaviorConfig,

ここで• class 要素は、作成されるオブジェクトの完全修飾クラス名を指定します。
• propertyName 要素は、名前で指定されたプロパティの初期値を指定します。 キーはプロパティ名で、値はそれに対応する初期値です。
パブリック・メンバ変数と でづぴぴづひ〯びづぴぴづひ によって定義されている プ
ロパティ のみを設定することができます。
• on eventName 要素は、どのようなハンドラがオブジェクトの イベン
ト にアタッチされるかを指定します。 配列のキーが on に続けてイベント名という書式になることに注意してください。サポートされているイベント・ハンドラの形式については、 イベント のセク
ションを参照してください。

〵〮〵〮 構成情報〲〴〹• as behaviorName 要素は、どのような ビヘイビア がオブジェクトにアタッチされるかを指定します。 配列のキーが as に続けてビヘイビ
ア名という書式になり、$behaviorConfig で示される値が、ここで説明する一般的な構成情報のような、 ビヘイビアを作成するための構成情報になることに注意してください。
下記は、初期プロパティ値、イベント・ハンドラ、およびビヘイビアでの構成を示した例です〺[]'class' => 'app\components\SearchEngine','apiKey' => 'xxxxxxxx','on search' => function ($event) {Yii::info("Keyword searched: " . $event->keyword);},'as indexer' => ['class' => 'app\components\IndexerBehavior',// ... プロパティ初期値 ...
],

5.5.2

構成情報を使用する構成情報は すどど の多くの場所で使用されています。このセクションの冒頭では、 すどど〺〺っひづちぴづくぢなづっぴ〨〩 を使って、構成情報に応じてオブジェク
トを作成する方法を示しました。この項では、 アプリケーションの構成とウィジェットの構成という、二つの主要な構成情報の用途を説明します。
アプリケーションの構成
アプリケーション の構成情報は、おそらく すどど の中で最も複雑な配列のひとつです。 それは アプリケーション クラスが、設定可能なプロ
パティとイベントを数多く持つためです。 さらに重要なことは、そのっはねばはのづのぴび プロパティが、アプリケーションに登録されている コンポー
ネントの生成用の構成情報配列を受け取ることができることです。以下
は、 ベーシック・プロジェクト・テンプレート のアプリケーション構成
ファイルの概要です。
$config = ['id' => 'basic','basePath' => dirname(__DIR__),'extensions' => require __DIR__ . '/../vendor/yiisoft/extensions.php','components' => ['cache' => ['class' => 'yii\caching\FileCache',],'mailer' => ['class' => 'yii\swiftmailer\Mailer',
],

〲〵〰

];

ぃえぁぐごぅげ 〵〮 鍵となる概念],'log' => ['class' => 'yii\log\Dispatcher','traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [['class' => 'yii\log\FileTarget',],],],'db' => ['class' => 'yii\db\Connection','dsn' => 'mysql:host=localhost;dbname=stay2','username' => 'root','password' => '','charset' => 'utf8',],

この構成情報には、 class キーがありません。それは、エントリ・スクリ
プト で以下のように、 クラス名が既に与えられて使用されているためです。
(new yii\web\Application($config))->run();アプリケーションの components プロパティ構成の詳細については、 アプ
リケーション のセクションと サービス・ロケータ のセクションにあります。
バージョン 〲〮〰〮〱〱 以降では、アプリケーション構成で container プロ
パティを使って 依存注入コンテナ を構成することがサポートされています。例えば、$config = ['id' => 'basic','basePath' => dirname(__DIR__),'extensions' => require __DIR__ . '/../vendor/yiisoft/extensions.php','container' => ['definitions' => ['yii\widgets\LinkPager' => ['maxButtonCount' => 5]],'singletons' => [// 依存注入コンテナのシングルトンの構成]]];
definitions と singletons の構成情報配列に使用できる値とその実例についてさらに知るためには、 依存注入コンテナ の記事の 高度な実際の使用方法 のセクションを読んでください。

〵〮〵〮 構成情報〲〵〱

ウィジェットの構成
ウィジェット を使用するときは、多くの場合、ウィジェットのプロパ
ティをカスタマイズするために、構成情報を使用する必要があります。
べどどぜぢちびづぜしどつでづぴ〺〺ぷどつでづぴ〨〩 と べどどぜぢちびづぜしどつでづぴ〺〺ぢづでどの〨〩 の両メソッドを使って、ウィジェットを作成できます。 それらは、以下のような構成情報配列を取ります。
use yii\widgets\Menu;
echo Menu::widget(['activateItems' => false,'items' => [['label' => 'ホーム', 'url' => ['site/index']],['label' => '製品', 'url' => ['product/index']],['label' => 'ログイン', 'url' => ['site/login'], 'visible' =>Yii::$app->user->isGuest],],]);

上記のコードは、 Menu ウィジェットを作成し、その activateItems プロパ
ティが false になるよう初期化します。 items プロパティも、表示されるメニュー項目で構成されます。
クラス名がすでに与えられているので、構成情報配列が class キーを持つべきではないことに注意してください。

5.5.3

構成情報ファイル

構成情報がとても複雑になる場合、一般的な方法は、 構成情報ファイルと呼ばれる、ひとつまたは複数の ぐえぐ ファイルにそれを格納することです。 構成情報ファイルは、構成情報を表す ぐえぐ 配列を返します。 たとえば、次のように、 web.php と名づけたファイルにアプリケーションの構成情報を保持することができます。
return ['id' => 'basic','basePath' => dirname(__DIR__),'extensions' => require __DIR__ . '/../vendor/yiisoft/extensions.php','components' => require __DIR__ . '/components.php',];
components の構成情報もまた複雑になるため、上記のように、 components.phpと呼ぶ別のファイルにそれを格納し web.php でそのファイルを 【ひづぱふどひづ】
しています。 この components.php の内容は、次のようになっています。
return ['cache' => ['class' => 'yii\caching\FileCache',
],

〲〵〲

];

ぃえぁぐごぅげ 〵〮 鍵となる概念'mailer' => ['class' => 'yii\swiftmailer\Mailer',],'log' => ['class' => 'yii\log\Dispatcher','traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [['class' => 'yii\log\FileTarget',],],],'db' => ['class' => 'yii\db\Connection','dsn' => 'mysql:host=localhost;dbname=stay2','username' => 'root','password' => '','charset' => 'utf8',],

構成情報ファイルに格納されている構成情報を取得するには、以下のよ
うに、それを 【ひづぱふどひづ】 するだけです〺$config = require 'path/to/web.php';(new yii\web\Application($config))->run();5.5.4

デフォルト設定

すどど〺〺っひづちぴづくぢなづっぴ〨〩 メソッドは、 依存性注入コンテナ をベースに実装されています。 そのため、指定されたクラスが すどど〺〺っひづちぴづくぢなづっぴ〨〩 を使用して作成されるとき、そのすべてのインスタンスに適用される、 い
わゆる デフォルト設定 のセットを指定することができます。デフォルト
設定は、 ブートストラップ 段階のコード内で Yii::$container->set() を呼び出すことで指定することができます。
たとえばあなたが、すべてのリンク・ページャが最大で〵つのペー
ジ・ボタン 〨デフォルト値は〱〰〩 を伴って表示されるよう べどどぜぷどつでづぴび
ぜがどのにぐちでづひ をカスタマイズしたいとき、その目標を達成するには次のコードを使用することができます。
\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5,]);

デフォルト設定を使用しなければ、あなたは、リンク・ページャを使う
すべての箇所で maxButtonCount を設定しなければなりません。

5.5.5

環境定数

構成情報は、多くの場合、アプリケーションが実行される環境に応じて変化します。たとえば、 開発環境では mydb_dev という名前のデータベー

〵〮〶〮 エイリアス〲〵〳

スを使用し、本番サーバ上では mydb_prod データベースを 使用したいかもしれません。環境の切り替えを容易にするために、すどど は、あなたのアプ
リケーションの エントリ・スクリプト で定義可能な YII_ENV という名前の定数を提供します。 たとえば〺
defined('YII_ENV') or define('YII_ENV', 'dev');
YII_ENV を次のいずれかの値と定義することができます〺• prod〺 本番環境。定数 YII_ENV_PROD が true と評価されます。 とくに定義しない場合、これが YII_ENV のデフォルト値です。
• dev〺 開発環境。定数 YII_ENV_DEV が true と評価されます。
• test〺 テスト環境。定数 YII_ENV_TEST が true と評価されます。
これらの環境定数を使用すると、現在の環境に基づいて条件付きで構成
情報を指定することもできます。 たとえば、アプリケーション構成情報には、開発環境での デバッグ・ツールバーとデバッガ を有効にするために、次のコードを含むことができます。
$config = [...];
if (YII_ENV_DEV) {// 'dev' 環境用に構成情報を調整$config['bootstrap'][] = 'debug';$config['modules']['debug'] = 'yii\debug\Module';}
return $config;

5.6

エイリアス

ファイル・パスや さげが を表すのにエイリアスを使用すると、あなたはプ
ロジェクト内で絶対パスや さげが をハードコードする必要がなくなります。 エイリアスは、通常のファイル・パスや さげが と区別するために、 @文字で始まる必要があります。 先頭に @ を付けずに定義されたエイリア
スは、@ 文字が先頭に追加されます。
すどど はすでに利用可能な多くの事前定義エイリアスを持っています。
たとえば、 @yii というエイリアスは すどど フレームワークのインストー
ル・パスを表し、@web は現在実行中のウェブ・アプリケーションのベース さげが を表します。

5.6.1

エイリアスを定義する

すどど〺〺びづぴぁぬどちび〨〩 を呼び出すことにより、ファイル・パスまたは さげが のエイリアスを定義することができます。
// ファイル・パスのエイリアス
Yii::setAlias('@foo', '/path/to/foo');〲〵〴

ぃえぁぐごぅげ 〵〮 鍵となる概念// URL のエイリアス
Yii::setAlias('@bar', 'https://www.example.com');// \foo\Bar クラスを保持する具体的なファイルのエイリアス
Yii::setAlias('@foo/Bar.php', '/definitely/not/foo/Bar.php');

補足〺 エイリアスされているファイル・パスや さげが は、必ずしも実在するファイルまたはリソースを参照しない場合があります。
定義済みのエイリアスがあれば、スラッシュ / に続けて 〱 つ以上のパス・セグメントを追加することで（すどど〺〺びづぴぁぬどちび〨〩 の呼び出しを必要とせずに〩 新しいエイリアスを導出することができます。 すどど〺〺びづぴぁぬどちび〨〩
を通じて定義されたエイリアスは ルート・エイリアス となり、それから派生したエイリアスは 派生エイリアス になります。たとえば、 @foo がルート・エイリアスなら、 @foo/bar/file.php は派生エイリアスです。
エイリアスを、他のエイリアス 〨ルートまたは派生のいずれか〩 を使用して定義することができます〺
Yii::setAlias('@foobar', '@foo/bar');

ルート・エイリアスは通常、 ブートストラップ 段階で定義されます。 たとえば、エントリ・スクリプト で すどど〺〺びづぴぁぬどちび〨〩 を呼び出すことができます。 便利なように、 アプリケーション は、aliases という名前の書き込み可能なプロパティを提供しており、 それをアプリケーションの 構
成情報 で設定することが可能です。
return [// ...
'aliases' => ['@foo' => '/path/to/foo','@bar' => 'https://www.example.com',
],
];

5.6.2

エイリアスを解決する

すどど〺〺でづぴぁぬどちび〨〩 を呼び出して、ルート・エイリアスが表すファイル・パスまたは さげが を解決することができます。 同メソッドで、派生エイ
リアスを対応するファイル・パスまたは さげが に解決することもできます。
echo Yii::getAlias('@foo');echo Yii::getAlias('@bar');echo Yii::getAlias('@foo/bar/file.php');
示// /path/to/foo を表示// https://www.example.com を表示// /path/to/foo/bar/file.php を表〵〮〶〮 エイリアス〲〵〵

派生エイリアスによって表されるパスや さげが は、 派生エイリアス内のルート・エイリアス部分を対応するパスや さげが で置換して決定されます。
補足〺 すどど〺〺でづぴぁぬどちび〨〩 メソッドは、 結果のパスや さげが が実在するファイルやリソースを参照しているかをチェックしません。
ルート・エイリアス名にはスラッシュ / 文字を含むことができます。 すどど〺〺でづぴぁぬどちび〨〩 メソッドは、 エイリアスのどの部分がルート・エイリアス
であるかを賢く判別し、 正確に対応するファイル・パスや さげが を決定します〺
Yii::setAlias('@foo', '/path/to/foo');
Yii::setAlias('@foo/bar', '/path2/bar');Yii::getAlias('@foo/test/file.php'); // /path/to/foo/test/file.php を表示
Yii::getAlias('@foo/bar/file.php');// /path2/bar/file.php を表示

もし @foo/bar がルート・エイリアスとして定義されていなければ、最後のステートメントは /path/to/foo/bar/file.php を表示します。

5.6.3

エイリアスを使用する

すどど では、多くの場所で、パスや さげが に変換する すどど〺〺でづぴぁぬどちび〨〩 を呼び出す必要なく、 エイリアスが認識されます。 たとえば、 べどどぜっちっとどのでぜうどぬづぃちっとづ〺〺〤っちっとづぐちぴと は、ファイル・パスとファイル・パスを表すエイリアスの両方を受け入れることが出来ます。 これは、接頭辞 @ によって、ファイル・パスとエイリアスを区別することが出来るためです。
use yii\caching\FileCache;$cache = new FileCache(['cachePath' => '@runtime/cache',]);プロパティやメソッドのパラメータがエイリアスをサポートしているかどうかは、ぁぐぉ ドキュメントに注意を払ってください。

5.6.4

事前定義されたエイリアス

すどど では、一般的に使用されるファイルのパスと さげが を簡単に参照でき
るよう、エイリアスのセットが事前に定義されています〺• @yii〬 BaseYii.php ファイルがあるディレクトリ 〨フレームワーク・
ディレクトリとも呼ばれます〩• @app〬 現在実行中のアプリケーションの ベース・パス• @runtime〬 現在実行中のアプリケーションの ランタイム・パス 。デフォルトは @app/runtime 。

〲〵〶ぃえぁぐごぅげ 〵〮 鍵となる概念• @webroot〬 現在実行中のウェブ・アプリケーションのウェブ・ルー
ト・ディレクトリ。 エントリス・クリプトを含むディレクトリによって決定されます。
• @web〬 現在実行中のウェブ・アプリケーションのベース さげが。これは、 べどどぜぷづぢぜげづぱふづびぴ〺〺〤ぢちびづさひぬ と同じ値を持ちます。
• @vendor〬 ぃはねばはびづひ のベンダー・ディレクトリ 。デフォルトは @app/vendor。
• @bower〬 ぢはぷづひ パッケージ6 が含まれるルート・ディレクトリ。デフォルトは @vendor/bower 。
• @npm〬 のばね パッケージ7 が含まれるルート・ディレクトリ。デフォル
トは @vendor/npm 。
@yii エイリアスは エントリ・スクリプト に Yii.php ファイルを読み込んだ時点で定義されます。 エイリアスの残りの部分は、アプリケーションのコンストラクタ内で、アプリケーションの 構成情報 を適用するときに定義されます。
補足〺 @web と @webroot のエイリアスは、その説明が示しているように、ウェブ・アプリケーション の中で定義されます。
従って、デフォルトでは コンソール・アプリケーション では
利用できません。

5.6.5

エクステンションのエイリアス

ぃはねばはびづひ でインストールされる エクステンション のそれぞれに対してエイリアスが自動的に定義されます。 各エイリアスは、そのcomposer.json ファイルで宣言されたエクステンションのルート名前空間にちなんで名付けられ、 パッケージのルート・ディレクトリを表します。たとえば、あなたが yiisoft/yii2-jui エクステンションをインストー
ルしたとすると、 自動的に @yii/jui というエイリアスが ブートストラッ
プ 段階で定義されます。これは次のものと等価です。
Yii::setAlias('@yii/jui', 'VendorPath/yiisoft/yii2-jui');

5.7

クラスのオートローディング

すどどは、必要となるすべてのクラス・ファイルを特定してインクルードするにあたり、 クラスのオートローディング・メカニズム8 を頼りにします。 すどど は、ぐこげ〭〴 標準9 に準拠した、高性能なクラスのオートローダを提供しています。 このオートローダは、あなたが Yii.php ファイルをイ
ンクルードするときにインストールされます。
https://bower.io/
https://www.npmjs.com/
8
https://www.php.net/manual/ja/language.oop5.autoload.php
9
https://github.com/php-fig/fig-standards/blob/master/accepted/
PSR-4-autoloader.md
67〵〮〷〮 クラスのオートローディング〲〵〷

補足〺 説明を簡単にするため、このセクションではクラスのオートローディングについてのみ話します。しかし、 ここに記述されている内容は、インタフェイスとトレイトのオー
トローディングにも同様に適用されることに注意してくださ
い。

5.7.1

Yii オートローダを使用する

すどど のクラス・オートローダを使用するには、クラスを作成して名前を付けるとき、次の二つの単純なルールに従わなければなりません〺• 各クラスは 名前空間10 の下になければなりません 〨例 foo\bar\MyClass〩• 各クラスは次のアルゴリズムで決定される個別のファイルに保存されなければなりません〺// $className は先頭にバック・スラッシュを持たない完全修飾クラス名$classFile = Yii::getAlias('@' . str_replace('\\', '/', $className) .
'.php');

たとえば、クラス名と名前空間が foo\bar\MyClass であれば、対応するクラス・ファイルのパスの エイリアス は、 @foo/bar/MyClass.php になります。このエイリアスがファイル・パスとして解決できるようにするためには、@foo または @foo/bar のどちらかが、 ルート・エイリアス でなければなりません。
ベーシック・プロジェクト・テンプレート を使用している場合、最上位の名前空間 app の下にクラスを置くことができ、 そうすると、新しいエイリアスを定義しなくても、すどど によってそれらをオートロードできるようになります。これは @app が 事前定義されたエイリアス であるため
で、app\components\MyClass のようなクラス名を 今説明したアルゴリズムに従って、クラス・ファイル AppBasePath/components/MyClass.php であると解決することが出来ます。
アドバンスト・プロジェクト・テンプレート11 では、各層がそれ自身のルート・エイリアスを持っています。たとえば、 フロントエンド層は
ルート・エイリアス @frontend を持ち、バックエンド層のルート・エイリ
アスは @backend です。その結果、名前空間 frontend の下に フロントエン
ド・クラスを置き、バックエンド・クラスを backend の下に置けます。これで、これらのクラスは すどど のオートローダによって オートロードできるようになります。
独自の名前空間をオートローダに追加するためには、すどど〺〺びづぴぁぬどちび〨〩を使って、その名前空間のベース・ディレクトリに対するエイリアスを定義する必要があります。 例えば、path/to/foo ディレクトリに配置されている foo 名前空間に属するクラスをロードするためには、だすどど〺〺びづぴぁぬどちび〨〧぀てはは〧〬だばちぴと〯ぴは〯てはは〧〩 を呼び出します。
https://www.php.net/manual/ja/language.namespaces.php
https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/
README.md
10
11

〲〵〸

ぃえぁぐごぅげ 〵〮 鍵となる概念

5.7.2

クラス・マップ

すどど のクラス・オートローダは、 クラス・マップ 機能をサポートして
おり、クラス名を対応するクラス・ファイルのパスにマップできます。
オートローダがクラスをロードするときは、クラスがマップに見つかるかどうかを最初にチェックします。もしあれば、対応する ファイル・パ
スは、それ以上チェックされることなく、直接インクルードされます。
これでクラスのオートローディングを非常に高速化できます。 実際のところ、すべての すどど のコア・クラスは、この方法でオートロードされています。
次の方法で、 Yii::$classMap に格納されるクラス・マップにクラスを追加できます〺
Yii::$classMap['foo\bar\MyClass'] = 'path/to/MyClass.php';

クラス・ファイルのパスを指定するのに、 エイリアス を使うことができます。クラスが使用される前にマップが準備できるように、 クラス・
マップの設定は ブートストラップ プロセス内でする必要があります。

5.7.3

他のオートローダの使用

すどど はパッケージ依存関係マネージャとして ぃはねばはびづひ を包含しているので、ぃはねばはびづひ のオートローダもインストールすることをお勧めします。
あなたが独自のオートローダを持つサードパーティ・ライブラリを使用している場合は、 それらもインストールする必要があります。
すどど オートローダを他のオートローダと一緒に使うときは、他のすべてのオートローダがインストールされた 後で 、 Yii.php ファイルをインクルードする必要があります。これで すどど のオートローダが、任意クラスのオートローディング要求に応答する最初のものになります。 たとえば、次のコードは ベーシック・プロジェクト・テンプレート の エン
トリ・スクリプト から抜き出したものです。 最初の行は、ぃはねばはびづひ のオートローダをインストールしており、二行目は すどど のオートローダを
インストールしています。
require __DIR__ . '/../vendor/autoload.php';
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';

あなたは すどど のオートローダを使わず、ぃはねばはびづひ のオートローダだけを単独で使用することもできます。しかし、そうすることによって、 あな
たのクラスのオートローディングのパフォーマンスは低下し、クラスをオートロード可能にするために ぃはねばはびづひ が設定したルールに従わなければならなくなります。
情報〺 すどどのオートローダを使用したくない場合は、Yii.php
ファイルのあなた独自のバージョンを作成し、 それを エント
リ・スクリプト でインクルードする必要があります。

〵〮〸〮 サービス・ロケータ

5.7.4

〲〵〹

エクステンション・クラスのオートロード

すどど のオートローダは、 エクステンション クラスのオートロードが可能です。唯一の要件は、 エクステンションがその composer.json ファイルに
正しく autoload セクションを指定していることです。 autoload の指定方
法の詳細については ぃはねばはびづひ のドキュメント12 参照してください。
すどど のオートローダを使用しない場合でも、まだ ぃはねばはびづひ のオート
ローダがエクステンション・クラスをオートロードすることが可能です。

5.8

サービス・ロケータ

サービス・ロケータは、アプリケーションが必要とする可能性のある各種のサービス 〨またはコンポーネント〩 を提供する方法を知っているオブジェクトです。 サービス・ロケータ内では、各コンポーネントは単一のインスタンスとして存在し、ぉい によって一意に識別されます。 あなた
は、この ぉい を使用してサービス・ロケータからコンポーネントを取得できます。
すどど では、サービス・ロケータは単純に べどどぜつどぜこづひぶどっづがはっちぴはひ のイ
ンスタンス、またはその子クラスのインスタンスです。
すどど の中で最も一般的に使用されるサービス・ロケータは、\Yii::$app
を通じてアクセスできる アプリケーション・オブジェクトです。 これが提供するサービスは、 アプリケーション・コンポーネント と呼ばれる request 、 response、 urlManager などのコンポーネントです。あなたはサービス・ロケータによって提供される機能を通じて、 簡単に、これらのコンポーネントを構成、あるいは独自の実装に置き換え、といったことができます。
アプリケーション・オブジェクトの他に、各モジュール・オブジェク
トもまたサービス・ロケータです。モジュールは ツリー走査 を実装しています。
サービス・ロケータを使用する最初のステップは、コンポーネントを登録することです。コンポーネントは、 べどどぜつどぜこづひぶどっづがはっちぴはひ〺〺びづぴ〨〩
を通じて登録することができます。次のコードは、コンポーネントを登録するさまざまな方法を示しています。
use yii\di\ServiceLocator;
use yii\caching\FileCache;$locator = new ServiceLocator;// コンポーネントの作成に使われるクラス名を使用して "cache" を登録$locator->set('cache', 'yii\caching\ApcCache');// コンポーネントの作成に使われる構成情報配列を使用して "db" を登録
12

https://getcomposer.org/doc/04-schema.md#autoload〲〶〰

ぃえぁぐごぅげ 〵〮 鍵となる概念$locator->set('db', ['class' => 'yii\db\Connection','dsn' => 'mysql:host=localhost;dbname=demo','username' => 'root','password' => '',]);// コンポーネントを構築する匿名関数を使って "search" を登録$locator->set('search', function () {return new app\components\SolrService;});// コンポーネントを使って "pageCache" を登録$locator->set('pageCache', new FileCache);

いったんコンポーネントが登録されたら、次の二つの方法のいずれかで、その ぉい を使ってそれにアクセスすることができます〺$cache = $locator->get('cache');// または代りに$cache = $locator->cache;

上記のように、べどどぜつどぜこづひぶどっづがはっちぴはひ を使うと、コンポーネント ぉい を使用して、プロパティのようにコンポーネントにアクセスすることができます。 あなたが最初にコンポーネントにアクセスしたとき、べどどぜつどぜこづひぶどっづがはっちぴはひ は コンポーネントの登録情報を使用してコンポーネン
トの新しいインスタンスを作成し、 それを返します。後でそのコンポー
ネントが再度アクセスされた場合、サービス・ロケータは同じインスタ
ンスを返します。
べどどぜつどぜこづひぶどっづがはっちぴはひ〺〺とちび〨〩 を 使 っ て 、 コ ン ポ ー ネ ン ト ぉい がすでに登録されているかをチェックできます。 無効な ぉい で べどどぜつどぜこづひぶどっづがはっちぴはひ〺〺でづぴ〨〩 を呼び出した場合、例外が投げられます。
サービス・ロケータは多くの場合、 構成情報 で作成されるため、っはねばはのづのぴび という名前の書き込み可能プロパティが提供されています。
これで一度に複数のコンポーネントを設定して登録することができます。 次のコードは、サービス・ロケータ 〨例えば アプリケーション〩 を
db、cache、tz、search コンポーネントとともに構成するための構成情報配列を示しています。
return [// ...
'components' => ['db' => ['class' => 'yii\db\Connection','dsn' => 'mysql:host=localhost;dbname=demo','username' => 'root','password' => '',],'cache' => 'yii\caching\ApcCache','tz' => function() {〵〮〸〮 サービス・ロケータ

];

],

〲〶〱

return new \DateTimeZone(Yii::$app->formatter->defaultTimeZone);},'search' => function () {$solr = new app\components\SolrService('127.0.0.1');// ... その他の初期化 ...
return $solr;},

上記において、search コンポーネントを構成する別の方法があります。
SolrService のインスタンスを構築する ぐえぐ コールバックを直接に書く代りに、 下記のように、そういうコールバックを返すスタティックなクラ
ス・メソッドを使うことが出来ます。
class SolrServiceBuilder{
public static function build($ip){
return function () use ($ip) {$solr = new app\components\SolrService($ip);// ... その他の初期化 ...
return $solr;};}}
return [// ...
'components' => [// ...
'search' => SolrServiceBuilder::build('127.0.0.1'),],];

この方法は、すどど に属さないサードパーティのライブラリをカプセル化す
る すどど コンポーネントをリリースしようとする場合に、特に推奨される代替手法です。 上で示されているようなスタティックなメソッドを使ってサードパーティのオブジェクトを構築する複雑なロジックを表現します。 そうすれば、あなたのコンポーネントのユーザは、コンポーネントを構成するスタティックなメソッドを呼ぶ必要があるだけになります。

5.8.1

ツリー走査

モジュールは任意にネストすることが出来ます。すどど アプリケーション
は本質的にモジュールのツリーなのです。 これらのモジュールのそれぞれがサービス・ロケータである訳ですから、子がその親にアクセスできるようにするのは理にかなった事です。 これによって、モジュールは、ルートのサービス・ロケータを参照して Yii::$app->get('db') とする代りに、$this->get('db') とすることが出来ます。 また、開発者にモジュール〲〶〲

ぃえぁぐごぅげ 〵〮 鍵となる概念

内で構成をオーバーライドするオプションを提供できることも、この仕組の利点です。
モジュールからサービスを引き出そうとする全てのリクエストは、
そのモジュールが要求に応じられない場合は、すべてその親に渡されます。
モジュール内のコンポーネントの構成情報は、親モジュール内のコ
ンポーネントの構成情報とは決してマージされないことに注意して下さい。 サービス・ロケータ・パターンによって私たちは名前の付いたサービスを定義することが出来ますが、同じ名前のサービスが同じ構成パラ
メータを使用すると想定することは出来ません。

5.9

依存注入コンテナ

依存注入 〨いぉ〩 コンテナは、オブジェクトとそれが依存するすべてのオブジェクトを、インスタンス化し、設定する方法を知っているオブジェク
トです。 なぜ いぉ コンテナが便利なのかは、きちひぴどの うはぷぬづひ の記事13 の説
明がわかりやすいでしょう。 ここでは、主に すどど の提供する いぉ コンテ
ナの使用方法を説明します。

5.9.1

依存注入

すどど は べどどぜつどぜぃはのぴちどのづひ クラスを通して いぉ コンテナの機能を提供します。 これは、次の種類の依存注入をサポートしています〺• コンストラクタ・インジェクション
• メソッド・インジェクション
• セッター〯プロパティ・インジェクション
• ぐえぐ コーラブル・インジェクション
コンストラクタ・インジェクション
いぉ コンテナは、コンストラクタ引数の型ヒントの助けを借りて、コンス
トラクタ・インジェクションをサポートしています。 コンテナが新しいオブジェクトの作成に使用されるさい、そのオブジェクトがどういうク
ラスやインタフェイスに依存しているかを、型ヒントがコンテナに教えます。 コンテナは、依存するクラスやインタフェイスのインスタンスを取得して、 コンストラクタを通して、新しいオブジェクトにそれらを注入しようと試みます。たとえば
class Foo{
public function __construct(Bar $bar)
{
}
}
13

https://martinfowler.com/articles/injection.html

〵〮〹〮 依存注入コンテナ〲〶〳$foo = $container->get('Foo');// これは下記と等価:$bar = new Bar;
$foo = new Foo($bar);

メソッド・インジェクション
通常、クラスの依存はコンストラクタに渡されて、そのクラスの内部
でライフサイクル全体にわたって利用可能になります。 メソッド・イ
ンジェクションを使うと、クラスのメソッドの一つだけに必要となる依存、例えば、コンストラクタに渡すことが不可能であったり、 大半のユース・ケースにおいてはオーバーヘッドが大きすぎるような依存を提供することが可能になります。
クラス・メソッドを次の例の doSomething メソッドのように定義することが出来ます。
class MyClass extends \yii\base\Component{
public function __construct(/* 軽量の依存はここに */ , $config = []){// ...
}}

public function doSomething($param1, \my\heavy\Dependency $something){// $something を使って何かをする}

このメソッドを呼ぶためには、あなた自身で \my\heavy\Dependency のインスタンスを渡すか、または、次のように べどどぜつどぜぃはのぴちどのづひ〺〺どのぶはにづ〨〩を使います。
$obj = new MyClass(/*...*/ );Yii::$container->invoke([$obj, 'doSomething'], ['param1' => 42]); //$something は DI コンテナによって提供される

セッター〯プロパティ・インジェクション
セッター〯プロパティ・インジェクションは、構成情報 を通してサポートされます。 依存を登録するときや、新しいオブジェクトを作成するときに、対応するセッターまたはプロパティを通しての依存注入に使用される構成情報を、 コンテナに提供することが出来ます。 たとえば
use yii\base\BaseObject;class Foo extends BaseObject{

〲〶〴ぃえぁぐごぅげ 〵〮 鍵となる概念
public $bar;
private $_qux;
public function getQux(){
return $this->_qux;}}

public function setQux(Qux $qux){$this->_qux = $qux;}$container->get('Foo', [], ['bar' => $container->get('Bar'),'qux' => $container->get('Qux'),]);

情報〺 べどどぜつどぜぃはのぴちどのづひ〺〺でづぴ〨〩 メソッドは三番目のパラメー
タを、生成されるオブジェクトに適用されるべき構成情報配列として受け取ります。 クラスが べどどぜぢちびづぜぃはのてどでふひちぢぬづ
インタフェイスを実装している場合 〨例えば、クラスが べどど
ぜぢちびづぜあちびづくぢなづっぴ である場合〩 には、 この構成情報配列がクラスのコンストラクタの最後のパラメータとして渡されます。 そうでない場合は、構成情報はオブジェクトが生成された 後で 適用されることになります。
ぐえぐ コーラブル・インジェクション
この場合、コンテナは、登録された ぐえぐ のコーラブルを使用して、クラスの新しいインスタンスを構築します。 べどどぜつどぜぃはのぴちどのづひ〺〺でづぴ〨〩 が呼ばれるたびに、対応するコーラブルが起動されます。 このコーラブル
が、依存を解決し、新しく作成されたオブジェクトに適切に依存を注入する役目を果たします。 たとえば
$container->set('Foo', function ($container, $params, $config) {$foo = new Foo(new Bar);// ... その他の初期化 ...
return $foo;});$foo = $container->get('Foo');

新しいオブジェクトを構築するための複雑なロジックを隠蔽するために、スタティックなクラスメソッドをコーラブルとして使うことが出来ます。例えば、
class FooBuilder{〵〮〹〮 依存注入コンテナ}〲〶〵

public static function build($container, $params, $config){$foo = new Foo(new Bar);// ... その他の初期化 ...
return $foo;}$container->set('Foo', ['app\helper\FooBuilder', 'build']);$foo = $container->get('Foo');

このようにすれば、Foo クラスを構成しようとする人は、Foo がどのように構築されるかを気にする必要はもうなくなります。

5.9.2

依存を登録する

べどどぜつどぜぃはのぴちどのづひ〺〺びづぴ〨〩 を使って依存を登録することができます。登録には依存の名前だけでなく、依存の定義が必要です。 依存の名前は、クラス名、インタフェイス名、エイリアス名を指定することができます。 依存の定義には、クラス名、構成情報配列、ぐえぐのコーラブルを指定できます。
$container = new \yii\di\Container;// クラス名そのままの登録。これは省略可能です。
$container->set('yii\db\Connection');// インタフェイスの登録// クラスがインタフェイスに依存する場合、対応するクラスが// 依存オブジェクトとしてインスタンス化されます$container->set('yii\mail\MailInterface', 'yii\swiftmailer\Mailer');// エイリアス名の登録。$container->get('foo') を使って// Connection のインスタンスを作成できます$container->set('foo', 'yii\db\Connection');// `Instance::of` を使ってエイリアスの登録。
$container->set('bar', Instance::of('foo'));// 構成情報をともなうクラスの登録。クラスが get() でインスタンス化// されるとき構成情報が適用されます$container->set('yii\db\Connection', ['dsn' => 'mysql:host=127.0.0.1;dbname=demo','username' => 'root','password' => '','charset' => 'utf8',]);// クラスの構成情報をともなうエイリアス名の登録// この場合、クラスを指定する "class" または "__class" 要素が必要です$container->set('db', [

〲〶〶

]);

ぃえぁぐごぅげ 〵〮 鍵となる概念'class' => 'yii\db\Connection','dsn' => 'mysql:host=127.0.0.1;dbname=demo','username' => 'root','password' => '','charset' => 'utf8',// コーラブルなクロージャまたは配列の登録// このコーラブルは $container->get('db') が呼ばれるたびに実行されます$container->set('db', function ($container, $params, $config) {return new \yii\db\Connection($config);});$container->set('db', ['app\db\DbFactory', 'create']);// コンポーネント・インスタンスの登録// $container->get('pageCache') は呼ばれるたびに毎回同じインスタンスを返します$container->set('pageCache', new FileCache);補足〺 依存の名前が対応する依存の定義と同じである場合は、それを いぉ コンテナに登録する必要はありません。
set() を介して登録された依存は、依存が必要とされるたびにインスタン

スを生成します。 べどどぜつどぜぃはのぴちどのづひ〺〺びづぴこどのでぬづぴはの〨〩 を使うと、 単一のインスタンスしか生成しない依存を登録することができます〺$container->setSingleton('yii\db\Connection', ['dsn' => 'mysql:host=127.0.0.1;dbname=demo','username' => 'root','password' => '','charset' => 'utf8',
]);

5.9.3

依存を解決する

依存を登録すると、新しいオブジェクトを作成するのに いぉ コンテナを使用することができます。 そして、コンテナが自動的に依存をインスタンス化し、新しく作成されたオブジェクトに注入して、 依存を解決します。依存の解決は再帰的に行われます。つまり、ある依存が他の依存を持っている場合、 それらの依存も自動的に解決されます。
でづぴ〨〩 を使って、オブジェクトのインスタンスを作成または取得することができます。 このメソッドは依存の名前を引数として取りますが、依存の名前は、クラス名、インタフェイス名、あるいは、エイリアス名で指定できます。 依存の名前は、 びづぴ〨〩 を介して登録されていることもあれば、 びづぴこどのでぬづぴはの〨〩 を介して登録されていることもあります。
オプションで、クラスのコンストラクタのパラメータのリストや、設定
情報 を渡して、新しく作成されるオブジェクトを構成することも出来ま
す。
たとえば、

〵〮〹〮 依存注入コンテナ〲〶〷// "db" は事前に登録されたエイリアス名$db = $container->get('db');// これと同じ意味: $engine = new \app\components\SearchEngine($apiKey,$apiSecret, ['type' => 1]);$engine = $container->get('app\components\SearchEngine', [$apiKey,$apiSecret], ['type' => 1]);

見えないところで、いぉコンテナは、単に新しいオブジェクトを作成する
よりもはるかに多くの作業を行います。 コンテナは、最初にクラスのコ
ンストラクタを調査し、依存するクラスまたはインタフェイスの名前を見つけると、 自動的にそれらの依存を再帰的に解決します。
次 の コ ー ド で よ り 洗 練 さ れ た 例 を 示 し ま す 。UserLister ク ラ ス はUserFinderInterface インタフェイスを実装するオブジェクトに依存します。UserFinder クラスはこのインタフェイスを実装していて、かつ、Connection オブジェクトに依存します。これらのすべての依存は、クラスのコンストラクタのパラメータの型ヒントによって宣言されています。
依存の登録が適切にされていれば、いぉ コンテナは自動的にこれらの依存を解決し、単純に get('userLister') を呼び出すだけで新しい UserLister イ
ンスタンスを作成できます。
namespace app\models;
use yii\base\BaseObject;
use yii\db\Connection;use yii\di\Container;interface UserFinderInterface{function findUser();}class UserFinder extends BaseObject implements UserFinderInterface{
public $db;
public function __construct(Connection $db, $config = []){$this->db = $db;
parent::__construct($config);}}

public function findUser(){}class UserLister extends BaseObject{
public $finder;

〲〶〸

}

ぃえぁぐごぅげ 〵〮 鍵となる概念
public function __construct(UserFinderInterface $finder, $config = []){$this->finder = $finder;
parent::__construct($config);}$container = new Container;$container->set('yii\db\Connection', ['dsn' => '...',]);$container->set('app\models\UserFinderInterface', ['class' => 'app\models\UserFinder',]);$container->set('userLister', 'app\models\UserLister');$lister = $container->get('userLister');// と、いうのはこれと同じ:$db = new \yii\db\Connection(['dsn' => '...']);$finder = new UserFinder($db);$lister = new UserLister($finder);

5.9.4

実際の使用方法

あなたのアプリケーションの エントリ・スクリプト で Yii.php ファ
イルをインクルードするとき、 すどど は いぉ コンテナを作成します。この いぉ コンテナは すどど〺〺〤っはのぴちどのづひ を介してアクセス可能です。 すどど〺〺
っひづちぴづくぢなづっぴ〨〩 を呼び出したとき、 このメソッドは実際にはコンテナのでづぴ〨〩 メソッドを呼び出して新しいオブジェクトを作成します。 前述のとおり、いぉ コンテナは〨もしあれば〩自動的に依存を解決し、取得されたオブジェクトにそれらを注入します。 すどど は、新しいオブジェクトを作成するコアコードのほとんどにおいて すどど〺〺っひづちぴづくぢなづっぴ〨〩 を使用しています。このことは、 すどど〺〺〤っはのぴちどのづひ を操作することでグローバルに
オブジェクトをカスタマイズすることができるということを意味しています。
例として、 べどどぜぷどつでづぴびぜがどのにぐちでづひ のページ・ネーションボタンのデフォルト個数をグローバルにカスタマイズしてみましょう。
\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]);

そして、次のコードでビューでウィジェットを使用すれば、maxButtonCount
プロパティは、 クラスで定義されているデフォルト値 〱〰 の代わりに 〵で初期化されます。
echo \yii\widgets\LinkPager::widget();

ただし、いぉ コンテナを経由して設定された値を上書きすることは、まだ可能です〺〵〮〹〮 依存注入コンテナ〲〶〹echo \yii\widgets\LinkPager::widget(['maxButtonCount' => 20]);

ヒント〺 ウィジェットの呼び出しで与えられたプロパティは常に いぉ コンテナが持つ定義を上書きします。 たとえ、'options'=> ['id' => 'mypager'] のように配列を指定したとしても、 それらは他のオプションとマージされるのでなく、他のオプションを置換えてしまいます。
もう一つの例は、いぉ コンテナの自動コンストラクタ・インジェクションの利点を活かすものです。 あなたのコントローラ・クラスが、ホテ
ル予約サービスのような、いくつかの他のオブジェクトに依存するとします。 あなたは、コンストラクタのパラメータを通して依存を宣言して、いぉ コンテナにそれを解決させることができます。
namespace app\controllers;
use yii\web\Controller;
use app\components\BookingInterface;class HotelController extends Controller{
protected $bookingService;}

public function __construct($id, $module, BookingInterface$bookingService, $config = []){$this->bookingService = $bookingService;
parent::__construct($id, $module, $config);}

あなたがブラウザからこのコントローラにアクセスすると、BookingInterface
をインスタンス化できない、という不平を言う エラーが表示されるでしょう。これは、この依存に対処する方法を いぉ コンテナに教える必要があるからです〺\Yii::$container->set('app\components\BookingInterface','app\components\BookingService');

これで、あなたが再びコントローラにアクセスするときは、app\components\BookingServiceのインスタンスが作成され、コントローラのコンストラクタに〳番目のパラメータとして注入されるようになります。
すどど 〲〮〰〮〳〶 以降は、ぐえぐ 〷 を使う場合に、ウェブおよびコンソール両方のコントローラでアクション・インジェクションを利用することが出来ます。
namespace app\controllers;
use yii\web\Controller;〲〷〰

ぃえぁぐごぅげ 〵〮 鍵となる概念

use app\components\BookingInterface;class HotelController extends Controller{
public function actionBook($id, BookingInterface $bookingService){$result = $bookingService->book($id);// ...
}}

5.9.5

高度な実際の使用方法

ぁぐぉ アプリケーションを開発していて、以下のクラスを持っているとします。
• app\components\Request クラス。yii\web\Request から拡張され、追加の機能を提供する。
• app\components\Response クラス。yii\web\Response から拡張。 生成されるときに、format プロパティが json に設定されなければならない。
• app\storage\FileStorage および app\storage\DocumentsReader クラス。
何らかのファイルストレージに配置されているドキュメントを操作するロジックを実装する。
class FileStorage{
public function __construct($root) {// あれやこれや}}class DocumentsReader{
public function __construct(FileStorage $fs) {// なんやかんや}}びづぴいづてどのどぴどはのび〨〩 または びづぴこどのでぬづぴはのび〨〩 のメソッドに構成情報の配列を渡して、複数の定義を一度に構成することが可能です。 これらのメソッドは、構成情報配列を反復して、各アイテムに対し、 それぞれ
びづぴ〨〩 を呼び出します。
構成情報配列のフォーマットは、• key〺 クラス名、インタフェイス名、または、エイリアス名。 このキーが びづぴ〨〩 メソッドの最初の引数 $class として渡されます。
• value〺 $class と関連づけられる定義。指定できる値は、びづぴ〨〩 の$definition パラメータのドキュメントで説明されています。 びづぴ〨〩
メソッドに二番目のパラメータ $definition として渡されます。
例として、上述の要求に従うように私たちのコンテナを構成しましょう。

〵〮〹〮 依存注入コンテナ〲〷〱$container->setDefinitions(['yii\web\Request' => 'app\components\Request','yii\web\Response' => ['class' => 'app\components\Response','format' => 'json'],'app\storage\DocumentsReader' => function ($container, $params, $config){$fs = new app\storage\FileStorage('/var/tempfiles');return new app\storage\DocumentsReader($fs);}]);$reader = $container->get('app\storage\DocumentsReader');// 構成情報に書かれている依存とともに DocumentReader オブジェクトが生成されますヒント〺 バージョン 〲〮〰〮〱〱 以降では、アプリケーションの構成
情報を使って、宣言的なスタイルでコンテナを構成することが出来ます。 構成情報 のガイドの アプリケーションの構成のセクションを参照してください。
これで全部動きますが、DocumentWriter クラスを生成する必要がある場合には、FileStorage オブジェクトを生成する行をコピペすることになるでしょう。 もちろん、それが一番スマートな方法ではありません。
依存を解決する のセクションで説明したように、びづぴ〨〩 と びづぴこどのでぬづぴはの〨〩
は、 オプションで、第三の引数として依存のコンストラクタのパラメー
タを取ることが出来ます。 コンストラクタのパラメータを設定するために、__construct() オプションを使うことが出来ます。
では、私たちの例を修正しましょう。
$container->setDefinitions(['tempFileStorage' => [ // 便利なようにエイリアスを作りました'class' => 'app\storage\FileStorage','__construct()' => ['/var/tempfiles'], // 何らかの構成ファイルから抽出することも可能],'app\storage\DocumentsReader' => ['class' => 'app\storage\DocumentsReader','__construct()' => [Instance::of('tempFileStorage')],],'app\storage\DocumentsWriter' => ['class' => 'app\storage\DocumentsWriter','__construct()' => [Instance::of('tempFileStorage')]]]);$reader = $container->get('app\storage\DocumentsReader');// 前の例と全く同じオブジェクトが生成されます
Instance::of('tempFileStorage') という記法に気づいたことでしょう。 こ
れは、ぃはのぴちどのづひ が、tempFileStorage という名前で登録されている依存を〲〷〲

ぃえぁぐごぅげ 〵〮 鍵となる概念

黙示的に提供して、 app\storage\DocumentsWriter のコンストラクタの最初の引数として渡す、ということを意味しています。
補足〺 びづぴいづてどのどぴどはのび〨〩 および びづぴこどのでぬづぴはのび〨〩 のメソッド
は、バージョン 〲〮〰〮〱〱 以降で利用できます。
構成情報の最適化にかかわるもう一つのステップは、いくつかの依存をシングルトンとして登録することです。 びづぴ〨〩 を通じて登録された依存は、必要になるたびに、毎回インスタンス化されます。 しかし、ある種のクラスは実行時を通じて状態を変化させませんので、 アプリケーショ
ンのパフォーマンスを高めるためにシングルトンとして登録することが出来ます。
app\storage\FileStorage クラスが好例でしょう。これは単純な ぁぐぉ に
よってファイル・システムに対する何らかの操作を実行するもの 〨例えば
$fs->read() や $fs->write()〩 ですが、これらの操作はクラスの内部状態を変化させないものです。 従って、このクラスのインスタンスを一度だけ生成して、それを複数回使用することが可能です。
$container->setSingletons(['tempFileStorage' => ['class' => 'app\storage\FileStorage','__construct()' => ['/var/tempfiles']],]);$container->setDefinitions(['app\storage\DocumentsReader' => ['class' => 'app\storage\DocumentsReader','__construct()' => [Instance::of('tempFileStorage')],],'app\storage\DocumentsWriter' => ['class' => 'app\storage\DocumentsWriter','__construct()' => [Instance::of('tempFileStorage')],]]);$reader = $container->get('app\storage\DocumentsReader');

5.9.6

いつ依存を登録するか依存は、新しいオブジェクトが作成されるとき必要とされるので、それらの登録は可能な限り早期に行われるべきです。 推奨されるプラクティスは以下のとおりです〺• あなたがアプリケーションの開発者である場合は、アプリケーショ
ンの構成情報を使って依存を登録することが出来ます。 構成情報のガイドの アプリケーションの構成 のセクションを読んでください。

〵〮〹〮 依存注入コンテナ〲〷〳• あなたが再配布可能な エクステンション の開発者である場合は、エクステンションのブートストラップ・クラス内で 依存を登録することができます。

5.9.7

まとめ

依存注入と サービス・ロケータ はともに、疎結合でよりテストしやすい方法でのソフトウェア構築を可能にする、 定番のデザインパターンです。 依存注入とサービス・ロケータへのより深い理解を得るために、
きちひぴどの の記事14 を読むことを強くお勧めします。
すどど はその サービス・ロケータ を、依存注入 〨いぉ〩 コンテナの上に実装しています。 サービス・ロケータは、新しいオブジェクトのインスタンスを作成しようとするとき、いぉ コンテナに呼び出しを転送します。 後者は、依存を、上で説明したように自動的に解決します。

14

https://martinfowler.com/articles/injection.html

〲〷〴

ぃえぁぐごぅげ 〵〮 鍵となる概念

Chapter 6

データベースの取り扱い
6.1

データベース・アクセス・オブジェクト

ぐいく1 の上に構築された すどど いぁく 〨データベース・アクセス・オブジェク
ト〩 は、 リレーショナル・データベースにアクセスするためのオブジェ
クト指向 ぁぐぉ を提供するものです。 これは、データベースにアクセスする他のもっと高度な方法、例えば クエリ・ビルダ や アクティブ・レコー
ド の基礎でもあります。
すどど いぁく を使うときは、主として素の こけが と ぐえぐ 配列を扱う必要があります。 結果として、すどど いぁく はデータベースにアクセスする方法
としては最も効率的なものになります。 しかし、こけが の構文はデータベースによってさまざまに異なる場合がありますので、すどど いぁく を使用するということは、特定のデータベースに依存しないアプリケーションを作るためには追加の労力が必要になる、ということをも同時に意味します。
すどど 〲〮〰 では、いぁく は下記の いあきこ のサポートを内蔵しています。
• きべこけが2• きちひどちいあ3• こけがどぴづ4• ぐはびぴでひづこけが5 〺 バージョン 〸〮〴 以上。
• ぃさあげぉい6 〺 バージョン 〹〮〳 以上。
• くひちっぬづ7• きここけが8 〺 バージョン 〲〰〰〸 以上。
補足〺 ぐえぐ 〷 用の ばつはたはっど の新しいバージョンは、現在、https://www.php.net/manual/ja/book.pdo.php
https://www.mysql.com/
3https://mariadb.com/
4https://sqlite.org/
5
https://www.postgresql.org/
6
https://www.cubrid.org/
7
https://www.oracle.com/database/8
https://www.microsoft.com/en-us/sqlserver/default.aspx
1
2

〲〷〵

〲〷〶

ぃえぁぐごぅげ 〶〮 データベースの取り扱い
ソース・コードとしてのみ存在します。 コミュニティによる
説明9 に従ってコンパイルするか、 または、ぐいく エミュレー
ション・レイヤ10 を使って下さい。

6.1.1

DB 接続を作成する

データベースにアクセスするためには、まずは、べどどぜつぢぜぃはののづっぴどはの のインスタンスを作成して、データベースに接続する必要があります。
$db = new yii\db\Connection(['dsn' => 'mysql:host=localhost;dbname=example','username' => 'root','password' => '','charset' => 'utf8',]);

いあ 接続は、たいていは、さまざまな場所でアクセスする必要がありますので、次のように、 アプリケーション・コンポーネント の形式で構成するのが通例です。
return [// ...
'components' => [// ...
'db' => ['class' => 'yii\db\Connection','dsn' => 'mysql:host=localhost;dbname=example','username' => 'root','password' => '','charset' => 'utf8',],],// ...
];

こうすると Yii::$app->db という式で いあ 接続にアクセスすることが出来るようになります。
ヒント〺 あなたのアプリケーションが複数のデータベースにアクセスする必要がある場合は、複数の いあ アプリケーショ
ン・コンポーネントを構成することが出来ます。
いあ 接続を構成するときは、つねに つびの プロパティによってデータ・ソー
ス名 〨いこぎ〩 を指定しなければなりません。 いこぎ の形式はデータベース
によってさまざまに異なります。 詳細は ぐえぐ マニュアル11 を参照して下さい。下記にいくつかの例を挙げます。
https://github.com/yiisoft/yii2/issues/10975#issuecomment-248479268
https://github.com/taq/pdooci11
https://www.php.net/manual/ja/function.PDO-construct.php
910〶〮〱〮 データベース・アクセス・オブジェクト〲〷〷• きべこけが〬 きちひどちいあ〺 mysql:host=localhost;dbname=mydatabase• こけがどぴづ〺 sqlite:/path/to/database/file• ぐはびぴでひづこけが〺 pgsql:host=localhost;port=5432;dbname=mydatabase• ぃさあげぉい〺 cubrid:dbname=demodb;host=localhost;port=33000• きこ こけが こづひぶづひ 〨びぱぬびひぶ ドライバ経由〩〺 sqlsrv:Server=localhost;Database=mydatabase• きこ こけが こづひぶづひ 〨つぢぬどぢ ドライバ経由〩〺 dblib:host=localhost;dbname=mydatabase• きこ こけが こづひぶづひ 〨ねびびぱぬ ドライバ経由〩〺 mssql:host=localhost;dbname=mydatabase• くひちっぬづ〺 oci:dbname=//localhost:1521/mydatabase
くいあぃ 経由でデータベースに接続しようとする場合は、べどどぜつぢぜぃはののづっぴどはの〺〺〤つひどぶづひぎちねづ プロパティを構成して、すどど に実際のデータベースのタイプを知らせなければならないことに注意してください。 例えば、
'db' => ['class' => 'yii\db\Connection','driverName' => 'mysql','dsn' => 'odbc:Driver={MySQL};Server=localhost;Database=test','username' => 'root','password' => '',],つびの プロパティに加えて、たいていは ふびづひのちねづ と ばちびびぷはひつ も構成しなければなりません。 構成可能なプロパティの全てのリストは べどどぜつぢ
ぜぃはののづっぴどはの を参照して下さい。
情報〺 いあ 接続のインスタンスを作成するとき、実際のデータベース接続は、最初の こけが を実行するか、 はばづの〨〩 メソッドを明示的に呼ぶかするまでは確立されません。
ヒント〺 時として、何らかの環境変数を初期化するために、
データベース接続を確立した直後に何かクエリを実行したい場合があるでしょう 〨例えば、タイムゾーンや文字セットを設定するなどです〩。 そうするために、データベース接続のちてぴづひくばづの イベントに対するイベント・ハンドラを登録することが出来ます。 以下のように、アプリケーションの構成情報に直接にハンドラを登録することが出来ます。
'db' => [// ...
'on afterOpen' => function($event) {// $event->sender は DB 接続を指す$event->sender->createCommand("SET time_zone ='UTC'")->execute();}]

きこ こけが こづひぶづひ でバイナリ・データを正しく処理するためには追加の接続オプションが必要になります。

〲〷〸ぃえぁぐごぅげ 〶〮 データベースの取り扱い'db' => ['class' => 'yii\db\Connection','dsn' => 'sqlsrv:Server=localhost;Database=mydatabase','attributes' => [\PDO::SQLSRV_ATTR_ENCODING => \PDO::SQLSRV_ENCODING_SYSTEM
]
],

6.1.2

SQL クエリを実行する

いったんデータベース接続のインスタンスを得てしまえば、次の手順に従って こけが クエリを実行することが出来ます。
〱〮 素の こけが クエリで べどどぜつぢぜぃはねねちのつ を作成する。
〲〮 パラメータをバインドする 〨オプション〩。
〳〮 べどどぜつぢぜぃはねねちのつ の こけが 実行メソッドの一つを呼ぶ。
次に、データベースからデータを読み出すさまざまな方法を例示します。
// 行のセットを返す。各行は、カラム名と値の連想配列。
// クエリが結果を返さなかった場合は空の配列が返される。
$posts = Yii::$app->db->createCommand('SELECT * FROM post')->queryAll();// 一つの行 (最初の行) を返す。
// クエリの結果が無かった場合は false が返される。
$post = Yii::$app->db->createCommand('SELECT * FROM post WHERE id=1')->queryOne();// 一つのカラム (最初のカラム) を返す。
// クエリが結果を返さなかった場合は空の配列が返される。
$titles = Yii::$app->db->createCommand('SELECT title FROM post')->queryColumn();// スカラ値を返す。
// クエリの結果が無かった場合は false が返される。
$count = Yii::$app->db->createCommand('SELECT COUNT(*) FROM post')->queryScalar();補足〺 精度を保つために、対応するデータベース・カラムの型が数値である場合でも、 データベースから取得されたデータ
は、全て文字列として表現されます。
パラメータをバインドする
パラメータを持つ こけが から いあ コマンドを作成するときは、こけが イン
ジェクション攻撃を防止するために、 ほとんど全ての場合においてパラメータをバインドする手法を用いるべきです。例えば、

〶〮〱〮 データベース・アクセス・オブジェクト〲〷〹$post = Yii::$app->db->createCommand('SELECT * FROM post WHERE id=:id AND
status=:status')->bindValue(':id', $_GET['id'])->bindValue(':status', 1)->queryOne();

こけが 文において、一つまたは複数のパラメータ・プレースホルダ 〨例
えば、上記のサンプルにおける :id〩 を埋め込むことが出来ます。 パラ
メータ・プレースホルダは、コロンから始まる文字列でなければなりません。 そして、次に掲げるパラメータをバインドするメソッドの一つを使って、パラメータの値をバインドします。
• ぢどのつざちぬふづ〨〩〺 一つのパラメータの値をバインドします。
• ぢどのつざちぬふづび〨〩〺 一回の呼び出しで複数のパラメータの値をバインドします。
• ぢどのつぐちひちね〨〩〺 ぢどのつざちぬふづ〨〩 と似ていますが、 パラメータを参照渡しでバインドすることもサポートしています。
次の例はパラメータをバインドする方法の選択肢を示すものです。
$params = [':id' => $_GET['id'], ':status' => 1];$post = Yii::$app->db->createCommand('SELECT * FROM post WHERE id=:id AND
status=:status')->bindValues($params)->queryOne();$post = Yii::$app->db->createCommand('SELECT * FROM post WHERE id=:id AND
status=:status', $params)->queryOne();パラメータ・バインディングは プリペアド・ステートメント12 によって実装されています。 パラメータ・バインディングには、こけが インジェク
ション攻撃を防止する以外にも、こけが 文を一度だけ準備して異なるパラメータで複数回実行することにより、 パフォーマンスを向上させる効果もあります。例えば、$command = Yii::$app->db->createCommand('SELECT * FROM post WHERE id=:id');$post1 = $command->bindValue(':id', 1)->queryOne();$post2 = $command->bindValue(':id', 2)->queryOne();// ...

ぢどのつぐちひちね〨〩 はパラメータを参照渡しでバインドすることをサポートしていますので、 上記のコードは次のように書くことも出来ます。
$command = Yii::$app->db->createCommand('SELECT * FROM post WHERE id=:id')->bindParam(':id', $id);$id = 1;
12https://www.php.net/manual/ja/mysqli.quickstart.prepared-statements.php〲〸〰

ぃえぁぐごぅげ 〶〮 データベースの取り扱い$post1 = $command->queryOne();$id = 2;
$post2 = $command->queryOne();

クエリの実行の前にプレースホルダを変数 $id にバインドし、そして、後に続く各回の実行の前にその変数の値を変更していること 〨これは、たいてい、ループで行います〩 に着目してください。 このやり方でクエリを実行すると、パラメータの値が違うごとに新しいクエリを実行するのに比べて、 はるかに効率を良くすることが出来ます。
情報〺 パラメータ・バインディングは、素の こけが を含む文字
列に値を挿入しなければならない場所でのみ使用されます。
クエリ・ビルダ や アクティブ・レコード のような高レベルの抽象的レイヤーでは、 多くの場所で こけが に変換される値の配列を指定する場合がよくあります。 これらの場所では すどど によってパラメータ・バインディングが内部的に実行されます
ので、パラメータを手動で指定する必要はありません。
こぅがぅぃご しないクエリを実行する
今までのセクションで紹介した queryXyz() メソッドは、すべて、データ
ベースからデータを取得する こぅがぅぃご クエリを扱うものでした。 デー
タを返さないクエリのためには、代りに べどどぜつぢぜぃはねねちのつ〺〺づへづっふぴづ〨〩 メ
ソッドを呼ばなければなりません。例えば、
Yii::$app->db->createCommand('UPDATE post SET status=1 WHERE id=1')->execute();

べどどぜつぢぜぃはねねちのつ〺〺づへづっふぴづ〨〩 メソッドは こけが の実行によって影響を受けた行の数を返します。
ぉぎこぅげご、さぐいぁごぅ および いぅがぅごぅ クエリのためには、素の こけがを書く代りに、それぞれ、 どのびづひぴ〨〩、ふばつちぴづ〨〩、つづぬづぴづ〨〩 を呼んで、対応する こけが を構築することが出来ます。 これらのメソッドは、テーブ
ルとカラムの名前を適切に引用符で囲み、パラメータの値をバインドします。例えば、// INSERT (テーブル名, カラムの値)
Yii::$app->db->createCommand()->insert('user', ['name' => 'Sam','age' => 30,])->execute();// UPDATE (テーブル名, カラムの値, 条件)
Yii::$app->db->createCommand()->update('user', ['status' => 1], 'age >30')->execute();// DELETE (テーブル名, 条件)
Yii::$app->db->createCommand()->delete('user', 'status = 0')->execute();〶〮〱〮 データベース・アクセス・オブジェクト〲〸〱

ぢちぴっとぉのびづひぴ〨〩 を呼んで複数の行を一気に挿入することも出来ます。 この方法は、一度に一行を挿入するよりはるかに効率的です。
// テーブル名, カラム名, カラムの値
Yii::$app->db->createCommand()->batchInsert('user', ['name', 'age'], [['Tom', 30],['Jane', 20],['Linda', 25],])->execute();

もう一つの有用なメソッドは ふばびづひぴ〨〩 です。ふばびづひぴ は、〨ユニーク制約に合致する〩行がまだ存在しない場合はデータベース・テーブルに行を挿入し、 既に行が存在している場合は行を更新する、アトミックな操作です。
Yii::$app->db->createCommand()->upsert('pages', ['name' => 'フロント・ページ','url' => 'https://example.com/', // url はユニーク'visits' => 0,], ['visits' => new \yii\db\Expression('visits + 1'),], $params)->execute();

上記のコードは、新しいページのレコードを挿入するか、または、既存のレコードの訪問者カウンタをインクリメントします。
上述のメソッド群はクエリを生成するだけであり、実際にそれを実行するためには、常に づへづっふぴづ〨〩 を呼び出す必要があることに注意してく
ださい。

6.1.3

テーブルとカラムの名前を引用符で囲む

特定のデータベースに依存しないコードを書くときには、テーブルとカラムの名前を適切に引用符で囲むことが、たいてい、頭痛の種になります。 データベースによって名前を引用符で囲む規則がさまざまに異なるからです。 この問題を克服するために、次のように、すどど によって導入された引用符の構文を使用することが出来ます。
• [[カラム名]]〺 引用符で囲むべきカラム名は、二重角括弧で包む。
• {{テーブル名}}〺 引用符で囲むべきテーブル名は、二重波括弧で包む。
すどど いぁく は、このような構文を、いあきこ 固有の文法に従って、 適切な引用符で囲まれたカラム名とテーブル名に自動的に変換します。 例えば、// MySQL では SELECT COUNT(`id`) FROM `employee` という SQL が実行される$count = Yii::$app->db->createCommand("SELECT COUNT([[id]]) FROM{{employee}}")->queryScalar();〲〸〲

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

テーブル接頭辞を使う
あなたの いあ テーブル名のほとんどが何か共通の接頭辞を持っている場
合は、 すどど いぁく によって提供されているテーブル接頭辞の機能を使うことが出来ます。
最初に、アプリケーションの構成情報で、べどどぜつぢぜぃはののづっぴどはの〺〺〤ぴちぢぬづぐひづてどへ
プロパティによって、テーブル接頭辞を指定します。
return [// ...
'components' => [// ...
'db' => [// ...
'tablePrefix' => 'tbl_',
],
],
];

そして、あなたのコードの中で、そのテーブル接頭辞を名前に持つテーブルを参照しなければならないときには、いつでも {{%テーブル名}} という構文を使います。 パーセント記号は いあ 接続を構成したときに指定したテーブル接頭辞に自動的に置き換えられます。 例えば、// MySQL では SELECT COUNT(`id`) FROM `tbl_employee` という SQL が実行される$count = Yii::$app->db->createCommand("SELECT COUNT([[id]]) FROM{{%employee}}")->queryScalar();

6.1.4

トランザクションを実行する

一続きになった複数の関連するクエリを実行するときは、データの整合性と一貫性を保証するために、 一連のクエリをトランザクションで囲む必要がある場合があります。 一連のクエリのどの一つが失敗した場合でも、データベースは、何一つクエリが実行されなかったかのような状態
へとロールバックされます。
次のコードはトランザクションの典型的な使用方法を示すものです。
Yii::$app->db->transaction(function($db) {$db->createCommand($sql1)->execute();$db->createCommand($sql2)->execute();// ... その他の SQL 文を実行 ...
});上記のコードは、次のものと等価です。こちらの方が、エラー処理のコードをより細かく制御することが出来ます。
$db = Yii::$app->db;$transaction = $db->beginTransaction();try {〶〮〱〮 データベース・アクセス・オブジェクト〲〸〳$db->createCommand($sql1)->execute();$db->createCommand($sql2)->execute();// ... その他の SQL 文を実行 ...
$transaction->commit();} catch(\Exception $e) {$transaction->rollBack();throw $e;
} catch(\Throwable $e) {$transaction->rollBack();throw $e;}

ぢづでどのごひちのびちっぴどはの〨〩 メソッドを呼ぶことによって、新しいトランザクションが開始されます。 トランザクションは、変数 $transaction に保存された べどどぜつぢぜごひちのびちっぴどはの オブジェクトとして表現されます。 そして、実行されるクエリが try...catch... ブロックで囲まれます。 全てのクエリの実行が成功した場合には、トランザクションをコミットするた
めに っはねねどぴ〨〩 が呼ばれます。 そうでなく、例外がトリガされてキャッチされた場合は、ひはぬぬあちっに〨〩 が呼ばれて、トランザクションの中で失敗したクエリに先行するクエリによって行なわれた変更が、ロールバックされます。 そして、throw $e が、まるでそれをキャッチしなかったかのように、例外を再スローしますので、通常のエラー処理プロセスがその例外の面倒を見ることになります。
補足〺 上記のコードでは、ぐえぐ 〵〮へ と ぐえぐ 〷〮へ との互換性のために、二つのっちぴっと ブロックを持っています。 \Exception は
ぐえぐ 〷〮〰 以降では、\Throwable インタフェイス13 を実装しています。 従って、あなたのアプリケーションが ぐえぐ 〷〮〰 以上しか使わない場合は、\Exception の部分を省略することが出来ます。
分離レベルを指定する
すどど は、トランザクションの 分離レベル14 の設定もサポートしています。デフォルトでは、新しいトランザクションを開始したときは、 デー
タベースシステムによって設定された分離レベルを使用します。デフォ
ルトの分離レベルは、次のようにしてオーバーライドすることが出来ます。
$isolationLevel = \yii\db\Transaction::REPEATABLE_READ;
Yii::$app->db->transaction(function ($db) {https://www.php.net/manual/ja/class.throwable.php
https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%
82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E5%88%86%E9%9B%A2%E3%83%AC%E3%83%99%E3%83%
AB
13
14

〲〸〴

ぃえぁぐごぅげ 〶〮 データベースの取り扱い....
}, $isolationLevel);// あるいは$transaction = Yii::$app->db->beginTransaction($isolationLevel);

すどど は、最もよく使われる分離レベルのために、四つの定数を提供しています。
• べどどぜつぢぜごひちのびちっぴどはの〺〺げぅぁいたさぎぃくききぉごごぅい 〭 最も弱いレベル。ダー
ティー・リード、非再現リード、ファントムが発生しうる。
• べどどぜつぢぜごひちのびちっぴどはの〺〺げぅぁいたぃくききぉごごぅい 〭 ダーティー・リードを回避。
• べどどぜつぢぜごひちのびちっぴどはの〺〺げぅぐぅぁごぁあがぅたげぅぁい 〭 ダーティー・リードと非再現リードを回避。
• べどどぜつぢぜごひちのびちっぴどはの〺〺こぅげぉぁがぉずぁあがぅ 〭 最も強いレベル。上記の問題を全て回避。
分離レベルを指定するためには、上記の定数を使う以外に、あなたが使っている いあきこ によってサポートされている有効な構文の文字列を使うことも出来ます。 例えば、ぐはびぴひづこけが では、"SERIALIZABLE READ ONLY
DEFERRABLE" を使うことが出来ます。
いあきこ によっては、接続全体に対してのみ分離レベルの設定を許容しているものがあることに注意してください。 その場合、すべての後続のトランザクションは、指定しなくても、それと同じ分離レベルで実行されます。 従って、この機能を使用するときは、矛盾する設定を避けるた
めに、全てのトランザクションについて分離レベルを明示的に指定しなければなりません。 このチュートリアルを書いている時点では、この制約の影響を受ける いあきこ は きここけが と こけがどぴづ だけです。
補足〺 こけがどぴづ は、二つの分離レベルしかサポートしていません。すなわち、READ UNCOMMITTED と SERIALIZABLE しか使えません。 他のレベルを使おうとすると、例外が投げられます。
補足〺 ぐはびぴでひづこけが は、トランザクションを開始する前に分離レベルを指定することを許容していません。 すなわち、トランザクションを開始するときに、分離レベルを直接に指定す
ることは出来ません。 この場合、トランザクションを開始した後に べどどぜつぢぜごひちのびちっぴどはの〺〺びづぴぉびはぬちぴどはのがづぶづぬ〨〩 を呼び出す必要があります。
トランザクションを入れ子にする
あなたの いあきこ が こちぶづばはどのぴ をサポートしている場合は、次のように、複数のトランザクションを入れ子にすることが出来ます。
Yii::$app->db->transaction(function ($db) {// 外側のトランザクション〶〮〱〮 データベース・アクセス・オブジェクト

});

〲〸〵

$db->transaction(function ($db) {// 内側のトランザクション
});

あるいは、
$db = Yii::$app->db;$outerTransaction = $db->beginTransaction();try {$db->createCommand($sql1)->execute();$innerTransaction = $db->beginTransaction();try {$db->createCommand($sql2)->execute();$innerTransaction->commit();} catch (\Exception $e) {$innerTransaction->rollBack();throw $e;
} catch(\Throwable $e) {$transaction->rollBack();throw $e;}
$outerTransaction->commit();} catch (\Exception $e) {$outerTransaction->rollBack();throw $e;
} catch(\Throwable $e) {$transaction->rollBack();throw $e;}

6.1.5

レプリケーションと読み書きの分離

多くの いあきこ は、データベースの可用性とサーバのレスポンス・タイムを向上させるために、 データベース・レプリケーション15 をサポートしています。 データベース・レプリケーションによって、データはいわゆ
る マスタ・サーバ から スレーブ・サーバ に複製されます。 データの書
き込みと更新はすべてマスタ・サーバ上で実行されなければなりません
が、データの読み出しはスレーブ・サーバ上でも可能です。
データベース・レプリケーションを活用して読み書きの分離を達成するために、 べどどぜつぢぜぃはののづっぴどはの コンポーネントを下記のように構成することが出来ます。
['class' => 'yii\db\Connection',

https://ja.wikipedia.org/wiki/%E3%83%AC%E3%83%97%E3%83%AA%E3%82%B1%E3%
83%BC%E3%82%B7%E3%83%A7%E3%83%B3#.E3.83.87.E3.83.BC.E3.82.BF.E3.83.99.E3.83.
BC.E3.82.B9
15

〲〸〶

ぃえぁぐごぅげ 〶〮 データベースの取り扱い// マスタの構成'dsn' => 'マスタ・サーバの DSN','username' => 'master','password' => '',// スレーブの共通の構成'slaveConfig' => ['username' => 'slave','password' => '','attributes' => [// 短かめの接続タイムアウトを使う
PDO::ATTR_TIMEOUT => 10,
],
],

]

// スレーブの構成のリスト'slaves' => [['dsn' => 'スレーブ・サーバ 1 の DSN'],['dsn' => 'スレーブ・サーバ 2 の DSN'],['dsn' => 'スレーブ・サーバ 3 の DSN'],['dsn' => 'スレーブ・サーバ 4 の DSN'],],

上記の構成は、一つのマスタと複数のスレーブを指定するものです。 読
み出しのクエリを実行するためには、スレーブの一つが接続されて使用
され、書き込みのクエリを実行するためには、マスタが使われます。 そのような読み書きの分離が、この構成によって、自動的に達成されます。例えば、// 上記の構成を使って Connection のインスタンスを作成する$db = Yii::createObject($config);// スレーブの一つに対してクエリを実行する$rows = Yii::$app->db->createCommand('SELECT * FROM user LIMIT10')->queryAll();// マスタに対してクエリを実行する
Yii::$app->db->createCommand("UPDATE user SET username='demo' WHERE
id=1")->execute();情報〺 べどどぜつぢぜぃはねねちのつ〺〺づへづっふぴづ〨〩 を呼ぶことで実行されるクエリは、書き込みのクエリと見なされ、 べどどぜつぢぜぃはねねちのつ の【ぱふづひべ】 メソッドのうちの一つによって実行されるその他す
べてのクエリは、読み出しクエリと見なされます。 現在アクティブなスレーブ接続は Yii::$app->db->slave によって取得することが出来ます。
Connection コンポーネントは、スレーブ間のロード・バランス調整とフェイルオーバーをサポートしています。 読み出しクエリを最初に実行する〶〮〱〮 データベース・アクセス・オブジェクト〲〸〷

ときに、Connection コンポーネントはランダムにスレーブを選んで接続を試みま・す。 そのスレーブが「死んでいる」ことが分かったときは、他のスレーブを試します。 スレーブが一つも使用できないときは、マスタに接続します。 サーバ・ステータスキャッシュ を構成することによって、「死んでいる」サーバを記憶し、 一定期間 はそのサーバへの接続を再試行しないようにすることが出来ます。
情報〺 上記の構成では、すべてのスレーブに対して 〱〰 秒の接
続タイムアウトが指定されています。 これは、〱〰 秒以内に接続できなければ、そのスレーブは「死んでいる」と見なされることを意味します。 このパラメータは、実際の環境に基づいて調整することが出来ます。
複数のマスタと複数のスレーブという構成にすることも可能です。例えば、['class' => 'yii\db\Connection',// マスタの共通の構成'masterConfig' => ['username' => 'master','password' => '','attributes' => [// 短かめの接続タイムアウトを使う
PDO::ATTR_TIMEOUT => 10,],],// マスタの構成のリスト'masters' => [['dsn' => 'マスタ・サーバ 1 の DSN'],['dsn' => 'マスタ・サーバ 2 の DSN'],],// スレーブの共通の構成'slaveConfig' => ['username' => 'slave','password' => '','attributes' => [// 短かめの接続タイムアウトを使う
PDO::ATTR_TIMEOUT => 10,],],// スレーブの構成のリスト'slaves' => [['dsn' => 'スレーブ・サーバ 1 の DSN'],['dsn' => 'スレーブ・サーバ 2 の DSN'],['dsn' => 'スレーブ・サーバ 3 の DSN'],['dsn' => 'スレーブ・サーバ 4 の DSN'],

〲〸〸

]

ぃえぁぐごぅげ 〶〮 データベースの取り扱い],

上記の構成は、二つのマ スタと四つのス レーブを指定してい ます。
Connection コンポーネントは、スレーブ間での場合と同じように、マス

タ間でのロード・バランス調整とフェイルオーバーをサポートしています。 一つ違うのは、マスタが一つも利用できないときは例外が投げられる、という点です。
補足〺 ねちびぴづひび プロパティを使って一つまたは複数のマスタを構成する場合は、 データベース接続を定義する Connection オ
ブジェクト自体の他のプロパティ 〨例えば、dsn、username、password〩は全て無視されます。
デフォルトでは、トランザクションはマスタ接続を使用します。 そして、トランザクション内では、全ての いあ 操作はマスタ接続を使用します。例えば、$db = Yii::$app->db;// トランザクションはマスタ接続で開始される$transaction = $db->beginTransaction();try {// クエリは両方ともマスタに対して実行される$rows = $db->createCommand('SELECT * FROM user LIMIT 10')->queryAll();$db->createCommand("UPDATE user SET username='demo' WHERE
id=1")->execute();$transaction->commit();} catch(\Exception $e) {$transaction->rollBack();throw $e;
} catch(\Throwable $e) {$transaction->rollBack();throw $e;}

スレーブ接続を使ってトランザクションを開始したいときは、次のように、明示的にそうする必要があります。
$transaction = Yii::$app->db->slave->beginTransaction();時として、読み出しクエリの実行にマスタ接続を使うことを強制したい
場合があります。 これは、useMaster() メソッドを使うことによって達成できます。
$rows = Yii::$app->db->useMaster(function ($db) {return $db->createCommand('SELECT * FROM user LIMIT 10')->queryAll();});

直接に Yii::$app->db->enableSlaves を false に設定して、全てのクエリをマスタ接続に向けることも出来ます。

〶〮〱〮 データベース・アクセス・オブジェクト

6.1.6

〲〸〹

データベース・スキーマを扱う

すどど いぁく は、新しいテーブルを作ったり、テーブルからカラムを削除したりなど、データベース・スキーマを操作することを可能にする一揃いのメソッドを提供しています。 以下がそのソッドのリストです。
• っひづちぴづごちぢぬづ〨〩〺 テーブルを作成する• ひづのちねづごちぢぬづ〨〩〺 テーブルの名前を変更する• つひはばごちぢぬづ〨〩〺 テーブルを削除する• ぴひふのっちぴづごちぢぬづ〨〩〺 テーブルの全ての行を削除する• ちつつぃはぬふねの〨〩〺 カラムを追加する• ひづのちねづぃはぬふねの〨〩〺 カラムの名前を変更する• つひはばぃはぬふねの〨〩〺 カラムを削除する• ちぬぴづひぃはぬふねの〨〩〺 カラムを変更する• ちつつぐひどねちひべかづべ〨〩〺 プライマリ・キーを追加する• つひはばぐひどねちひべかづべ〨〩〺 プライマリ・キーを削除する• ちつつうはひづどでのかづべ〨〩〺 外部キーを追加する• つひはばうはひづどでのかづべ〨〩〺 外部キーを削除する• っひづちぴづぉのつづへ〨〩〺 インデックスを作成する• つひはばぉのつづへ〨〩〺 インデックスを削除する
これらのメソッドは次のようにして使うことが出来ます。
// CREATE TABLE
Yii::$app->db->createCommand()->createTable('post', ['id' => 'pk','title' => 'string','text' => 'text',]);

上記の配列は、生成されるカラムの名前と型を記述しています。 すどど は
カラムの型のために一連の抽象データ型を提供しているため、データ
ベースの違いを意識せずにスキーマを定義することが可能です。 これらの抽象データ型は、テーブルが作成されるデータベースによって異なる
いあきこ 固有の型定義に変換されます。 詳しい情報は っひづちぴづごちぢぬづ〨〩 メ
ソッドの ぁぐぉ ドキュメントを参照してください。
データベースのスキーマを変更するだけでなく、テーブルに関する定義情報を いあ 接続の でづぴごちぢぬづこっとづねち〨〩 メソッドによって取得することも出来ます。 例えば、
$table = Yii::$app->db->getTableSchema('post');

このメソッドは、テーブルのカラム、プライマリ・キー、外部キーなどの情報を含む べどどぜつぢぜごちぢぬづこっとづねち オブジェクトを返します。 これらの情報は、主として クエリ・ビルダ や アクティブ・レコード によって利用されて、 特定のデータベースに依存しないコードを書くことを助けてくれています。

〲〹〰

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

クエリ・ビルダ

6.2

データベース・アクセス・オブジェクト の上に構築されているクエリ・
ビルダは、こけが クエリをプログラム的に、 かつ、いあきこ の違いを意識せずに作成することを可能にしてくれます。 クエリ・ビルダを使うと、生の こけが 文を書くことに比べて、より読みやすい こけが 関連のコードを書き、より安全な こけが 文を生成することが容易になります。
通常、クエリ・ビルダの使用は、二つのステップから成ります。
〱〮 こぅがぅぃご こけが 文のさまざまな部分 〨例えば、SELECT、FROM〩 を表現する べどどぜつぢぜけふづひべ オブジェクトを構築する。
〲〮 べどどぜつぢぜけふづひべ のクエリ・メソッド 〨例えば all()〩 を実行して、デー
タベースからデータを取得する。
次のコードは、クエリ・ビルダを使用する典型的な方法を示すものです。
$rows = (new \yii\db\Query())->select(['id', 'email'])->from('user')->where(['last_name' => 'Smith'])->limit(10)->all();

上 記 の コ ー ド は 、 次 の こけが ク エ リ を 生 成 し て 実 行 し ま す 。 こ こ では、:last_name パラメータは 'Smith' という文字列にバインドされています。
SELECT `id`, `email`
FROM `user`
WHERE `last_name` = :last_name
LIMIT 10

情報〺 通常は、べどどぜつぢぜけふづひべあふどぬつづひ ではなく、主として べどど
ぜつぢぜけふづひべ を使用します。 前者は、クエリ・メソッドの一つを呼ぶときに、後者によって黙示的に起動されます。 べどどぜつぢ
ぜけふづひべあふどぬつづひ は、いあきこ に依存しない べどどぜつぢぜけふづひべ オブ
ジェクトから、いあきこ に依存する こけが 文を生成する 〨例えば、テーブルやカラムの名前を いあきこ ごとに違う方法で引用
符で囲む〩 役割を負っているクラスです。

6.2.1

クエリを構築する

べどどぜつぢぜけふづひべ オブジェクトを構築するために、さまざまなクエリ構築メ
ソッドを呼んで、こけが クエリのさまざまな部分を定義します。 これらのメソッドの名前は、こけが 文の対応する部分に使われる こけが キーワードに〶〮〲〮 クエリ・ビルダ〲〹〱

似たものになっています。 例えば、こけが クエリの FROM の部分を定義する
ためには、from() メソッドを呼び出します。 クエリ構築メソッドは、すべて、クエリ・オブジェクトそのものを返しますので、複数の呼び出しをチェーンしてまとめることが出来ます。
以下で、それぞれのクエリ構築メソッドの使用方法を説明しましょう。
びづぬづっぴ〨〩びづぬづっぴ〨〩 メソッドは、こけが 文の SELECT 句を定義します。 選択される
カラムは、次のように、配列または文字列として指定することが出来ます。 選択されるカラムの名前は、クエリ・オブジェクトから こけが 文が生成されるときに、自動的に引用符で囲まれます。
$query->select(['id', 'email']);// 次と等価$query->select('id, email');

選択されるカラム名は、生の こけが クエリを書くときにするように、テー
ブル接頭辞 および〯または カラムのエイリアスを含むことが出来ます。
例えば、$query->select(['user.id AS user_id', 'email']);// 次と等価$query->select('user.id AS user_id, email');

カラムを指定するのに配列形式を使っている場合は、配列のキーを使ってカラムのエイリアスを指定することも出来ます。 例えば、上記のコードは次のように書くことが出来ます。
$query->select(['user_id' => 'user.id', 'email']);

クエリを構築するときに びづぬづっぴ〨〩 メソッドを呼ばなかった場合は、* がセレクトされます。 すなわち、全て のカラムが選択されることになります。
カラム名に加えて、いあ 式をセレクトすることも出来ます。 カンマを含む いあ 式をセレクトする場合は、自動的に引用符で囲む機能が誤動作しないように、配列形式を使わなければなりません。例えば、$query->select(["CONCAT(first_name, ' ', last_name) AS full_name",'email']);

生の こけが が使われる場所ではどこでもそうですが、セレクトに いあ 式を書く場合には、テーブルやカラムの名前を表すために 特定のデータベースに依存しない引用符の構文 を使うことが出来ます。

〲〹〲

ぃえぁぐごぅげ 〶〮 データベースの取り扱いバージョン 〲〮〰〮〱 以降では、サブ・クエリもセレクトすることが出来ます。 各サブ・クエリは、べどどぜつぢぜけふづひべ オブジェクトの形で指定しなけ
ればなりません。例えば、$subQuery = (new Query())->select('COUNT(*)')->from('user');// SELECT `id`, (SELECT COUNT(*) FROM `user`) AS `count` FROM `post`$query = (new Query())->select(['id', 'count' => $subQuery])->from('post');

重複行を除外してセレクトするためには、次のように、つどびぴどのっぴ〨〩 を呼ぶことが出来ます。
// SELECT DISTINCT `user_id` ...
$query->select('user_id')->distinct();

追加のカラムをセレクトするためには ちつつこづぬづっぴ〨〩 を呼ぶことが出来ます。例えば、$query->select(['id', 'username'])->addSelect(['email']);てひはね〨〩てひはね〨〩 メソッドは、こけが 文の FROM 句を定義します。例えば、// SELECT * FROM `user`$query->from('user');

セレクトの対象になる 〨一つまたは複数の〩 テーブルは、文字列または配列として指定することが出来ます。 テーブル名は、生の こけが 文を書くときにするように、スキーマ接頭辞 および〯または テーブル・エイリアスを含むことが出来ます。例えば、$query->from(['public.user u', 'public.post p']);// 次と等価$query->from('public.user u, public.post p');配列形式を使う場合は、次のように、配列のキーを使ってテーブル・エ
イリアスを指定することも出来ます。
$query->from(['u' => 'public.user', 'p' => 'public.post']);

テーブル名の他に、べどどぜつぢぜけふづひべ オブジェクトの形で指定することによって、サブ・クエリをセレクトの対象とすることも出来ます。 例えば、$subQuery = (new Query())->select('id')->from('user')->where('status=1');// SELECT * FROM (SELECT `id` FROM `user` WHERE status=1) u$query->from(['u' => $subQuery]);〶〮〲〮 クエリ・ビルダ〲〹〳

プレフィックス また、デフォルトの ぴちぢぬづぐひづてどへ を適用することも出来ます。 実装の仕方は 【データベース・アクセス・オブジェクト】 ガイドの 【テーブル名を引用符で囲む】 のセクション にあります。
ぷとづひづ〨〩
ぷとづひづ〨〩 メソッドは、こけが クエリの WHERE 句を定義します。 WHERE の条
件を指定するために、次の〴つの形式から一つを選んで使うことが出来ます。
• 文字列形式、例えば、'status=1'• ハッシュ形式、例えば、['status' => 1, 'type' => 2]• 演算子形式、例えば、['like', 'name', 'test']• オブジェクト形式、例えば、new LikeCondition('name', 'LIKE', 'test')
文字列形式 文字列形式は、非常に単純な条件を定義する場合や、いあきこの組み込み関数を使う必要がある場合に最適です。 これは、生の こけが を書いている場合と同じように動作します。例えば、$query->where('status=1');// あるいは、パラメータ・バインディングを使って、動的にパラメータをバインドする$query->where('status=:status', [':status' => $status]);// date フィールドに対して MySQL の YEAR() 関数を使う生の SQL$query->where('YEAR(somedate) = 2015');

次のように、条件式に変数を直接に埋め込んではいけません。 特に、変数の値がユーザの入力に由来する場合、あなたのアプリケーションをこけが インジェクション攻撃にさらすことになりますので、してはいけません。
// 危険! $status が整数であることが絶対に確実でなければ、してはいけない。
$query->where("status=$status");
パラメータ・バインディング を使う場合は、ばちひちねび〨〩 または ちつつぐちひちねび〨〩 を使って、パラメータの指定を分離することが出来ます。
$query->where('status=:status')->addParams([':status' => $status]);

生の こけが が使われる場所ではどこでもそうですが、文字列形式で条件を書く場合には、テーブルやカラムの名前を表すために 特定のデータベースに依存しない引用符の構文 を使うことが出来ます。

〲〹〴

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

ハッシュ形式 値が等しいことを要求する単純な条件をいくつか AND で結合する場合は、ハッシュ形式を使うのが最適です。 個々の条件を表す
配列の各要素は、キーをカラム名、値をそのカラムが持つべき値とします。 例えば、// ...WHERE (`status` = 10) AND (`type` IS NULL) AND (`id` IN (4, 8, 15))$query->where(['status' => 10,'type' => null,'id' => [4, 8, 15],]);

ご覧のように、クエリ・ビルダは頭が良いので、のふぬぬ や配列である値も、適切に処理します。
次のように、サブ・クエリをハッシュ形式で使うことも出来ます。
$userQuery = (new Query())->select('id')->from('user');// ...WHERE `id` IN (SELECT `id` FROM `user`)$query->where(['id' => $userQuery]);

ハッシュ形式を使う場合、すどど は内部的にパラメータ・バインディングを使用します。 従って、文字列形式 とは対照的に、ここでは手動でパラメータを追加する必要はありません。ただし、すどど はカラム名を決してエスケープしないことに注意して下さい。 従って、ユーザから取得した変数を何ら追加のチェックをすることなくカラム名として渡すと、こけが イ
ンジェクション攻撃に対して脆弱になります。 アプリケーションを安全に保つためには、カラム名として変数を使わないこと、または、変数を許容リストによってフィルターすることが必要です。 カラム名をユーザから取得する必要がある場合は、ガイドの データをフィルタリングするという記事を読んで下さい。 例えば、次のコードは脆弱です。
// 脆弱なコード:$column = $request->get('column');$value = $request->get('value');$query->where([$column => $value]);// $value は安全です。しかし、$column の名前はエンコードされません。

演算子形式 演算子形式を使うと、任意の条件をプログラム的な方法で指定することが出来ます。これは次の形式を取るものです。
[演算子, オペランド1, オペランド2, ...]

ここで、各オペランドは、文字列形式、ハッシュ形式、あるいは、再帰的に演算子形式として指定することが出来ます。 そして、演算子には、次のどれか一つを使うことが出来ます。

〶〮〲〮 クエリ・ビルダ〲〹〵• and〺 複数のオペランドが AND を使って結合されます。 例えば、['and','id=1', 'id=2'] は id=1 AND id=2 を生成します。 オペランドが配列である場合は、ここで説明されている規則に従って文字列に変換されます。 例えば、['and', 'type=1', ['or', 'id=1', 'id=2']] は type=1
AND (id=1 OR id=2) を生成します。 このメソッドは、文字列を引用符で囲ったりエスケープしたりしません。
• or〺 オペランドが OR を使って結合されること以外は and 演算子と同じです。
• not〺 オペランド〱 だけを受け取って NOT() で包みます。例えば、['not','id=1'] は NOT (id=1) を生成します。オペランド〱 は、それ自体も複数の式を表す配列であっても構いません。例えば、['not', ['status'=> 'draft', 'name' => 'example']] は NOT ((status='draft') AND (name='example'))を生成します。
• between〺 オペランド 〱 はカラム名、オペランド 〲 と 〳 はカラムの値が属すべき範囲の開始値と終了値としなければなりません。 例えば、['between', 'id', 1, 10] は id BETWEEN 1 AND 10 を生成します。
値が二つのカラムの値の間にあるという条件 〨例えば、11 BETWEEN
min_id AND max_id〩 を構築する必要がある場合は、 あづぴぷづづのぃはぬふねのびぃはのつどぴどはのを使用しなければなりません。 条件定義のオブジェクト形式について更に学習するためには 条件 〕 オブジェクト形式 のセクションを参照して下さい。
• not between〺 生成される条件において BETWEEN が NOT BETWEEN に置き換えられる以外は、 between と同じです。
• in〺 オペランド 〱 はカラム名または いあ 式でなければなりません。
オペランド 〲 は、配列または Query オブジェクトのどちらかを取ることが出来ます。 オペランド 〲 が配列である場合は、その配列
は、カラムまたは いあ 式が該当すべき値域を表すものとされます。
オペランド 〲 が Query オブジェクトである場合は、サブ・クエリが生成されて、カラムまたは いあ 式の値域として使われます。 例えば、['in', 'id', [1, 2, 3]] は id IN (1, 2, 3) を生成します。 このメソッドは、カラム名を適切に引用符で囲み、値域の値をエスケープします。 in 演算子はまた複合カラムをもサポートしています。
その場合、オペランド 〱 はカラム名の配列とし、オペランド 〲 は配列の配列、または、複合カラムの値域を表す Query オブジェクトでなければなりません。 例えば、['in', ['id', 'name'], [['id' => 1,'name' => 'oy']]] は (id, name) IN ((1, 'oy')) を生成します。
• not in〺 生成される条件において IN が NOT IN に置き換えられる以外
は、in と同じです。
• like〺 オペランド 〱 はカラム名または いあ 式、オペランド 〲 は
そのカラムまたは いあ 式がマッチすべき値を示す 文字列または配列でなければなりません。 例えば、['like', 'name', 'tester'] はname LIKE '%tester%' を生成します。 値域が配列として与えられた
場合は、複数の LIKE 述語が生成されて だぁぎい〧 によって結合されます。 例えば、['like', 'name', ['test', 'sample']] は name LIKE〲〹〶

ぃえぁぐごぅげ 〶〮 データベースの取り扱い'%test%' AND name LIKE '%sample%' を生成します。 さらに、オプションである三番目のオペランドによって、値の中の特殊文字をエスケープする方法を指定することも出来ます。 このオペランド 〳 は、特殊文字とそのエスケープ結果のマッピングを示す配列でなければなりません。 このオペランドが提供されない場合は、デフォルトのエスケープ・マッピングが使用されます。 false または空の配列を使って、値が既にエスケープ済みであり、それ以上エスケープを適用すべきでないことを示すことが出来ます。 エスケープマッピングを使用する場合 〨または第三のオペランドが与えられない場合〩 は、値が自動的に一対のパーセント記号によって囲まれることに注意してください。
補足〺 ぐはびぴでひづこけが を使っている場合は、like の代りに、大文字と小文字を区別しない比較のための ilike16 を使うことも出来ます。
• or like〺 オペランド 〲 が配列である場合に LIKE 述語が OR によって結合される以外は、 like 演算子と同じです。
• not like〺 生成される条件において LIKE が NOT LIKE に置き換えられる以外は、 like 演算子と同じです。
• or not like〺 NOT LIKE 述語が OR によって結合される以外は、 not like
演算子と同じです。
• exists〺 要求される一つだけのオペランドは、サブ・クエリを表す べどどぜつぢぜけふづひべ のインスタンスでなければなりません。 これは
EXISTS (sub-query) という式を構築します。
• not exists〺 exists 演算子と同じで、NOT EXISTS (sub-query) という式を構築します。
• >、<=、その他、二つのオペランドを取る有効な いあ 演算子全て〺 最
初のオペランドはカラム名、第二のオペランドは値でなければなりません。 例えば、['>', 'age', 10] は age>10 を生成します。
演算子形式を使う場合、すどど は値に対して内部的にパラメータ・バイン
ディングを使用します。 従って、文字列形式 とは対照的に、ここでは手動でパラメータを追加する必要はありません。 ただし、すどど はカラム名を決してエスケープしないことに注意して下さい。従って、変数をカラム名として渡すと、アプリケーションは こけが インジェクション攻撃に対して脆弱になります。 アプリケーションを安全に保つためには、カラム
名として変数を使わないこと、または、変数を許容リストによってフィルターすることが必要です。 カラム名をユーザから取得する必要がある
場合は、ガイドの データをフィルタリングする という記事を読んで下さい。 例えば、次のコードは脆弱です。
// 脆弱なコード:$column = $request->get('column');$value = $request->get('value');16
https://www.postgresql.org/docs/8.3/functions-matching.html#
FUNCTIONS-LIKE〶〮〲〮 クエリ・ビルダ〲〹〷$query->where([$column => $value]);// $value は安全です。しかし、$column の名前はエンコードされません。

オブジェクト形式 オブジェクト形式は 〲〮〰〮〱〴 から利用可能な、条件を定義するための最も強力でもあり、最も複雑でもある方法です。 クエ
リ・ビルダの上にあなた自身の抽象レイヤを構築したいときや、または独自の複雑な条件を実装したいときは、 この形式を採用する必要があります。
条件クラスのインスタンスはイミュータブルです。 条件クラスのイン
スタンスは条件データを保持し、条件ビルダにゲッターを提供することを唯一の目的とします。 そして、条件ビルダが、条件クラスのインスタンスに保存されたデータを こけが の式に変換するロジックを持つクラスです。
内部的には、上述の三つの形式は、生の こけが を構築するに先立って、暗黙のうちにオブジェクト形式に変換されます。 従って、複数の形
式を単一の条件に結合することが可能です。
$query->andWhere(new OrCondition([
new InCondition('type', 'in', $types),['like', 'name', '%good%'],'disabled=false']))

演算子形式からオブジェクト形式への変換は、 演算子の名前とそれを表すクラス名を対応づける けふづひべあふどぬつづひ〺〺っはのつどぴどはのぃぬちびびづび プロパティ
に従って行われます。
• AND〬 OR 〭〾 yii\db\conditions\ConjunctionCondition• NOT 〭〾 yii\db\conditions\NotCondition• IN〬 NOT IN 〭〾 yii\db\conditions\InCondition• BETWEEN〬 NOT BETWEEN 〭〾 yii\db\conditions\BetweenCondition
等々。
オブジェクト形式を使うことによって、あなた独自の条件を作成した
り、デフォルトの条件が作成される方法を変更したりすることが可能になります。 詳細は 特製の条件や式を追加する のセクションを参照して下さい。
条件を追加する ちのつしとづひづ〨〩 または はひしとづひづ〨〩 を使って、既存の条件に別の条件を追加することが出来ます。 これらのメソッドを複数回呼んで、複数の条件を別々に追加することが出来ます。 例えば、
$status = 10;$search = 'yii';$query->where(['status' => $status]);if (!empty($search)) {

〲〹〸

}

ぃえぁぐごぅげ 〶〮 データベースの取り扱い$query->andWhere(['like', 'title', $search]);$search が空でない場合は次の WHERE 条件 が生成されます。
WHERE (`status` = 10) AND (`title` LIKE '%yii%')

フィルタ条件 ユーザの入力に基づいて WHERE の条件を構築する場合、
普通は、空の入力値は無視したいものです。 例えば、ユーザ名とメー
ル・アドレスによる検索が可能な検索フォームにおいては、 ユーザがふびづひのちねづ〯づねちどぬ のインプット・フィールドに何も入力しなかった場合
は、ふびづひのちねづ〯づねちどぬ の条件を無視したいでしょう。 てどぬぴづひしとづひづ〨〩 メ
ソッドを使うことによって、この目的を達することが出来ます。
// $username と $email はユーザの入力による$query->filterWhere(['username' => $username,'email' => $email,]);てどぬぴづひしとづひづ〨〩 と ぷとづひづ〨〩 の唯一の違いは、 前者は ハッシュ形式 の条件において提供された空の値を無視する、という点です。 従って、$email
が空で $sername がそうではない場合は、上記のコードは、結果として
WHERE username=:username という こけが 条件になります。
情報〺 値が空であると見なされるのは、null、空の配列、空の文字列、または空白のみを含む文字列である場合です。
ちのつしとづひづ〨〩 または はひしとづひづ〨〩 と同じように、 ちのつうどぬぴづひしとづひづ〨〩 またははひうどぬぴづひしとづひづ〨〩 を使って、 既存の条件に別のフィルタ条件を追加することも出来ます。
さらに加えて、値の方に含まれている比較演算子を適切に判断してくれる べどどぜつぢぜけふづひべ〺〺ちのつうどぬぴづひぃはねばちひづ〨〩 があります。
$query->andFilterCompare('name', 'John Doe');$query->andFilterCompare('rating', '>9');$query->andFilterCompare('value', '<=100');

演算子を明示的に指定することも可能です。
$query->andFilterCompare('name', 'Doe', 'like');

すどど 〲〮〰〮〱〱 以降には、HAVING の条件のためにも、同様のメソッドがあります。
• てどぬぴづひえちぶどので〨〩• ちのつうどぬぴづひえちぶどので〨〩• はひうどぬぴづひえちぶどので〨〩〶〮〲〮 クエリ・ビルダ〲〹〹

はひつづひあべ〨〩はひつづひあべ〨〩 メソッドは こけが クエリの ORDER BY 句を指定します。例えば、// ... ORDER BY `id` ASC, `name` DESC
$query->orderBy(['id' => SORT_ASC,'name' => SORT_DESC,]);

上記のコードにおいて、配列のキーはカラム名であり、配列の値は並べ替えの方向です。 ぐえぐ の定数 SORT_ASC は昇順、SORT_DESC は降順を指定するものです。
ORDER BY が単純なカラム名だけを含む場合は、生の こけが 文を書くときにするように、文字列を使って指定することが出来ます。 例えば、
$query->orderBy('id ASC, name DESC');補足〺 ORDER BY が何らかの いあ 式を含む場合は、配列形式を使わなければなりません。
ちつつくひつづひあべ〨〩 を呼んで、だくげいぅげ あす〧 句にカラムを追加することが出来ます。 例えば、$query->orderBy('id ASC')->addOrderBy('name DESC');

でひはふばあべ〨〩
でひはふばあべ〨〩 メソッドは こけが クエリの GROUP BY 句を指定します。例えば、// ... GROUP BY `id`, `status`$query->groupBy(['id', 'status']);GROUP BY が単純なカラム名だけを含む場合は、生の こけが 文を書くときにするように、文字列を使って指定することが出来ます。 例えば、

$query->groupBy('id, status');補足〺 GROUP BY が何らかの いあ 式を含む場合は、配列形式を使わなければなりません。
ちつつぇひはふばあべ〨〩 を呼んで、GROUP BY 句にカラムを追加することが出来ます。 例えば、$query->groupBy(['id', 'status'])->addGroupBy('age');〳〰〰

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

とちぶどので〨〩
とちぶどので〨〩 メソッドは こけが クエリの HAVING 句を指定します。 このメソッドが取る条件は、ぷとづひづ〨〩 と同じ方法で指定することが出来ます。例えば、// ... HAVING `status` = 1$query->having(['status' => 1]);

条件を指定する方法の詳細については、ぷとづひづ〨〩 のドキュメントを参照してください。
ちのつえちぶどので〨〩 または はひえちぶどので〨〩 を呼んで、HAVING 句に条件を追加することが出来ます。 例えば、// ... HAVING (`status` = 1) AND (`age` > 30)$query->having(['status' => 1])->andHaving(['>', 'age', 30]);

ぬどねどぴ〨〩 と はててびづぴ〨〩
ぬどねどぴ〨〩 と はててびづぴ〨〩 のメソッドは、こけが クエリの LIMIT 句と OFFSET 句を指定します。 例えば、// ... LIMIT 10 OFFSET 20$query->limit(10)->offset(20);無効な上限やオフセット 〨例えば、負の数〩 を指定した場合は、無視されます。
情報〺 LIMIT と OFFSET をサポートしていない いあきこ 〨例えば
きここけが〩 に対しては、 クエリ・ビルダが LIMIT〯OFFSET の振る舞いをエミュレートする こけが 文を生成します。
なはどの〨〩
なはどの〨〩 メソッドは こけが クエリの JOIN 句を指定します。例えば、// ... LEFT JOIN `post` ON `post`.`user_id` = `user`.`id`$query->join('LEFT JOIN', 'post', 'post.user_id = user.id');

なはどの〨〩 メソッドは、四つのパラメータを取ります。
• $type〺 結合のタイプ、例えば、'INNER JOIN'、'LEFT JOIN'。
• $table〺 結合されるテーブルの名前。
• $on〺 オプション。結合条件、すなわち、ON 句。 条件の指定方法の詳細については、ぷとづひづ〨〩 を参照してください。 カラムに基づく条件を指定する場合は、配列記法は使えないことに注意してください。 例えば、['user.id' => 'comment.userId'] は、ふびづひ の どつ が'comment.userId' という文字列でなければならない、という条件に帰結します。 配列記法ではなく文字列記法を使って、'user.id =comment.userId' という条件を指定しなければなりません。

〶〮〲〮 クエリ・ビルダ〳〰〱• $params〺 オプション。結合条件にバインドされるパラメータ。
INNER JOIN、LEFT JOIN および RIGHT JOIN を指定するためには、それぞれ、次のショートカット・メソッドを使うことが出来ます。
• どののづひおはどの〨〩• ぬづてぴおはどの〨〩• ひどでとぴおはどの〨〩
例えば、$query->leftJoin('post', 'post.user_id = user.id');

複数のテーブルを結合するためには、テーブルごとに一回ずつ、上記の結合メソッドを複数回呼び出します。
テーブルを結合することに加えて、サブ・クエリを結合することも出来ます。 そうするためには、結合されるべきサブ・クエリを べどどぜつぢ
ぜけふづひべ オブジェクトとして指定します。例えば、$subQuery = (new \yii\db\Query())->from('post');$query->leftJoin(['u' => $subQuery], 'u.id = author_id');

この場合、サブ・クエリを配列に入れて、配列のキーを使ってエイリア
スを指定しなければなりません。
ふのどはの〨〩
ふのどはの〨〩 メソッドは こけが クエリの UNION 句を指定します。例えば、$query1 = (new \yii\db\Query())->select("id, category_id AS type, name")->from('post')->limit(10);$query2 = (new \yii\db\Query())->select('id, type, name')->from('user')->limit(10);$query1->union($query2);

ふのどはの〨〩 を複数回呼んで、UNION 句をさらに追加することが出来ます。
ぷどぴとけふづひべ〨〩
ぷどぴとけふづひべ〨〩 メソッドは こけが クエリの WITH プレフィックスを指定するものです。サブクエリの代りに WITH を使うと読みやすさを向上させ、ユニークな機能〨再帰 ぃごぅ〩を利用することが出来ます。詳細は ねはつづひの〭びぱぬ17 を参照して下さい。例えば、次のクエリは admin の持つ権限をその子も含めて全て再帰的に取得します。
17https://modern-sql.com/feature/with〳〰〲

ぃえぁぐごぅげ 〶〮 データベースの取り扱い$initialQuery = (new \yii\db\Query())->select(['parent', 'child'])->from(['aic' => 'auth_item_child'])->where(['parent' => 'admin']);$recursiveQuery = (new \yii\db\Query())->select(['aic.parent', 'aic.child'])->from(['aic' => 'auth_item_child'])->innerJoin('t1', 't1.child = aic.parent');$mainQuery = (new \yii\db\Query())->select(['parent', 'child'])->from('t1')->withQuery($initialQuery->union($recursiveQuery), 't1', true);

ぷどぴとけふづひべ〨〩 を複数回呼び出してさらなる ぃごぅ をメイン・クエリに追加することが出来ます。クエリはアタッチされたのと同じ順序でプリペンドされます。クエリのうちの一つが再帰的である場合は ぃごぅ 全体が再帰的になります。

6.2.2

クエリ・メソッド

べどどぜつぢぜけふづひべ は、さまざまな目的のクエリのために、一揃いのメソッドを提供しています。
• ちぬぬ〨〩〺 各行を「名前〭値」のペアの連想配列とする、結果の行の配列を返す。
• はのづ〨〩〺 結果の最初の行を返す。
• っはぬふねの〨〩〺 結果の最初のカラムを返す。
• びっちぬちひ〨〩〺 結果の最初の行の最初のカラムにあるスカラ値を返す。
• づへどびぴび〨〩〺 クエリが結果を含むか否かを示す値を返す。
• っはふのぴ〨〩〺 COUNT クエリの結果を返す。
• その他の集計クエリ、すなわち、びふね〨〤ぱ〩〬 ちぶづひちでづ〨〤ぱ〩〬 ねちへ〨〤ぱ〩〬ねどの〨〤ぱ〩〮 これらのメソッドでは、$q パラメータは必須であり、カラム名または いあ 式とすることが出来る。
例えば、// SELECT `id`, `email` FROM `user`$rows = (new \yii\db\Query())->select(['id', 'email'])->from('user')->all();// SELECT * FROM `user` WHERE `username` LIKE `%test%`$row = (new \yii\db\Query())->from('user')->where(['like', 'username', 'test'])->one();

補足〺 はのづ〨〩 メソッドはクエリ結果の最初の行だけを返します。このメソッドは LIMIT 1 を生成された こけが 文に追加し〶〮〲〮 クエリ・ビルダ〳〰〳

ません。このことは、クエリが一つまたは少数の行しか返さないことが判っている場合 〨例えば、何らかのプライマリ・キーでクエリを発行する場合〩 は問題になりませんし、むしろ好ましいことです。 しかし、クエリ結果が多数のデータ行になる可能性がある場合は、パフォーマンスを向上させる
ために、明示的に limit(1) を呼ぶべきです。例えば、 (new\yii\db\Query())->from('user')->limit(1)->one()

上記のメソッドの全ては、オプションで、いあ クエリの実行に使用されるべき いあ 接続 を表す $db パラメータを取ることが出来ます。 このパ
ラメータを省略した場合は、いあ 接続として db アプリケーション・コン
ポーネント が使用されます。 次に っはふのぴ〨〩 クエリ・メソッドを使う例をもう一つ挙げます。
// 実行される SQL: SELECT COUNT(*) FROM `user` WHERE `last_name`=:last_name$count = (new \yii\db\Query())->from('user')->where(['last_name' => 'Smith'])->count();

あなたが べどどぜつぢぜけふづひべ のクエリ・メソッドを呼び出すと、実際には、内部的に次の仕事がなされます。
• べどどぜつぢぜけふづひべあふどぬつづひ を呼んで、べどどぜつぢぜけふづひべ の現在の構成に基づいた こけが 文を生成する。
• 生成された こけが 文で べどどぜつぢぜぃはねねちのつ オブジェクトを作成する。
• べどどぜつぢぜぃはねねちのつ のクエリ・メソッド 〨例えば ぱふづひべぁぬぬ〨〩〩 を呼ん
で、こけが 文を実行し、データを取得する。
場合によっては、べどどぜつぢぜけふづひべ オブジェクトから構築された こけが 文を調べたり使ったりしたいことがあるでしょう。 次のコードを使って、その目的を達することが出来ます。
$command = (new \yii\db\Query())->select(['id', 'email'])->from('user')->where(['last_name' => 'Smith'])->limit(10)->createCommand();// SQL 文を表示する
echo $command->sql;// バインドされるパラメータを表示する
print_r($command->params);// クエリ結果の全ての行を返す$rows = $command->queryAll();

6.2.3

クエリ結果をインデックスする

ちぬぬ〨〩 を呼ぶと、結果の行は連続した整数でインデックスされた配列で返されます。 場合によっては、違う方法でインデックスしたいことがあ〳〰〴

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

るでしょう。 例えば、特定のカラムの値や、何らかの式の値によってインデックスするなどです。 この目的は、ちぬぬ〨〩 の前に どのつづへあべ〨〩 を呼ぶ
ことによって達成することが出来ます。例えば、// [100 => ['id' => 100, 'username' => '...', ...], 101 => [...], 103 =>[...], ...] を返す$query = (new \yii\db\Query())->from('user')->limit(10)->indexBy('id')->all();

インデックス付けが働くためには、どのつづへあべ〨〩 メソッドに渡されるカラム名が結果セットに存在する必要があります。 そのことを保証するのは開発者の責任です。
式の値によってインデックスするためには、どのつづへあべ〨〩 メソッドに無名関数を渡します。
$query = (new \yii\db\Query())->from('user')->indexBy(function ($row) {return $row['id'] . $row['username'];})->all();

この無名関数は、現在の行データを含む $row というパラメータを取り、現在の行のインデックス値として使われるスカラ値を返さなくてはなりません。
補足〺 でひはふばあべ〨〩 や はひつづひあべ〨〩 のようなクエリ・メソッドがこけが に変換されてクエリの一部となるのとは対照的に、このメソッドはデータベースからデータが取得された後で動作します。 このことは、クエリの こぅがぅぃご に含まれるカラム名だけを使うことが出来る、ということを意味します。 また、
テーブル・プレフィックスを付けてカラムを選択した場合、
例えば customer.id を選択した場合は、 リザルトセットのカラ
ム名は id しか含みませんので、テーブルプレフィックス無し
で ->indexBy('id') と呼ぶ必要があります。

6.2.4

バッチ・クエリ

大量のデータを扱う場合は、べどどぜつぢぜけふづひべ〺〺ちぬぬ〨〩 のようなメソッドは適していません。 なぜなら、それらのメソッドは、クエリの結果全てをクライアントのメモリに読み込むことを必要とするためです。 この問題を解決するために、すどど はバッチ・クエリのサポートを提供しています。
クエリ結果はサーバに保持し、 クライアントはカーソルを利用して〱回に〱バッチずつ結果セットを反復取得するのです。

〶〮〲〮 クエリ・ビルダ〳〰〵

警告〺 きべこけが のバッチ・クエリの実装には既知の制約と回避策があります。下記を参照して下さい。
バッチ・クエリは次のようにして使うことが出来ます。
use yii\db\Query;$query = (new Query())->from('user')->orderBy('id');foreach ($query->batch() as $users) {// $users は user テーブルから取得した 100 以下の行の配列}// または、一行ずつ反復する場合はforeach ($query->each() as $user) {// データはサーバから 100 行のバッチで取得される// しかし $user は user テーブルの一つの行を表す}

べどどぜつぢぜけふづひべ〺〺ぢちぴっと〨〩 メソッドと べどどぜつぢぜけふづひべ〺〺づちっと〨〩 メソッドは
べどどぜつぢぜあちぴっとけふづひべげづびふぬぴ オブジェクトを返します。このオブジェクト
は Iterator インタフェイスを実装しており、従って、foreach 構文の中で使うことが出来ます。 初回の反復の際に、データベースに対する こけがクエリが作成されます。データは、その後、反復のたびにバッチ・モー
ドで取得されます。 デフォルトでは、バッチ・サイズは 〱〰〰 であり、各バッチにおいて 〱〰〰 行のデータが取得されます。 バッチ・サイズ
は、batch() または each() メソッドに最初のパラメータを渡すことによって変更することが出来ます。
べどどぜつぢぜけふづひべ〺〺ちぬぬ〨〩 とは対照的に、バッチ・クエリは一度に 〱〰〰 行のデータしかメモリに読み込みません。
べどどぜつぢぜけふづひべ〺〺どのつづへあべ〨〩 によって、いずれかのカラムでクエリ結果
をインデックスするように指定している場合でも、 バッチ・クエリは正
しいインデックスを保持します。
例えば、$query = (new \yii\db\Query())->from('user')->indexBy('username');foreach ($query->batch() as $users) {// $users は "username" カラムでインデックスされている}
foreach ($query->each() as $username => $user) {// ...
}

〳〰〶

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

きべこけが におけるバッチ・クエリの制約 きべこけが のバッチ・クエリの実装は ぐいく ドライバのライブラリに依存しています。デフォルトでは、きべこけが のクエリは バッファ・モード18 で実行されます。 このことが、カーソルを使ってデータを取得する目的を挫折させます。というのは、バッファ・モードでは、 ドライバによって結果セット全体がクライアン
トのメモリに読み込まれることを防止できないからです。
補足〺 libmysqlclient が使われている場合 〨ぐえぐ〵 ではそれが普通ですが〩 は、 結果セットに使用されたメモリは ぐえぐ のメモリ使用量としてカウントされません。そのため、一見、
バッチ・クエリが正しく動作するように見えますが、 実際には、データ・セット全体がクライアントのメモリに読み込
まれて、クライアントのメモリを使い果たす可能性があります。
バッファ・モードを無効化してクライアントのメモリ要求量を削減するためには、ぐいく 接続のプロパティ PDO::MYSQL_ATTR_USE_BUFFERED_QUERY を
false に設定しなければなりません。しかし、そうすると、 データ・セッ
ト全体を取得するまでは、同じ接続を通じては別のクエリを実行できな
くなります。これによって ActiveRecord が必要に応じてテーブル・スキー
マを取得するためのクエリを実行できなくなる可能性があります。 これが問題にならない場合 〨テーブル・スキーマが既にキャッシュされている
場合〩 は、元の接続を非バッファ・モードに切り替えて、 バッチ・クエ
リを実行した後に元に戻すということが可能です。
Yii::$app->db->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,
false);// バッチ・クエリを実行
Yii::$app->db->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);補足〺 きべぉこぁき の場合は、バッチ・クエリが継続している
間、テーブルがロックされて、 他の接続からの書き込みアクセスが遅延または拒絶されることがあります。非バッファ・
モードのクエリを使う場合は、 カーソルを開いている時間を可能な限り短くするように努めて下さい。
スキーマがキャッシュされていない場合、またはバッチ・クエリを処理している間に他のクエリを走らせる必要がある場合は、 独立した非バッ
ファ・モードのデータベース接続を作成することが出来ます。
$unbufferedDb = new \yii\db\Connection(['dsn' => Yii::$app->db->dsn,'username' => Yii::$app->db->username,18

https://www.php.net/manual/ja/mysqlinfo.concepts.buffering.php〶〮〲〮 クエリ・ビルダ〳〰〷'password' => Yii::$app->db->password,'charset' => Yii::$app->db->charset,]);$unbufferedDb->open();$unbufferedDb->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,
false);$unbufferedDb が PDO::MYSQL_ATTR_USE_BUFFERED_QUERY が false であること以外

は、 元のバッファ・モードの $db と同じ ぐいく 属性を持つことを保証したい場合は、 $db のディープ・コピー19 をしてから、手動で てちぬびづ に設定することを考慮して下さい。
そして、クエリは普通に作成します。新しい接続を使ってバッチ・ク
エリを走らせ、結果をバッチで取得、 または一つずつ取得します。
// データを 1000 のバッチで取得
foreach ($query->batch(1000, $unbufferedDb) as $users) {// ...
}// データは 1000 のバッチでサーバから取得されるが、一つずつ反復処理される
foreach ($query->each(1000, $unbufferedDb) as $user) {// ...
}

結果セットが全て取得されて接続が必要なくなったら、接続を閉じることが出来ます。
$unbufferedDb->close();補足〺 非バッファ・モードのクエリは ぐえぐ 側でのメモリ消費は少なくなりますが、きべこけが サーバの負荷を増加させ得ます。 特別に巨大なデータに対するアプリの動作については、
あなた自身のコードを設計することが推奨されます。 例えば、整数のキーで範囲を分割して、非バッファ・モードのクエリでループする20 など。
特製の条件や式を追加する
条件 〕 オブジェクト形式 のセクションで触れたように、特製の条件クラスを作成することが可能です。 例として、特定のカラムが一定の値より小さいことをチェックする条件を作ってみましょう。 演算子形式を使え
ば、それは次のようになるでしょう。
['and',
1920

https://github.com/yiisoft/yii2/issues/8420#issuecomment-301423833
https://github.com/yiisoft/yii2/issues/8420#issuecomment-296109257

〳〰〸

]

ぃえぁぐごぅげ 〶〮 データベースの取り扱い'>', 'posts', $minLimit,'>', 'comments', $minLimit,'>', 'reactions', $minLimit,'>', 'subscriptions', $minLimit

このような条件を一度に適用できたら良いですね。一つのクエリの中で複数回使われる場合には、最適化の効果が大きいでしょう。 特製の条件
オブジェクトを作って、それを実証しましょう。
すどど には、条件を表現するクラスを特徴付ける ぃはのつどぴどはのぉのぴづひてちっづがあります。 このインタフェイスは、配列形式から条件を作ることを可能にするための fromArrayDefinition() メソッドを実装することを要求します。 あなたがそれを必要としない場合は、例外を投げるだけのメソッドとして実装しても構いません。
特製の条件クラスを作るのですから、私たちの仕事に最適な ぁぐぉ を構築すれば良いのです。
namespace app\db\conditions;class AllGreaterCondition implements \yii\db\conditions\ConditionInterface{
private $columns;
private $value;/*** @param string[] $columns $value よりも大きくなければならないカラムの配列* @param mixed $value 各カラムと比較する値*/
public function __construct(array $columns, $value){$this->columns = $columns;$this->value = $value;}
public static function fromArrayDefinition($operator, $operands){
throw new InvalidArgumentException('未実装、あとでやる');}}public function getColumns() { return $this->columns; }public function getValue() { return $this->vaule; }これで条件オブジェクトを作ることが出来ます。
$conditon = new AllGreaterCondition(['col1', 'col2'], 42);

しかし QueryBuilder は、このオブジェクトから こけが 条件式を作る方法を知りません。 次に、この条件に対する式ビルダを作成する必要があります。 式ビルダは build() メソッドを提供する べどどぜつぢぜぅへばひづびびどはのあふどぬつづひぉのぴづひてちっづを実装しなければいけません。

〶〮〲〮 クエリ・ビルダ〳〰〹

namespace app\db\conditions;class AllGreaterConditionBuilder implements\yii\db\ExpressionBuilderInterface{
use \yii\db\ExpressionBuilderTrait; // コンストラクタと `queryBuilder` プ
ロパティを含む。
/*** @param ExpressionInterface $condition ビルドすべき条件* @param array $params バインディング・パラメータ* @return AllGreaterCondition*/
public function build(ExpressionInterface $expression, array &$params =[]){$value = $condition->getValue();$conditions = [];foreach ($expression->getColumns() as $column) {$conditions[] = new SimpleCondition($column, '>', $value);}}}

return $this->queryBuilder->buildCondition(newAndCondition($conditions), $params);

後は、単に けふづひべあふどぬつづひ に私たちの新しい条件について知らせるだけです 〕 条件のマッピングを expressionBuilders 配列に追加します。次のように、アプリケーション構成で直接に追加することが出来ます。
'db' => ['class' => 'yii\db\mysql\Connection',// ...
'queryBuilder' => ['expressionBuilders' => ['app\db\conditions\AllGreaterCondition' =>'app\db\conditions\AllGreaterConditionBuilder',
],
],
],

これで、私たちの新しい条件を where() で使用することが出来るようになりました。
$query->andWhere(new AllGreaterCondition(['posts', 'comments', 'reactions','subscriptions'], $minValue));

演算子形式を使って私たちの特製の条件を作成することが出来るようにしたい場合は、 演算子を けふづひべあふどぬつづひ〺〺っはのつどぴどはのぃぬちびびづび の中で宣言しなければなりません。

〳〱〰

ぃえぁぐごぅげ 〶〮 データベースの取り扱い'db' => ['class' => 'yii\db\mysql\Connection',// ...
'queryBuilder' => ['expressionBuilders' => ['app\db\conditions\AllGreaterCondition' =>'app\db\conditions\AllGreaterConditionBuilder',],'conditionClasses' => ['ALL>' => 'app\db\conditions\AllGreaterCondition',
],
],
],

そして、app\db\conditions\AllGreaterCondition の中で AllGreaterCondition::fromArrayDefinition()
メソッドの本当の実装を作成します。
namespace app\db\conditions;class AllGreaterCondition implements \yii\db\conditions\ConditionInterface{// ... 上記の実装を参照}

public static function fromArrayDefinition($operator, $operands){
return new static($operands[0], $operands[1]);}これ以降は、私たちの特製の条件をより短い演算子形式を使って作成することが出来ます。
$query->andWhere(['ALL>', ['posts', 'comments', 'reactions','subscriptions'], $minValue]);

お気付きのことと思いますが、ここには二つの概念があります。ぅへばひづびびどはの〨式〩とぃはのつどぴどはの〨条件〩です。 べどどぜつぢぜぅへばひづびびどはのぉのぴづひてちっづ は、それを構築するために べどどぜつぢぜぅへばひづびびどはのあふどぬつづひぉのぴづひてちっづ を実装した式ビルダクラ
スを必要とするオブジェクトを特徴付けるインタフェイスです。 また
べどどぜつぢぜっはのつどぴどはのぜぃはのつどぴどはのぉのぴづひてちっづ は、ぅへばひづびびどはのぉのぴづひてちっづ を拡張して、 上述されたように配列形式の定義から作成できるオブジェクトに対して使用されるべきものですが、同様にビルダを必要とするものです。
要約すると、• ぅへばひづびびどはの〨式〩 〕 データセットのためのデータ転送オブジェクトであり、最終的に何らかの こけが 文にコンパイルされる。 〨演算子、文字列、配列、おこくぎ、等〩• ぃはのつどぴどはの〨条件〩 〕 ぅへばひづびびどはの〨式〩 のスーパーセットで、一つの こけが条件にコンパイルすることが可能な複数の式 〨またはスカラ値〩の集合。

〶〮〳〮 アクティブ・レコード〳〱〱

ぅへばひづびびどはのぉのぴづひてちっづ を実装する独自のクラスを作成して、 データをこけが 文に変換することの複雑さを隠蔽することが出来ます。 次の記事 では、式について、さらに多くの例を学習します。

6.3

アクティブ・レコード

アクティブ・レコード21 は、データベースに保存されているデータにアクセスするために、 オブジェクト指向のインタフェイスを提供するものです。 アクティブ・レコード・クラスはデータベース・テーブルと関連付けられます。 アクティブ・レコードのインスタンスはそのテーブルの行に対応し、アクティブ・レコードのインスタンスの 属性 がその行にある特定のカラムの値を表現します。 生の こけが 文を書く代りに、アクティ
ブ・レコードの属性にアクセスしたり、アクティブ・レコードのメソッドを呼んだりして、 データベース・テーブルに保存さているデータにアクセスしたり、データを操作したりします。
例えば、Customer が customer テーブルに関連付けられたアクティブ・
レコード・クラスであり、 name が customer テーブルのカラムであると仮定しましょう。 customer テーブルに新しい行を挿入するために次のコードを書くことが出来ます。
$customer = new Customer();$customer->name = 'Qiang';$customer->save();

上記のコードは、きべこけが では、次のような生の こけが 文を使うのと等価なものです。 しかし、生の こけが 文の方は、直感的でなく、間違いも生じ
やすく、また、別の種類のデータベースを使う場合には、互換性の問題も生じ得ます。
$db->createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', [':name' => 'Qiang',])->execute();すどど は次のリレーショナル・データベースに対して、アクティブ・レコー
ドのサポートを提供しています。
• きべこけが 〴〮〱 以降〺 べどどぜつぢぜぁっぴどぶづげづっはひつ による。
• ぐはびぴでひづこけが 〷〮〳 以降〺 べどどぜつぢぜぁっぴどぶづげづっはひつ による。
• こけがどぴづ 〲 および 〳〺 べどどぜつぢぜぁっぴどぶづげづっはひつ による。
• きどっひはびはてぴ こけが こづひぶづひ 〲〰〰〸 以降〺 べどどぜつぢぜぁっぴどぶづげづっはひつ による。
• くひちっぬづ〺 べどどぜつぢぜぁっぴどぶづげづっはひつ による。
• ぃさあげぉい 〹〮〳 以降〺 べどどぜつぢぜぁっぴどぶづげづっはひつ による。〨っふぢひどつ ぐいく 拡
張の バグ22 のために、値を引用符で囲む機能が動作しません。そのため、サーバだけでなくクライアントも ぃさあげぉい 〹〮〳 が必要にな
ります〩
21
22

https://ja.wikipedia.org/wiki/Active_Record
http://jira.cubrid.org/browse/APIS-658

〳〱〲

ぃえぁぐごぅげ 〶〮 データベースの取り扱い• こばとどのへ〺 べどどぜびばとどのへぜぁっぴどぶづげづっはひつ による。yii2-sphinx エクステン
ションが必要。
• ぅぬちびぴどっこづちひっと〺 べどどぜづぬちびぴどっびづちひっとぜぁっぴどぶづげづっはひつ による。yii2-elasticsearch
エクステンションが必要。
これらに加えて、すどど は次の ぎはこけが データベースに対しても、アクティ
ブ・レコードの使用をサポートしています。
• げづつどび 〲〮〶〮〱〲 以降〺 べどどぜひづつどびぜぁっぴどぶづげづっはひつ による。yii2-redis エク
ステンションが必要。
• きはのではいあ 〱〮〳〮〰 以降〺 べどどぜねはのではつぢぜぁっぴどぶづげづっはひつ による。yii2-mongodb
エクステンションが必要。
このチュートリアルでは、主としてリレーショナル・データベースのためのアクティブ・レコードの使用方法を説明します。 しかし、ここで説明するほとんどの内容は ぎはこけが データベースのためのアクティブ・レ
コードにも適用することが出来るものです。

6.3.1

アクティブ・レコード・クラスを宣言する

まずは、べどどぜつぢぜぁっぴどぶづげづっはひつ を拡張してアクティブ・レコード・クラスを宣言するところから始めましょう。
テーブル名を設定する
デフォルトでは、すべてのアクティブ・レコード・クラスはデータベー
ス・テーブルと関連付けられます。 ぴちぢぬづぎちねづ〨〩 メソッドが、クラス名
を べどどぜとづぬばづひびぜぉのてぬづっぴはひ〺〺っちねづぬ〲どつ〨〩 によって変換して、テーブル名を返します。 テーブル名がこの規約に従っていない場合は、このメソッ
ドをオーバライドすることが出来ます。
同時に、デフォルトの ぴちぢぬづぐひづてどへ を適用することも可能です。 例
えば、ぴちぢぬづぐひづてどへ が tbl_ である場合は、Customer は tbl_customer になり、OrderItem はtbl_order_item になります。
テーブル名が {{%TableName}} という形式で与えられた場合は、パーセント記号 % がテーブルプレフィックスに置き換えられます。 例えば、{{%post}} は {{tbl_post}} となります。 テーブル名を囲む二重波括弧
は、テーブル名を囲む引用符号 となります。
次の例では、customer というデータベース・テーブルのための Customerという名前のアクティブ・レコード・クラスを宣言しています。
namespace app\models;
use yii\db\ActiveRecord;class Customer extends ActiveRecord{
const STATUS_INACTIVE = 0;
const STATUS_ACTIVE = 1;〶〮〳〮 アクティブ・レコード

〳〱〳

/**
* @return string このアクティブ・レコード・クラスと関連付けられるテーブルの名前*/
public static function tableName(){
return '{{customer}}';}}

アクティブ・レコードは「モデル」と呼ばれる
アクティブ・レコードのインスタンスは モデル であると見なされます。
この理由により、私たちは通常 app\models 名前空間 〨あるいはモデル・ク
ラスを保管するための他の名前空間〩 の下にアクティブ・レコード・クラ
スを置きます。
べどどぜつぢぜぁっぴどぶづげづっはひつ は べどどぜぢちびづぜきはつづぬ から拡張していますので、属性、検証規則、データのシリアル化など、 モデル が持つ 全ての 機能を継承しています。

6.3.2

データベースに接続する

デフォルトでは、アクティブ・レコードは、db アプリケーション・コン
ポーネント を いあ 接続 として使用して、データベースのデータにアクセ
スしたり操作したりします。 データベース・アクセス・オブジェクト で説明したように、次のようにして、アプリケーションの構成情報ファイルの中で db コンポーネントを構成することが出来ます。
return ['components' => ['db' => ['class' => 'yii\db\Connection','dsn' => 'mysql:host=localhost;dbname=testdb','username' => 'demo','password' => 'demo',],],];
db コンポーネントとは異なるデータベース接続を使いたい場合は、でづぴいぢ〨〩

メソッドをオーバーライドしなければなりません。
class Customer extends ActiveRecord{// ...
public static function getDb(){// "db2" アプリケーション・コンポーネントを使用
return \Yii::$app->db2;

〳〱〴

}

ぃえぁぐごぅげ 〶〮 データベースの取り扱い
}

6.3.3

データをクエリする

アクティブ・レコード・クラスを宣言した後、それを使って対応する
データベース・テーブルからデータをクエリすることが出来ます。 このプロセスは通常次の三つのステップを踏みます。
〱〮 べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺てどのつ〨〩 メソッドを呼んで、新しいクエリ・
オブジェクトを作成する。
〲〮 クエリ構築メソッド を呼んで、クエリ・オブジェクトを構築する。
〳〮 クエリ・メソッド を呼んで、アクティブ・レコードのインスタンスの形でデータを取得する。
ご覧のように、このプロセスは クエリ・ビルダ による手続きと非常によく似ています。 唯一の違いは、new 演算子を使ってクエリ・オブジェクトを生成する代りに、べどどぜつぢぜぁっぴどぶづけふづひべ クラスであるクエリ・オブジェ
クトを返す べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺てどのつ〨〩 を呼ぶ、という点です。
以下の例は、アクティブ・クエリを使ってデータをクエリする方法を示すものです。
// ID が 123 である一人の顧客を返す// SELECT * FROM `customer` WHERE `id` = 123$customer = Customer::find()->where(['id' => 123])->one();// アクティブな全ての顧客を返して、ID によって並べる// SELECT * FROM `customer` WHERE `status` = 1 ORDER BY `id`$customers = Customer::find()->where(['status' => Customer::STATUS_ACTIVE])->orderBy('id')->all();// アクティブな顧客の数を返す// SELECT COUNT(*) FROM `customer` WHERE `status` = 1$count = Customer::find()->where(['status' => Customer::STATUS_ACTIVE])->count();// 全ての顧客を顧客IDによってインデックスされた配列として返す// SELECT * FROM `customer`$customers = Customer::find()->indexBy('id')->all();

上記において、$customer は Customer オブジェクトであり、$customers は
Customer オブジェクトの配列です。 全てこれらには customer テーブルから取得されたデータが投入されます。

〶〮〳〮 アクティブ・レコード〳〱〵

情報〺 べどどぜつぢぜぁっぴどぶづけふづひべ は べどどぜつぢぜけふづひべ から拡張しているため、クエリ・ビルダ のセクションで説明されたクエリ構
築メソッドとクエリ・メソッドの 全て を使うことが出来ます。
プライマリ・キーの値や一群のカラムの値でクエリをすることはよく行われる仕事ですので、すどど はこの目的のために、 二つのショートカット・
メソッドを提供しています。
• べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺てどのつくのづ〨〩〺 クエリ結果の最初の行を一つのアクティブ・レコード・インスタンスに投入して返す。
• べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺てどのつぁぬぬ〨〩〺 全ての クエリ結果をアクティ
ブ・レコード・インスタンスの配列に投入して返す。
どちらのメソッドも、次のパラメータ形式のどれかを取ることが出来ます。
• スカラ値〺 値は検索時に求められるプライマリ・キーの値として扱われます。 すどど は、データベースのスキーマ情報を読んで、どのカラムがプライマリ・キーのカラムであるかを自動的に判断します。
• スカラ値の配列〺 配列は検索時に求められるプライマリ・キーの値の配列として扱われます。
• 連想配列〺 キーはカラム名であり、値は検索時に求められる対応するカラムの値です。 詳細については、ハッシュ形式 を参照してく
ださい。
次のコードは、これらのメソッドの使用方法を示すものです。
// ID が 123 である一人の顧客を返す// SELECT * FROM `customer` WHERE `id` = 123$customer = Customer::findOne(123);// ID が 100, 101, 123, 124 のどれかである顧客を全て返す// SELECT * FROM `customer` WHERE `id` IN (100, 101, 123, 124)
$customers = Customer::findAll([100, 101, 123, 124]);// ID が 123 であるアクティブな顧客を返す// SELECT * FROM `customer` WHERE `id` = 123 AND `status` = 1$customer = Customer::findOne(['id' => 123,
'status' => Customer::STATUS_ACTIVE,]);// アクティブでない全ての顧客を返す// SELECT * FROM `customer` WHERE `status` = 0$customers = Customer::findAll(['status' => Customer::STATUS_INACTIVE,]);

警告〺 これらのメソッドにユーザ入力を渡す必要がある場合
は、入力値がスカラ値であること、または、 入力値が配列形式の条件である場合は配列の構造が外部から変更され得ないことを保証して下さい。

〳〱〶ぃえぁぐごぅげ 〶〮 データベースの取り扱い// yii\web\Controller が $id はスカラ値であることを保証していますpublic function actionView($id){$model = Post::findOne($id);// ...
}// 検索するカラムを明示的に指定する場合。ここでは、どんなスカラ値または配列を渡しても、単一のレコードを発見する結果になります。
$model = Post::findOne(['id' => Yii::$app->request->get('id')]);// 次のコードを使用してはいけません! 任意のカラムの値による検索が可能な配列形式の条件を挿入される可能性があります!
$model = Post::findOne(Yii::$app->request->get('id'));補足〺 べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺てどのつくのづ〨〩 も べどどぜつぢぜぁっぴどぶづけふづひべ〺〺はのづ〨〩 も、生成される こけが 文に LIMIT 1 を追加しません。
あなたのクエリが多数のデータ行を返すかもしれない場合
は、パフォーマンスを向上させるために、limit(1) を明示的に呼ぶべきです。 例えば Customer::find()->limit(1)->one() のように。
クエリ構築メソッドを使う以外に、生の こけが を書いてデータをクエリして結果をアクティブ・レコード・オブジェクトに投入することも出来ます。 そうするためには べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺てどのつあべこぱぬ〨〩 メソッドを呼ぶことが出来ます。
// アクティブでない全ての顧客を返す$sql = 'SELECT * FROM customer WHERE status=:status';$customers = Customer::findBySql($sql, [':status' =>Customer::STATUS_INACTIVE])->all();てどのつあべこぱぬ〨〩 を呼んだ後は、追加でクエリ構築メソッドを呼び出してはいけません。 呼んでも無視されます。

6.3.4

データにアクセスする

既に述べたように、データベースから取得されたデータはアクティブ・
レコードのインスタンスに投入されます。 そして、クエリ結果の各行がアクティブ・レコードの一つのインスタンスに対応します。 アクティ
ブ・レコード・インスタンスの属性にアクセスすることによって、カラムの値にアクセスすることが出来ます。例えば、// "id" と "email" は "customer" テーブルのカラム名$customer = Customer::findOne(123);$id = $customer->id;$email = $customer->email;〶〮〳〮 アクティブ・レコード〳〱〷

補足〺 アクティブ・レコードの属性の名前は、関連付けられたテーブルのカラムの名前に従って、大文字と小文字を区別して名付けられます。 すどど は、関連付けられたテーブルの全てのカラムに対して、アクティブ・レコードの属性を自動的に定義します。 これらの属性は、すべて、再宣言してはいけません。
アクティブ・レコードの属性はテーブルのカラムに従って命名されるため、 テーブルのカラム名がアンダースコアで単語を分ける方法で命名されている場合は、 $customer->first_name のような属性名を使って ぐえぐ
コードを書くことになります。 コード・スタイルの一貫性が気になるのであれば、テーブルのカラム名を 〨例えば っちねづぬぃちびづ を使う名前に〩 変更
しなければなりません。
データ変換
入力または表示されるデータの形式が、データベースにデータを保存するときに使われるものと異なる場合がよくあります。 例えば、データベースでは顧客の誕生日を さぎぉじ タイムスタンプで保存している 〨まあ、
あまり良い設計ではありませんが〩 けれども、ほとんどの場合において誕生日を 'YYYY/MM/DD' という形式の文字列として操作したい、というような場合です。 この目的を達するために、次のように、Customer アクティ
ブ・レコード・クラスにおいて データ変換 メソッドを定義することが出来ます。
class Customer extends ActiveRecord{// ...
public function getBirthdayText(){
return date('Y/m/d', $this->birthday);}}public function setBirthdayText($value){$this->birthday = strtotime($value);}

このようにすれば、ぐえぐ コードにおいて、$customer->birthday にアクセスする代りに、$customer->birthdayText にアクセスすれば、 顧客の誕生日を'YYYY/MM/DD' の形式で入力および表示することが出来ます。
ヒント〺 上記は、一般にデータの変換を達成するための簡単な方法を示すためのものです。 日付の値については、すどど
は、いちぴづざちぬどつちぴはひ と いちぴづぐどっにづひ ウィジェットを使用するという、より良い方法を提供しています。 いちぴづぐどっにづひ については、おさぉ ウィジェットのセクション で説明されています。

〳〱〸ぃえぁぐごぅげ 〶〮 データベースの取り扱い

データを配列に取得するデータをアクティブ・レコード・オブジェクトの形で取得するのは便利であり柔軟ですが、大きなメモリ使用量を要するために、 大量のデータを取得しなければならない場合は、必ずしも望ましい方法ではありません。 そういう場合は、クエリ・メソッドを実行する前に ちびぁひひちべ〨〩 を呼ぶことによって、ぐえぐ 配列を使ってデータを取得することが出来ます。
// すべての顧客を返す// 各顧客は連想配列として返される$customers = Customer::find()->asArray()->all();

補足〺 このメソッドはメモリを節約してパフォーマンスを向上させますが、低レベルの いあ 抽象レイヤに近いものであり、あなたはアクティブ・レコードの機能のほとんどを失うことになります。非常に重要な違いが、カラムの値のデータ型に現れます。 アクティブ・レコード・インスタンスとしてデー
タを返す場合、カラムの値は実際のカラムの型に従って自動的に型キャストされます。 一方、配列としてデータを返す場
合は、実際のカラムの型に関係なく、カラムの値は文字列になります。 なぜなら、何も処理をしない場合の ぐいく の結果は文字列だからです。
データをバッチ・モードで取得する
クエリ・ビルダ において、大量のデータをデータベースから検索する場
合に、メモリ使用量を最小化するために バッチ・クエリ を使うことが出来るということを説明しました。おなじテクニックをアクティブ・レ
コードでも使うことが出来ます。例えば、// 一度に 10 人の顧客を読み出す
foreach (Customer::find()->batch(10) as $customers) {// $customers は 10 以下の Customer オブジェクトの配列}// 一度に 10 人の顧客を読み出して、一人ずつ反復する
foreach (Customer::find()->each(10) as $customer) {// $customer は Customer オブジェクト}// イーガー・ローディングをするバッチ・クエリ
foreach (Customer::find()->with('orders')->each() as $customer) {// $customer は 'orders' リレーションを投入された Customer オブジェクト}〶〮〳〮 アクティブ・レコード

6.3.5

〳〱〹

データを保存する

アクティブ・レコードを使えば、次のステップを踏んで簡単にデータをデータベースに保存することが出来ます。
〱〮 アクティブ・レコードのインスタンスを準備する〲〮 アクティブ・レコードの属性に新しい値を割り当てる〳〮 べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺びちぶづ〨〩 を呼んでデータをデータベースに保存する
例えば、// 新しいデータ行を挿入する$customer = new Customer();$customer->name = 'James';$customer->email = 'james@example.com';$customer->save();// 既存のデータ行を更新する$customer = Customer::findOne(123);$customer->email = 'james@newexample.com';$customer->save();

びちぶづ〨〩 メソッドは、アクティブ・レコード・インスタンスの状態に従って、データ行を挿入するか、 または、更新することが出来ます。インスタンスが new 演算子によって新しく作成されたものである場合は、
びちぶづ〨〩 を呼び出すと、新しい行が挿入されます。インスタンスがクエ
リ・メソッドの結果である場合は、 びちぶづ〨〩 を呼び出すと、そのインスタンスと関連付けられた行が更新されます。
アクティブ・レコード・インスタンスの二つの状態は、その どびぎづぷげづっはひつ
プロパティの値をチェックすることによって区別することが出来ます。
下記のように、このプロパティは びちぶづ〨〩 によっても内部的に使用されています。
public function save($runValidation = true, $attributeNames = null){
if ($this->getIsNewRecord()) {return $this->insert($runValidation, $attributeNames);} else {return $this->update($runValidation, $attributeNames) !== false;}}

ヒント〺 どのびづひぴ〨〩 または ふばつちぴづ〨〩 を直接に呼んで、 行を挿入または更新することも出来ます。

〳〲〰

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

データの検証
べどどぜつぢぜぁっぴどぶづげづっはひつ は べどどぜぢちびづぜきはつづぬ を拡張したものですので、同
じ データ検証 機能を共有しています。 ひふぬづび〨〩 メソッドをオーバーライ
ドすることによって検証規則を宣言し、 ぶちぬどつちぴづ〨〩 メソッドを呼ぶこと
によってテータの検証を実行することが出来ます。
びちぶづ〨〩 を呼ぶと、デフォルトでは ぶちぬどつちぴづ〨〩 が自動的に呼ばれます。 検証が通った時だけ、実際にデータが保存されます。 検証が通らなかった時は単に false が返され、づひひはひび プロパティをチェックして検証
エラー・メッセージを取得することが出来ます。
ヒント〺 データが検証を必要としないことが確実である場合〨例えば、データが信頼できるソースに由来するものである場
合〩 は、 検証をスキップするために save(false) を呼ぶことが
出来ます。
一括代入
通常の モデル と同じように、アクティブ・レコードのインスタンスも 一
括代入機能 を享受することが出来ます。 この機能を使うと、下記で示されているように、一つの ぐえぐ 文で、アクティブ・レコード・インスタン
スの複数の属性に値を割り当てることが出来ます。 ただし、安全な属性だけが一括代入が可能であることを記憶しておいてください。
$values = ['name' => 'James','email' => 'james@example.com',];$customer = new Customer();$customer->attributes = $values;$customer->save();

カウンタを更新する
データベース・テーブルのあるカラムの値を増加・減少させるのは、よくある仕事です。私たちはそのようなカラムをカウンタ・カラムと呼んでいます。 ふばつちぴづぃはふのぴづひび〨〩 を使って一つまたは複数のカウンタ・カラ
ムを更新することが出来ます。 例えば、
$post = Post::findOne(100);// UPDATE `post` SET `view_count` = `view_count` + 1 WHERE `id` = 100$post->updateCounters(['view_count' => 1]);

補足〺 カウンタ・カラムを更新するのに べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺びちぶづ〨〩 を使うと、不正確な結果になってしまう場合があり〶〮〳〮 アクティブ・レコード〳〲〱

ます。 というのは、同じカウンタの値を読み書きする複数のリクエストによって、同一のカウンタが保存される可能性があるからです。
ダーティな属性
びちぶづ〨〩 を呼んでアクティブ・レコード・インスタンスを保存すると、ダーティな属性 だけが保存されます。 属性は、いあ からロードされた
後、または、最後に保存された後にその値が変更されると、ダーティ であると見なされます。 ただし、データ検証は、アクティブ・レコード・
インスタンスがダーティな属性を持っているかどうかに関係なく実施される ことに注意してください。
アクティブ・レコードはダーティな属性のリストを自動的に保守します。 そうするために、一つ前のバージョンの属性値を保持して、最新のバージョンと比較します。 べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺でづぴいどひぴべぁぴぴひどぢふぴづび〨〩を呼ぶと、現在ダーティである属性を取得することが出来ます。 また、べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺ねちひにぁぴぴひどぢふぴづいどひぴべ〨〩 を呼んで、ある属性
をダーティであると明示的にマークすることも出来ます。
最新の修正を受ける前の属性値を知りたい場合は、でづぴくぬつぁぴぴひどぢふぴづび〨〩
または でづぴくぬつぁぴぴひどぢふぴづ〨〩 を呼ぶことが出来ます。
補足〺 新旧の値は === 演算子を使って比較されるため、同じ値を持っていても型が違うとダーティであると見なされます。
このことは、モデルが えごきが フォームからユーザの入力を受け取るときにしばしば生じます。 えごきが フォームでは全ての値が文字列として表現されるからです。 入力値が正しい型、
例えば整数値となることを保証するために、['attributeName','filter', 'filter' => 'intval'] のように 検証フィルタ を適用することが出来ます。 このフィルタは、どのぴぶちぬ〨〩23 〬 〝はちぴぶちぬ〨〩24 〬ぢははぬぶちぬ25 など、ぐえぐ の全てのタイプキャスト関数で動作します。
デフォルト属性値
あなたのテーブルのカラムの中には、データベースでデフォルト値が定義されているものがあるかも知れません。 そして、場合によっては、ア
クティブ・レコード・インスタンスのウェブ・フォームに、そういうデ
フォルト値をあらかじめ投入したいことがあるでしょう。 同じデフォル
ト値を繰り返して書くことを避けるために、ぬはちついづてちふぬぴざちぬふづび〨〩 を呼んで、いあ で定義されたデフォルト値を対応するアクティブ・レコードの属性に投入することが出来ます。
https://www.php.net/manual/ja/function.intval.php
https://www.php.net/manual/ja/function.floatval.php
25
https://www.php.net/manual/ja/function.boolval.php
23
24

〳〲〲

ぃえぁぐごぅげ 〶〮 データベースの取り扱い$customer = new Customer();$customer->loadDefaultValues();// $customer->xyz には、"xyz" カラムを定義するときに宣言されたデフォルト値が割り当てられる

属性の型キャスト
べどどぜつぢぜぁっぴどぶづげづっはひつ は、クエリの結果を投入されるときに、データ
ベース・テーブル・スキーマ からの情報を使って、自動的な型キャストを実行します。これによって、整数として宣言されているテーブルカ
ラムから取得されるデータを アクティブ・レコードのインスタンスでも ぐえぐ の どのぴづでづひ として投入し、真偽値として宣言されているデータを
ぢははぬづちの として投入することが出来るようになっています。 しかしながら、型キャストのメカニズムには、いくつかの制約があります。
• 浮動小数点数値は変換されず、文字列として表されます。そうしな
いと精度が失われるおそれがあるからです。
• 整数値の変換は、あなたが使っているオペレーティング・システムの整数の大きさに依存します。具体的に言うと、 だふのびどでのづつ どのぴづでづひ〧
または だぢどで どのぴづでづひ〧 として宣言されたカラムの値は、〶〴〭ぢどぴ オペレー
ティングシステムでのみ ぐえぐ の どのぴづでづひ に変換されます。 〳〲〭ぢどぴ オ
ペレーティングシステムでは、文字列として表されます。
属性の型キャストは、アクティブ・レコードのインスタンスにクエリの結果から値を投入するときだけしか実行されないことに注意してください。 えごごぐ リクエストから値をロードしたり、プロパティにアクセスして直接に値を設定したりするときには、自動的な変換は行われません。
また、アクティブ・レコードのデータ保存のための こけが 文を準備する際にもテーブル・スキーマが使用されて、 値が正しい型でクエリにバインドされることを保証します。 しかし、アクティブ・レコードのインスタ
ンスの属性値は保存の過程において変換されることはありません。
ヒント〺 アクティブ・レコードの検証や保存の際の属性型キャ
ストを楽にするために べどどぜぢづとちぶどはひびぜぁぴぴひどぢふぴづごべばづっちびぴあづとちぶどはひを使うことが出来ます。
〲〮〰〮〱〴 以降、すどど のアクティブ・レコードは、おこくぎ や多次元配列のような複雑な型をサポートしています。
きべこけが および ぐはびぴでひづこけが における おこくぎ データが取得された
後、おこくぎ カラムの値は標準的な おこくぎ デコード規則に従って、 自動的に おこくぎ からデコードされます。
アクティブ・レコードは、属性値を おこくぎ カラムに保存するためにおびはのぅへばひづびびどはの オブジェクトを自動的に生成します。このオブジェクト
が クエリ・ビルダ レベルで おこくぎ 文字列にエンコードされます。

〶〮〳〮 アクティブ・レコード〳〲〳

ぐはびぴでひづこけが における配列 データが取得された後、配列カラムの値
は ぐでこけが 記法から自動的に ぁひひちべぅへばひづびびどはの オブジェクトにデコードされます。 このオブジェクトは ぐえぐ の ArrayAccess インタフェイスを実装しているため、これを配列として使うこと事が出来ます。また、->getValue() を呼んで配列そのものを取得することも出来ます。
アクティブ・レコードは、属性値を配列カラムに保存するためにぁひひちべぅへばひづびびどはの オブジェクトを生成します。このオブジェクトが ク
エリ・ビルダ のレベルで配列を表す ぐでこけが 文字列にエンコードされます。
おこくぎ カラムに対して条件を使用することも出来ます。
$query->andWhere(['=', 'json', new ArrayExpression(['foo' => 'bar'])

式を構築するシステムについて更に学習するためには クエリ・ビルダ〕 特製の条件や式を追加する という記事を参照して下さい。
複数の行を更新する
上述のメソッドは、すべて、個別のアクティブ・レコード・インスタン
スに対して作用し、個別のテーブル行を挿入したり更新したりするものです。 複数の行を同時に更新するためには、代りに、スタティックなメ
ソッドである ふばつちぴづぁぬぬ〨〩 を呼ばなければなりません。
// UPDATE `customer` SET `status` = 1 WHERE `email` LIKE `%@example.com`
Customer::updateAll(['status' => Customer::STATUS_ACTIVE], ['like', 'email','@example.com']);

同様に、ふばつちぴづぁぬぬぃはふのぴづひび〨〩 を呼んで、 複数の行のカウンタカラムを同時に更新することが出来ます。
// UPDATE `customer` SET `age` = `age` + 1
Customer::updateAllCounters(['age' => 1]);

6.3.6

データを削除する

一行のデータを削除するためには、最初にその行に対応するアクティ
ブ・レコード・インスタンスを取得して、 次に べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺
つづぬづぴづ〨〩 メソッドを呼びます。
$customer = Customer::findOne(123);$customer->delete();

べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺つづぬづぴづぁぬぬ〨〩 を呼んで、複数またはすべてのデー
タ行を削除することが出来ます。例えば、
Customer::deleteAll(['status' => Customer::STATUS_INACTIVE]);

補足〺 つづぬづぴづぁぬぬ〨〩 を呼ぶときは、十分に注意深くしてください。 なぜなら、条件の指定を間違うと、あなたのテーブルからすべてのデータを完全に消し去ってしまうことになるから
です。

〳〲〴

6.3.7

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

アクティブ・レコードのライフサイクル

アクティブ・レコードがさまざまな目的で使用される場合のそれぞれのライフサイクルを理解しておくことは重要なことです。 それぞれのライ
フサイクルにおいては、特定の一続きのメソッドが呼び出されます。 そして、これらのメソッドをオーバーライドして、ライフサイクルをカス
タマイズするチャンスを得ることが出来ます。 また、ライフサイクルの中でトリガされる特定のアクティブ・レコード・イベントに反応して、あなたのカスタム・コードを挿入することも出来ます。 これらのイベントが特に役に立つのは、アクティブ・レコードのライフサイクルをカス
タマイズする必要のあるアクティブ・レコード・ビヘイビア を開発する
際です。
次に、さまざまなアクティブ・レコードのライフサイクルと、 そのラ
イフサイクルに含まれるメソッドやイベントを要約します。
新しいインスタンスのライフサイクル
new 演算子によって新しいアクティブ・レコード・インスタンスを作成する場合は、次のライフサイクルを経ます。
〱〮 クラスのコンストラクタ。
〲〮 どのどぴ〨〩〺 ぅざぅぎごたぉぎぉご イベントをトリガ。
データをクエリする際のライフサイクル
クエリ・メソッド のどれか一つによってデータをクエリする場合は、 新
しくデータを投入されるアクティブ・レコードは次のライフサイクルを経ます。
〱〮 クラスのコンストラクタ。
〲〮 どのどぴ〨〩〺 ぅざぅぎごたぉぎぉご イベントをトリガ。
〳〮 ちてぴづひうどのつ〨〩〺 ぅざぅぎごたぁうごぅげたうぉぎい イベントをトリガ。
データを保存する際のライフサイクル
びちぶづ〨〩 を呼んでアクティブ・レコード・インスタンスを挿入または更新する場合は、 次のライフサイクルを経ます。
〱〮 ぢづてはひづざちぬどつちぴづ〨〩〺 ぅざぅぎごたあぅうくげぅたざぁがぉいぁごぅ イベントをトリガ。 このメソッドが false を返すか、べどどぜぢちびづぜきはつづぬぅぶづのぴ〺〺〤どびざちぬどつ が
false であった場合、 残りのステップはスキップされる。
〲〮 データ検証を実行。データ検証が失敗した場合、〳 より後のステッ
プはスキップされる。

〶〮〳〮 アクティブ・レコード〳〲〵〳〮 ちてぴづひざちぬどつちぴづ〨〩〺 ぅざぅぎごたぁうごぅげたざぁがぉいぁごぅ イベントをトリガ。
〴〮 ぢづてはひづこちぶづ〨〩〺 ぅざぅぎごたあぅうくげぅたぉぎこぅげご または ぅざぅぎごたあぅうくげぅたさぐいぁごぅ
イベントをトリガ。 このメソッドが false を返すか、べどどぜぢちびづ
ぜきはつづぬぅぶづのぴ〺〺〤どびざちぬどつ が false であった場合、 残りのステップはスキップされる。
〵〮 実際のデータの挿入または更新を実行。
〶〮 ちてぴづひこちぶづ〨〩〺 ぅざぅぎごたぁうごぅげたぉぎこぅげご または ぅざぅぎごたぁうごぅげたさぐいぁごぅ イ
ベントをトリガ。
データを削除する際のライフサイクル
つづぬづぴづ〨〩 を呼んでアクティブ・レコード・インスタンスを削除する際は、 次のライフサイクルを経ます。
〱〮 ぢづてはひづいづぬづぴづ〨〩〺 ぅざぅぎごたあぅうくげぅたいぅがぅごぅ イベントをトリガ。このメソッドが false を返すか、べどどぜぢちびづぜきはつづぬぅぶづのぴ〺〺〤どびざちぬどつ が false
であった場合は、 残りのステップはスキップされる。
〲〮 実際のデータの削除を実行。
〳〮 ちてぴづひいづぬづぴづ〨〩〺 ぅざぅぎごたぁうごぅげたいぅがぅごぅ イベントをトリガ。
補足〺 次のメソッドを呼んだ場合は、いずれの場合も、上記のライフサイクルのどれかを開始させることはありません。 こ
れらのメソッドは、レコード単位ではなく、データベース上で直接に動作するためです。
• べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺ふばつちぴづぁぬぬ〨〩• べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺つづぬづぴづぁぬぬ〨〩• べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺ふばつちぴづぃはふのぴづひび〨〩• べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺ふばつちぴづぁぬぬぃはふのぴづひび〨〩
データをリフレッシュする際のライフサイクル
ひづてひづびと〨〩 を呼んでアクティブ・レコード・インスタンスをリフレッ
シ ュ す る 際 は 、 リ フ レ ッ シ ュ が 成 功 し て メ ソ ッ ド が true を 返 す とぅざぅぎごたぁうごぅげたげぅうげぅこえ イベントがトリガされます。

6.3.8

トランザクションを扱う

アクティブ・レコードを扱う際には、二つの方法で トランザクション を処理することができます。
最初の方法は、次に示すように、アクティブ・レコードのメソッドの呼び出しを明示的にトランザクションのブロックで囲む方法です。

〳〲〶

ぃえぁぐごぅげ 〶〮 データベースの取り扱い$customer = Customer::findOne(123);
Customer::getDb()->transaction(function($db) use ($customer) {$customer->id = 200;
$customer->save();// ... 他の DB 操作 ...
});// あるいは、別の方法$transaction = Customer::getDb()->beginTransaction();try {$customer->id = 200;
$customer->save();// ... 他の DB 操作 ...
$transaction->commit();} catch(\Exception $e) {$transaction->rollBack();throw $e;
} catch(\Throwable $e) {$transaction->rollBack();throw $e;}

補足〺 上記のコードでは、ぐえぐ 〵〮へ と ぐえぐ 〷〮へ との互換性のために、二つの っちぴっと ブロックを持っています。 \Exception は
ぐえぐ 〷〮〰 以降では、\Throwable インタフェイス26 を実装しています。 従って、あなたのアプリケーションが ぐえぐ 〷〮〰 以上しか使わない場合は、\Exception の部分を省略することが出来ます。
第二の方法は、トランザクションのサポートが必要な いあ 操作を べどどぜつぢ
ぜぁっぴどぶづげづっはひつ〺〺ぴひちのびちっぴどはのび〨〩 メソッドに列挙するという方法です。
class Post extends \yii\db\ActiveRecord{
public function transactions(){
return ['admin' => self::OP_INSERT,'api' => self::OP_INSERT | self::OP_UPDATE | self::OP_DELETE,// 上は次と等価// 'api' => self::OP_ALL,];}}

べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺ぴひちのびちっぴどはのび〨〩 メソッドが返す配列では、キーは シナリオ の名前であり、 値はトランザクションで囲まれるべき操作
26

https://www.php.net/manual/ja/class.throwable.php〶〮〳〮 アクティブ・レコード〳〲〷

でなくてはなりません。 いろいろな いあ 操作を参照するのには、次の定数を使わなければなりません。
• くぐたぉぎこぅげご〺 どのびづひぴ〨〩 によって実行される挿入の操作。
• くぐたさぐいぁごぅ〺 ふばつちぴづ〨〩 によって実行される更新の操作。
• くぐたいぅがぅごぅ〺 つづぬづぴづ〨〩 によって実行される削除の操作。
複数の操作を示すためには、| を使って上記の定数を連結してください。
ショートカット定数 くぐたぁがが を使って、上記の三つの操作すべてを示すことも出来ます。
このメソッドを使って生成されたトランザクションは、ぢづてはひづこちぶづ〨〩を呼ぶ前に開始され、 ちてぴづひこちぶづ〨〩 を実行した後にコミットされます。

6.3.9

楽観的ロック

楽観的ロックは、一つのデータ行が複数のユーザによって更新されるときに発生しうる衝突を回避するための方法です。 例えば、ユーザ ぁ と
ユーザ あ が 同時に同じ ぷどにど 記事を編集しており、ユーザ ぁ が自分の編集結果を保存した後に、 ユーザ あ も自分の編集結果を保存しようとして「保存」ボタンをクリックする場合を考えてください。 ユーザ あ は、実際には古くなったバージョンの記事に対する操作をしようとしています
ので、彼が記事を保存するのを防止し、 彼に何らかのヒント・メッセー
ジを表示する方法があることが望まれます。
楽観的ロックは、あるカラムを使って各行のバージョン番号を記録するという方法によって、上記の問題を解決します。 古くなったバージョ
ン番号とともに行を保存しようとすると、べどどぜつぢぜこぴちぬづくぢなづっぴぅへっづばぴどはの
例外が投げられて、 行が保存されるのが防止されます。 楽観的ロッ
クは、 べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺ふばつちぴづ〨〩 または べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺
つづぬづぴづ〨〩 メソッドを使って既存の行を更新または削除しようとする場合にだけサポートされます。
楽観的ロックを使用するためには、次のようにします。
〱〮 アクティブ・レコード・クラスと関連付けられている いあ テーブルに、各行のバージョン番号を保存するカラムを作成します。 カラム
は長倍精度整数 〨ぢどで どのぴづでづひ〩 タイプでなければなりません 〨きべこけがでは BIGINT DEFAULT 0 です〩。
〲〮 べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺はばぴどねどびぴどっがはっに〨〩 メソッドをオーバーライ
ドして、このカラムの名前を返すようにします。
〳〮 あなたのモデル・クラスの中で くばぴどねどびぴどっがはっにあづとちぶどはひ を実装
し、受信したリクエストからその値を自動的に解析できるようにします。 くばぴどねどびぴどっがはっにあづとちぶどはひ が検証を処理すべきですので、バージョンの属性は検証規則から削除します。
〴〮 ユーザ入力を収集するウェブフォームに、更新されるレコードの現在のバージョン番号を保持する隠しフィールドを追加します。

〳〲〸ぃえぁぐごぅげ 〶〮 データベースの取り扱い〵〮 アクティブ・レコードを使って行の更新を行うコントローラ・アク
ションにおいて、べどどぜつぢぜこぴちぬづくぢなづっぴぅへっづばぴどはの 例外を捕捉して、衝突を解決するために必要なビジネス・ロジック 〨例えば、変更をマージしたり、データの陳腐化を知らせたり〩 を実装します。
例えば、バージョン番号のカラムが version と名付けられているとすると、 次のようなコードによって楽観的ロックを実装することが出来ます。
// ------ ビューのコード ------use yii\helpers\Html;// ... 他の入力フィールド
echo Html::activeHiddenInput($model, 'version');// ------ コントローラのコード ------use yii\db\StaleObjectException;
public function actionUpdate($id){$model = $this->findModel($id);

}

try {
if ($model->load(Yii::$app->request->post()) && $model->save()) {return $this->redirect(['view', 'id' => $model->id]);} else {return $this->render('update', ['model' => $model,]);}} catch (StaleObjectException $e) {// 衝突を解決するロジック}// ------ モデルのコード ------use yii\behaviors\OptimisticLockBehavior;public function behaviors(){
return [OptimisticLockBehavior::class,];}public function optimisticLock(){return 'version';}〶〮〳〮 アクティブ・レコード〳〲〹

補足〺 くばぴどねどびぴどっがはっにあづとちぶどはひ は、ユーザが正しいバージョ
ン番号を送信したときにだけ レコードが保存されるという事を保証します。そして、そのために、でづぴあはつべぐちひちね〨〩 の結果を直接に解析します。 そこで、あなたのモデル・クラスを拡張して、親モデルで第〲段階を行い、ビヘイビアのアタッ
チ〨第〳段階〩を子モデルで行うようにすると便利でしょう。 そうすれば、一方を内部使用のためだけのインスタンスとして使うことが出来、他方をエンド・ユーザの入力の受信に責任を持つモデルとしてコントローラと結びつける事が出来ます。 もう一つのやり方としては、ぶちぬふづ プロパティを構成して独自のロジックを実装することも可能です。

6.3.10

リレーショナル・データを扱う

個々のデータベース・テーブルを扱うだけでなく、アクティブ・レコー
ドは関連したテーブルのデータも一緒に読み出して、 主たるデータを通して簡単にアクセス出来るようにすることが出来ます。 例えば、一人の顧客は一つまたは複数の注文を発することがあり得ますので、顧客のデータは注文のデータと関連を持っていることになります。 このリレーションが適切に宣言されていれば、$customer->orders という式を使って顧客の注文情報にアクセスすることが出来ます。 $customer->orders は、顧客の注文情報を Order アクティブ・レコード・インスタンスの配列として返してくれます。
リレーションを宣言する
アクティブ・レコードを使ってリレーショナル・データを扱うためには、最初に、アクティブ・レコード・クラスの中でリレーションを宣言する必要があります。 これは、以下のように、関心のあるそれぞれのリレーションについて リレーション・メソッド を宣言するだけの簡単な作業です。
class Customer extends ActiveRecord{// ...

}

public function getOrders(){
return $this->hasMany(Order::class, ['customer_id' => 'id']);}class Order extends ActiveRecord{// ...
public function getCustomer()
{

〳〳〰

}

ぃえぁぐごぅげ 〶〮 データベースの取り扱い}

return $this->hasOne(Customer::class, ['id' => 'customer_id']);上記のコードでは、Customer クラスのために orders リレーションを宣言
し、Order クラスのために customer リレーションを宣言しています。
各リレーション・メソッドは getXyz という名前にしなければなりません。ここで xyz 〨最初の文字は小文字です〩 が リレーション名 と呼ばれます。 リレーション名は 大文字と小文字を区別する ことに注意してください。
リレーションを宣言する際には、次の情報を指定しなければなりません。
• リレーションの多重性〺 とちびきちのべ〨〩 または とちびくのづ〨〩 のどちらかを呼ぶことによって指定されます。 上記の例では、リレーションの宣言
において、顧客は複数の注文を持ち得るが、一方、注文は一人の顧客しか持たない、ということが容易に読み取れます。
• 関連するアクティブ・レコード・クラスの名前〺 とちびきちのべ〨〩 または
とちびくのづ〨〩 の最初のパラメータとして指定されます。 クラス名を取得するのに Xyz::class を呼ぶのが推奨されるプラクティスです。 そうすれば、ぉいぅ の自動補完のサポートを得ることことが出来るだけでなく、コンパイル段階でエラーを検出することが出来ます。
• 二つの型のデータ間のリンク〺 二つの型のデータの関連付けに用いられるカラムを指定します。 配列の値は主たるデータ 〨リレーションを宣言しているアクティブ・レコード・クラスによって表される
データ〩 のカラムであり、 配列のキーは関連するデータのカラムです。
これを記憶するための簡単な規則は、上の例で見るように、関連するアクティブ・レコードを書いた直後に、それに属するカラムを 続
けて書く、ということです。ご覧のように、customer_id は Order のプロパティであり、 id はCustomer のプロパティです。
警告〺 リレーション名としては relation は予約済みで使えません。これを使うと ArgumentCountError となります。
リレーショナル・データにアクセスする
リレーションを宣言した後は、リレーション名を通じてリレーショナ
ル・データにアクセスすることが出来ます。 これは、リレーション・メ
ソッドによって定義されるオブジェクト・プロパティ にアクセスするのと同様です。 このため、これを リレーション・プロパティ と呼びます。
例えば、// SELECT * FROM `customer` WHERE `id` = 123$customer = Customer::findOne(123);// SELECT * FROM `order` WHERE `customer_id` = 123〶〮〳〮 アクティブ・レコード〳〳〱// $orders is an array of Order objects$orders = $customer->orders;

情報〺 xyz という名前のリレーションを でづぴぴづひ メソッド getXyz()
によって宣言すると、xyz を オブジェクト・プロパティ のよ
うにアクセスすることが出来るようになります。名前は大文
字と小文字を区別することに注意してください。
リレーションが とちびきちのべ〨〩 によって宣言されている場合は、 このリレー
ション・プロパティにアクセスすると、関連付けられたアクティブ・レ
コード・インスタンスの配列が返されます。 リレーションが とちびくのづ〨〩によって宣言されている場合は、 このリレーション・プロパティにアクセスすると、関連付けられたアクティブ・レコード・インスタンスか、
関連付けられたデータが見つからないときは null が返されます。
リレーション・プロパティに最初にアクセスしたときは、上記の例で示されているように、こけが 文が実行されます。 その同じプロパティに再びアクセスしたときは、こけが 文を再実行することなく、以前の結果が返されます。 こけが 文の再実行を強制するためには、まず、リレー
ション・プロパティの割り当てを解除 〨ふのびづぴ〩 しなければなりません 〺
unset($customer->orders)。
補足〺 リレーション・プロパティの概念は オブジェクト・プ
ロパティ の機能と同一であるように見えますが、一つ、重要な相違点があります。 通常のオブジェクト・プロパティでは、プロパティの値はそれを定義する でづぴぴづひ メソッドと同じ型を持ちます。 しかし、リレーション・プロパティにアクセスすると べどどぜつぢぜぁっぴどぶづげづっはひつ のインスタンスまたはその配列が返されるのに対して、 リレーション・メソッドは べどどぜつぢ
ぜぁっぴどぶづけふづひべ のインスタンスを返します。
$customer->orders; // `Order` オブジェクトの配列$customer->getOrders(); // ActiveQuery のインスタンス

このことは、次のセクションで説明するように、カスタマイズしたクエリを作成するのに役に立ちます。
動的なリレーショナル・クエリ
リレーション・メソッドは べどどぜつぢぜぁっぴどぶづけふづひべ のインスタンスを返すた
め、いあ クエリを実行する前に、 クエリ構築メソッドを使ってこのクエ
リを更に修正することが出来ます。例えば、$customer = Customer::findOne(123);// SELECT * FROM `order` WHERE `customer_id` = 123 AND `subtotal` > 200
ORDER BY `id`
$orders = $customer->getOrders()〳〳〲

ぃえぁぐごぅげ 〶〮 データベースの取り扱い->where(['>', 'subtotal', 200])->orderBy('id')->all();

リレーション・プロパティにアクセスする場合と違って、リレーショ
ン・メソッドによって動的なリレーショナル・クエリを実行する場合
は、 同じ動的なリレーショナル・クエリが以前に実行されたことがあっても、毎回、こけが 文が実行されます。
さらに進んで、もっと簡単に動的なリレーショナル・クエリを実行できるように、リレーションの宣言をパラメータ化したい場合もあるでしょう。 例えば、bigOrders リレーションを下記のように宣言することが出来ます。
class Customer extends ActiveRecord{
public function getBigOrders($threshold = 100){
return $this->hasMany(Order::class, ['customer_id' => 'id'])->where('subtotal > :threshold', [':threshold' => $threshold])->orderBy('id');}}

これによって、次のようなリレーショナル・クエリを実行することが出来るようになります。
// SELECT * FROM `order` WHERE `customer_id` = 123 AND `subtotal` > 200
ORDER BY `id`
$orders = $customer->getBigOrders(200)->all();// SELECT * FROM `order` WHERE `customer_id` = 123 AND `subtotal` > 100
ORDER BY `id`
$orders = $customer->bigOrders;

中間テーブルによるリレーション
データベースの設計において、二つの関連するテーブル間の多重性が多対多である場合は、通常、 中間テーブル27 が導入されます。 例え
ば、order テーブルと item テーブルは、order_item と言う名前の中間テー
ブルによって関連付けることが出来ます。 このようにすれば、一つの注文を複数の商品に対応させ、また、一つの商品を複数の注文に対応させることが出来ます。
このようなリレーションを宣言するときは、ぶどち〨〩 または ぶどちごちぢぬづ〨〩のどちらかを呼んで中間テーブルを指定します。 ぶどち〨〩 と ぶどちごちぢぬづ〨〩の違いは、 前者が既存のリレーション名の形式で中間テーブルを指定するのに対して、後者は中間テーブルを直接に指定する、という点です。
例えば、
27
https://ja.wikipedia.org/wiki/%E9%80%A3%E6%83%B3%E3%82%A8%E3%83%B3%E3%
83%86%E3%82%A3%E3%83%86%E3%82%A3〶〮〳〮 アクティブ・レコード〳〳〳

class Order extends ActiveRecord{
public function getItems(){
return $this->hasMany(Item::class, ['id' => 'item_id'])->viaTable('order_item', ['order_id' => 'id']);}}あるいは、また、
class Order extends ActiveRecord{
public function getOrderItems(){
return $this->hasMany(OrderItem::class, ['order_id' => 'id']);}}public function getItems(){
return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems');}

中間テーブルを使って宣言されたリレーションの使い方は、通常のリレーションと同じです。例えば、// SELECT * FROM `order` WHERE `id` = 100$order = Order::findOne(100);// SELECT * FROM `order_item` WHERE `order_id` = 100// SELECT * FROM `item` WHERE `item_id` IN (...)// 商品オブジェクトの配列を返す$items = $order->items;

複数のテーブルを経由するリレーション定義の連鎖
さらに、ぶどち〨〩 を使ってリレーション定義を連鎖させ、複数のテーブルを経由するリレーションを定義することも可能です。 上記の例で考えましょう。そこには Customer〨顧客〩、Order〨注文〩 そして Item〨品目〩 というクラスがあります。 Customer クラスに、発注された全ての注文によって購入された全ての品目を列挙するリレーションを追加して、 それに
getPurchasedItems() という名前を付けることが出来ます。リレーション定義の連鎖が次のコード・サンプルで示されています。
class Customer extends ActiveRecord{// ...
public function getPurchasedItems()〳〳〴

ぃえぁぐごぅげ 〶〮 データベースの取り扱い{}// 顧客の購入品目、すなわち、`Item` の 'id' カラムが OrderItem の'item_id' に合致するもの
return $this->hasMany(Item::class, ['id' => 'item_id'])->via('orderItems');

public function getOrderItems(){// 顧客の OrderItems、すなわち、`Order` の `id` カラムが `OrderItem`の 'order_id' に合致するもの
return $this->hasMany(OrderItem::class, ['order_id' => 'id'])->via('orders');}}

public function getOrders(){// 顧客の注文
return $this->hasMany(Order::class, ['customer_id' => 'id']);}レイジー・ローディングとイーガー・ローディング
リレーショナル・データにアクセスする において、通常のオブジェク
ト・プロパティにアクセスするのと同じようにして、 アクティブ・レ
コード・インスタンスのリレーション・プロパティにアクセスすることが出来ることを説明しました。 こけが 文は、リレーション・プロパティに最初にアクセスするときにだけ実行されます。 このようなリレーショナ
ル・データのアクセス方法を レイジー・ローディング と呼びます。例えば、// SELECT * FROM `customer` WHERE `id` = 123$customer = Customer::findOne(123);// SELECT * FROM `order` WHERE `customer_id` = 123$orders = $customer->orders;// SQL は実行されない$orders2 = $customer->orders;

レイジー・ローディングは非常に使い勝手が良いものです。 しかし、複数のアクティブ・レコード・インスタンスの同じリレーション・プロパ
ティにアクセスする必要がある場合は、パフォーマンスの問題を生じ得ます。 次のコードサンプルを考えて見てください。実行される こけが 文の数はいくらになるでしょう〿// SELECT * FROM `customer` LIMIT 100$customers = Customer::find()->limit(100)->all();〶〮〳〮 アクティブ・レコード〳〳〵

foreach ($customers as $customer) {// SELECT * FROM `order` WHERE `customer_id` = ...
$orders = $customer->orders;}

上のコードのコメントから判るように、実行される こけが 文は 〱〰〱 にもなります。 これは、てはひ ループの中で、異なる Customer オブジェクトのorders リレーションにアクセスするたびに、 こけが 文が一つ実行されることになるからです。
このパフォーマンスの問題を解決するために、次に示すように、いわゆる イーガー・ローディング の手法を使うことが出来ます。
// SELECT * FROM `customer` LIMIT 100;// SELECT * FROM `orders` WHERE `customer_id` IN (...)$customers = Customer::find()->with('orders')->limit(100)->all();
foreach ($customers as $customer) {// SQL は実行されない$orders = $customer->orders;}

べどどぜつぢぜぁっぴどぶづけふづひべ〺〺ぷどぴと〨〩 を呼ぶことによって、最初の 〱〰〰 人の顧客の注文をたった一つの こけが 文で返すように、アクティブ・レコードに指示をしています。 結果として、実行される こけが 文の数は 〱〰〱 から 〲 に減ります。
イーガー・ローディングは、一つだけでなく、複数のリレーションに対しても使うことが出来ます。さらには、ネストされたリレーション でさえ、イーガー・ロードすることが出来ます。 ネストされたリレーションというのは、関連するアクティブ・レコードの中で宣言されているリレーションです。 例えば、Cutomer が orders リレーションによって Orderと関連しており、Order が items リレーションによって Item と関連している場合です。 Customer に対するクエリを実行するときに、ネストされたリレーションの記法である orders.items を使って、items をイーガー・
ロードすることが出来ます。
次のコードは、ぷどぴと〨〩 のさまざまな使い方を示すものです。 ここでは、Customer クラスは orders と country という二つのリレーションを持っており、また、Order クラスは items という一つのリレーションを持っていると仮定しています。
// "orders" と "country" の両方をイーガー・ロードする$customers = Customer::find()->with('orders', 'country')->all();// これは下の配列記法と等価$customers = Customer::find()->with(['orders', 'country'])->all();// SQL は実行されない$orders= $customers[0]->orders;〳〳〶

ぃえぁぐごぅげ 〶〮 データベースの取り扱い// SQL は実行されない$country = $customers[0]->country;// "orders" リレーションと、ネストされた "orders.items" をイーガー・ロード$customers = Customer::find()->with('orders.items')->all();// 最初の顧客の、最初の注文の品目にアクセスする// SQL は実行されない$items = $customers[0]->orders[0]->items;

深くネストされたリレーション、たとえば a.b.c.c をイーガー・ロード
することも出来ます。 このとき、すべての親リレーションもイーガー・
ロードされます。 つまり、a.b.c.d を使って ぷどぴと〨〩 を呼ぶと、a、a.b、a.b.c
そして a.b.c.d をイーガー・ロードすることになります。
情報〺 一般化して言うと、N 個のリレーションのうち M 個のリレーションが 中間テーブル によって定義されている場合、 この N 個のリレーションをイーガー・ロードしようとすると、合計で 1+M+N 個の こけが クエリが実行されます。 ネストされたリレーション a.b.c.d は 〴 個のリレーションとして数えられることに注意してください。
リレーションをイーガー・ロードするときに、対応するリレーショナ
ル・クエリを無名関数を使ってカスタマイズすることが出来ます。 例えば、// 顧客を検索し、その国とアクティブな注文を同時に返す// SELECT * FROM `customer`// SELECT * FROM `country` WHERE `id` IN (...)// SELECT * FROM `order` WHERE `customer_id` IN (...) AND `status` = 1$customers = Customer::find()->with(['country','orders' => function ($query) {$query->andWhere(['status' => Order::STATUS_ACTIVE]);},])->all();

リレーションのためのリレーショナル・クエリをカスタマイズするとき
は、リレーション名を配列のキーとし、対応する値に無名関数を使わなければなりません。 無名関数が受け取る $query パラメータは、リレー
ションのためのリレーショナル・クエリを実行するのに使用される べどど
ぜつぢぜぁっぴどぶづけふづひべ オブジェクトを表します。 上のコード例では、注文の状態に関する条件を追加して、リレーショナル・クエリを修正しています。
補足〺 リレーションをイーガー・ロードするときに びづぬづっぴ〨〩を呼ぶ場合は、 リレーションの宣言で参照されているカラムが選択されるように注意しなければなりません。 そうしないと、リレーションのモデルが正しくロードされないことがあります。例えば、〶〮〳〮 アクティブ・レコード〳〳〷$orders = Order::find()->select(['id','amount'])->with('customer')->all();// この場合、$orders[0]->customer は常に `null` になります。問題を修正するためには、次のようにしなければなりません。
$orders = Order::find()->select(['id', 'amount','customer_id'])->with('customer')->all();

リレーションを使ってテーブルを結合する補足〺 この項で説明されていることは、きべこけが、ぐはびぴでひづこけがなど、 リレーショナル・データベースに対してのみ適用されます。
ここまで説明してきたリレーショナル・クエリは、主たるデータを検索する際に主テーブルのカラムだけを参照するものでした。 現実には、関連するテーブルのカラムを参照しなければならない場合がよくあります。 例えば、少なくとも一つのアクティブな注文を持つ顧客を取得したい、というような場合です。 この問題を解決するためには、以下のようにして、テーブルを結合するクエリを構築することが出来ます。
// SELECT `customer`.* FROM `customer`// LEFT JOIN `order` ON `order`.`customer_id` = `customer`.`id`// WHERE `order`.`status` = 1//// SELECT * FROM `order` WHERE `customer_id` IN (...)$customers = Customer::find()->select('customer.*')->leftJoin('order', '`order`.`customer_id` = `customer`.`id`')->where(['order.status' => Order::STATUS_ACTIVE])->with('orders')->all();

補足〺 おくぉぎ こけが 文を含むリレーショナル・クエリを構築する場合は、カラム名の曖昧さを解消することが重要です。 カラム名に対応するテーブル名をプレフィクスするのが慣例です。
しかしながら、もっと良いのは、べどどぜつぢぜぁっぴどぶづけふづひべ〺〺なはどのしどぴと〨〩 を呼んで、既にあるリレーションの宣言を利用するという手法です。
$customers = Customer::find()->joinWith('orders')->where(['order.status' => Order::STATUS_ACTIVE])->all();

どちらの方法でも、実行される こけが 文のセットは同じです。けれども、後者の方がはるかに明快で簡潔です。
デフォルトでは、なはどのしどぴと〨〩 は LEFT JOIN を使って、関連するテーブ
ルを主テーブルに結合します。 第三のパラメータ $joinType によって異な〳〳〸

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

る結合タイプ 〨例えば RIGHT JOIN〩 を指定することが出来ます。 指定したい結合タイプが INNER JOIN である場合は、代りに、どののづひおはどのしどぴと〨〩 を呼ぶだけで済ませることが出来ます。
デフォルトでは、なはどのしどぴと〨〩 を呼ぶと、リレーションのデータがイーガー・ロード されます。 リレーションのデータを読み取りたくない
場合は、第二のパラメータ $eagerLoading を false に指定することが出来ます。
補足〺 たとえイーガー・ローディングを有効にして なはどのしどぴと〨〩
や どののづひおはどのしどぴと〨〩 を使う場合でも、 リレーションのデータを取得するのには JOIN クエリの結果は使われません。 その場
合でも、やはり、イーガー・ローディング のセクションで説明したように、結合されたリレーションごとに追加のクエリが実行されます。
ぷどぴと〨〩 と同じように、一つまたは複数のリレーションを結合したり、 リ
レーションクエリをその場でカスタマイズしたり、ネストされたリレー
ションを結合したりすることが出来ます。 また、ぷどぴと〨〩 と なはどのしどぴと〨〩を混ぜて使用することも出来ます。例えば、$customers = Customer::find()->joinWith(['orders' => function ($query) {$query->andWhere(['>', 'subtotal', 100]);},])->with('country')->all();

二つのテーブルを結合するときに、結合クエリの ON の部分に追加の条件を指定する必要がある場合があるでしょう。 これは、次のように、べどどぜつぢぜぁっぴどぶづけふづひべ〺〺はのぃはのつどぴどはの〨〩 メソッドを呼ぶことによって実現できます。
// SELECT `customer`.* FROM `customer`// LEFT JOIN `order` ON `order`.`customer_id` = `customer`.`id` AND`order`.`status` = 1//// SELECT * FROM `order` WHERE `customer_id` IN (...)$customers = Customer::find()->joinWith(['orders' => function ($query) {$query->onCondition(['order.status' => Order::STATUS_ACTIVE]);},])->all();

上記のクエリは 全ての 顧客を返し、各顧客について全てのアクティブな注文を返します。 これは、少なくとも一つのアクティブな注文を持つ顧客を全て返す、という以前の例とは異なっていることに注意してください。

〶〮〳〮 アクティブ・レコード〳〳〹

情報〺 べどどぜつぢぜぁっぴどぶづけふづひべ が はのぃはのつどぴどはの〨〩 によって条件を指定された場合、 クエリが おくぉぎ 句を含む場合は、条件は ONの部分に置かれます。 クエリが おくぉぎ 句を含まない場合は、条件は自動的に WHERE の部分に追加されます。 このようにして、リレーションのテーブルのカラムを含む条件だけが ON の部分に置かれます。
リレーションのテーブルのエイリアス 前に注意したように、クエリにおくぉぎ を使うときは、カラム名の曖昧さを解消する必要があります。そのために、テーブルにエイリアスを定義することがよくあります。 リレー
ションのテーブルのためにエイリアスを設定することは、リレーショナ
ル・クエリを次のようにカスタマイズすることによっても可能です。
$query->joinWith(['orders' => function ($q) {$q->from(['o' => Order::tableName()]);},])

しかし、これでは非常に複雑ですし、リレーションオブジェクトのテー
ブル名をハードコーディングしたり、Order::tableName() を呼んだりしな
ければなりません。 バージョン 〲〮〰〮〷 以降、すどど はこれに対するショート
カットを提供しています。今では、次のようにしてリレーションのテー
ブルのエイリアスを定義して使うことが出来ます。
// orders リレーションを JOIN し、結果を orders.id でソートする$query->joinWith(['orders o'])->orderBy('o.id');

上記の文法が動作するのは単純なリレーションの場合です。ネストされたリレーションを結合する 〨例えば、$query->joinWith(['orders.product'])〩 ときに、中間テーブルのエイリアスが必要になった場合は、 次の例のように、なはどのしどぴと の呼び出しをネストさせる必要があります。
$query->joinWith(['orders o' => function($q) {$q->joinWith('product p');}])->where('o.amount > 100');

逆リレーション
リレーションの宣言は、たいていの場合、二つのアクティブ・レコー
ド・クラスの間で相互的なものになります。 例えば、Customer は orders
リレーションによって Order に関連付けられ、逆に、Order はcustomer リ
レーションによって Customer に関連付けられる、という具合です。
class Customer extends ActiveRecord{
public function getOrders()〳〴〰

ぃえぁぐごぅげ 〶〮 データベースの取り扱い{}}

return $this->hasMany(Order::class, ['customer_id' => 'id']);class Order extends ActiveRecord{
public function getCustomer(){
return $this->hasOne(Customer::class, ['id' => 'customer_id']);}}ここで、次のコード断片について考えて見てください。
// SELECT * FROM `customer` WHERE `id` = 123$customer = Customer::findOne(123);// SELECT * FROM `order` WHERE `customer_id` = 123$order = $customer->orders[0];// SELECT * FROM `customer` WHERE `id` = 123$customer2 = $order->customer;// "異なる" が表示される
echo $customer2 === $customer ? '同じ' : '異なる';

私たちは $customer と $customer2 が同じであると期待しますが、そうではありません。 実際、二つは同じ顧客データを含んでいますが、オブジェ
クトとしては異なります。 $order->customer にアクセスするときに追加のこけが 文が実行されて、新しいオブジェクトである $customer2 にデータが投入されます。
上記の例において、冗長な最後の こけが 文の実行を避けるためには、下に示すように、 どのぶづひびづくて〨〩メソッドを呼ぶことによって、customer がorders の 逆リレーション であることを すどど に教えておかなければなりま
せん。
class Customer extends ActiveRecord{
public function getOrders(){
return $this->hasMany(Order::class, ['customer_id' =>'id'])->inverseOf('customer');}}

このようにリレーションの宣言を修正すると、次の結果を得ることが出来ます。
// SELECT * FROM `customer` WHERE `id` = 123$customer = Customer::findOne(123);〶〮〳〮 アクティブ・レコード〳〴〱// SELECT * FROM `order` WHERE `customer_id` = 123$order = $customer->orders[0];// No SQL will be executed$customer2 = $order->customer;// "同じ" が表示される
echo $customer2 === $customer ? '同じ' : '異なる';

補足〺 逆リレーションは 中間テーブル を含むリレーションについては宣言することが出来ません。 つまり、リレーショ
ンが ぶどち〨〩 または ぶどちごちぢぬづ〨〩 によって定義されている場合
は、どのぶづひびづくて〨〩 を追加で呼んではいけません。

6.3.11

リレーションを保存する

リレーショナル・データを扱う時には、たいてい、さまざまなデータ間にリレーションを確立したり、既存のリレーションを破棄したりする必要があります。 そのためには、リレーションを定義するカラムの値を適切に設定することが必要です。 アクティブ・レコードを使う場合は、結局の所、次のようなコードを書くことになるでしょう。
$customer = Customer::findOne(123);$order = new Order();$order->subtotal = 100;// ...
// Order において "customer" リレーションを定義する属性の値を設定する$order->customer_id = $customer->id;$order->save();

アクティブ・レコードは、この仕事をもっと楽に達成することが出来る
ように、ぬどのに〨〩 メソッドを提供しています。
$customer = Customer::findOne(123);$order = new Order();$order->subtotal = 100;// ...
$order->link('customer', $customer);

ぬどのに〨〩 メソッドは、リレーション名と、リレーションを確立する対象のアクティブ・レコード・インスタンスを指定することを要求します。 このメソッドは、二つのアクティブ・レコード・インスタンスをリンクす
る属性の値を修正して、それをデータベースに書き込みます。 上記の例
では、Order インスタンスの customer_id 属性を Customer インスタンスの id
属性の値になるようにセットして、それをデータベースに保存します。

〳〴〲

ぃえぁぐごぅげ 〶〮 データベースの取り扱い
補足〺 二つの新規作成されたアクティブ・レコード・インスタ
ンスをリンクすることは出来ません。

ぬどのに〨〩 を使用することの利点は、リレーションが 中間テーブル によって定義されている場合に、さらに明白になります。 例えば、一つの Order
インスタンスと一つのItem インスタンスをリンクするのに、次のコードを使うことが出来ます。
$order->link('items', $item);

上記のコードによって、order_item 中間テーブルに、注文と商品を関連付けるための行が自動的に挿入されます。
情報〺 ぬどのに〨〩 メソッドは、 影響を受けるアクティブ・レコー
ド・インスタンスを保存する際に、データ検証を実行しません。 このメソッドを呼ぶ前にすべての入力値を検証することはあなたの責任です。
ぬどのに〨〩 の逆の操作が ふのぬどのに〨〩 です。 これは、既存の二つのアクティ
ブ・レコード・インスタンスのリレーションを破棄します。例えば、$customer = Customer::find()->with('orders')->where(['id' => 123])->one();$customer->unlink('orders', $customer->orders[0]);デフォルトでは、ふのぬどのに〨〩 メソッドは、 既存のリレーションを指定している外部キーの値を null に設定します。 ただし、$delete パラメータをtrue にしてメソッドに渡して、その外部キーを含むテーブル行を削除するという方法を選ぶことも出来ます。
リレーションに中間テーブルが含まれている場合は、ふのぬどのに〨〩 を呼ぶと、 中間テーブルにある外部キーがクリアされるか、または、$delete
が true であるときは、 中間テーブルにある対応する行が削除されるかします。

6.3.12DBMS 間のリレーション

アクティブ・レコードは、異なるデータベースをバックエンドに持つア
クティブ・レコードの間でリレーションを宣言することを可能にしています。 データベースは異なるタイプ 〨例えば、きべこけが と ぐはびぴでひづこけが、または、きこ こけが と きはのではいあ〩 であってもよく、別のサーバで動作していても構いません。 同じ構文を使ってリレーショナル・クエリを実行することが出来ます。例えば、// Customer はリレーショナル・データベース (例えば MySQL) の "customer" テーブルと関連付けられている
class Customer extends \yii\db\ActiveRecord{
public static function tableName()〶〮〳〮 アクティブ・レコード{

return 'customer';

}

}

〳〴〳

public function getComments(){// Customer は多くの Comment を持つ
return $this->hasMany(Comment::class, ['customer_id' => 'id']);}// Comment は MongoDb データベースの "comment" コレクションと関連付けられているclass Comment extends \yii\mongodb\ActiveRecord{
public static function collectionName(){
return 'comment';}}

public function getCustomer(){// Comment は 一つの Customer を持つ
return $this->hasOne(Customer::class, ['id' => 'customer_id']);}$customers = Customer::find()->with('comments')->all();

このセクションで説明されたリレーショナル・クエリ機能のほとんどを使用することが出来ます。
補足〺 べどどぜつぢぜぁっぴどぶづけふづひべ〺〺なはどのしどぴと〨〩 の使用は、データベース間の おくぉぎ クエリをサポートしているデータベースに限定されます。 この理由により、上記の例では joinWith メ
ソッドは使用することが出来ません。きはのではいあ は おくぉぎ をサポートしていないからです。

6.3.13

クエリ・クラスをカスタマイズする

デフォルトでは、全てのアクティブ・レコードのクエリは べどどぜつぢぜぁっぴどぶづけふづひべ
によってサポートされます。 カスタマイズされたクエリ・クラスをアク
ティブ・レコードで使用するためには、べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺てどのつ〨〩メソッドをオーバーライドして、カスタマイズされたクエリ・クラスのインスタンスを返すようにしなければなりません。例えば、// file Comment.php
namespace app\models;
use yii\db\ActiveRecord;〳〴〴

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

class Comment extends ActiveRecord{
public static function find(){
return new CommentQuery(get_called_class());}}

こ のよ うに する と 、Comment の クエ リを実行し たり 〨例え ば find() や
findOne() を呼んだり〩、Comment とのリレーションを定義したり 〨例えば
hasOne() を定義したり〩 する際には、いつでも、AcctiveQuery の代りにCommentQuery のインスタンスを使用することになります。
さて、CommentQuery クラスを定義しなければならない訳ですが、このクラスをさまざまな創造的方法でカスタマイズして、あなたのクエリ構
築作業を楽しいものにすることが出来ます。例えば、// file CommentQuery.php
namespace app\models;
use yii\db\ActiveQuery;class CommentQuery extends ActiveQuery{// デフォルトで条件を追加 (省略可)public function init(){$this->andOnCondition(['deleted' => false]);parent::init();}// ... ここにカスタマイズしたクエリ・メソッドを追加 ...

}public function active($state = true){
return $this->andOnCondition(['active' => $state]);}補足〺 新しいクエリ構築メソッドを定義するときには、通常
は、既存のどの条件も上書きしないように、 はのぃはのつどぴどはの〨〩ではなく、ちのつくのぃはのつどぴどはの〨〩 または はひくのぃはのつどぴどはの〨〩 を呼んで条件を追加しなければなりません。
このようにすると、次のようなクエリ構築のコードを書くことが出来るようになります。
$comments = Comment::find()->active()->all();$inactiveComments = Comment::find()->active(false)->all();

ヒント〺 大きなプロジェクトでは、アクティブ・レコード・クラスをクリーンに保つことが出来るように、 クエリ関連の〶〮〳〮 アクティブ・レコード〳〴〵

コードのほとんどをカスタマイズされたクエリ・クラスに保持することが推奨されます。
この新しいクエリ構築メソッドは、Comment に関するリレーションを定義するときや、リレーショナル・クエリを実行するときにも使用することが出来ます。
class Customer extends \yii\db\ActiveRecord{
public function getActiveComments(){
return $this->hasMany(Comment::class, ['customer_id' =>'id'])->active();}}$customers = Customer::find()->with('activeComments')->all();// あるいは、またclass Customer extends \yii\db\ActiveRecord{
public function getComments(){
return $this->hasMany(Comment::class, ['customer_id' => 'id']);}}$customers = Customer::find()->with(['comments' => function($q) {$q->active();}])->all();

情報〺 すどど 〱〮〱 には、スコープ と呼ばれる概念がありました。
すどど 〲〮〰 では、スコープはもはや直接にはサポートされません。 同じ目的を達するためには、カスタマイズされたクエ
リ・クラスとクエリ・メソッドを使わなければなりません。

6.3.14

追加のフィールドを選択する

アクティブ・レコードのインスタンスにクエリ結果からデータが投入されるときは、 受け取ったデータセットのカラムの値が対応する属性に入れられます。
クエリ結果から追加のカラムや値を取得して、アクティブ・レコー
ドの内部に格納することが出来ます。 例えば、ホテルの客室の情報を含む room という名前のテーブルがあるとしましょう。 そして、全ての客室のデータは length 〨長さ〩、width 〨幅〩、height 〨高さ〩 というフィールドを使って、部屋の幾何学的なサイズに関する情報を格納しているとします。 空いている全ての部屋の一覧を容積の降順で取得する必要がある〳〴〶

ぃえぁぐごぅげ 〶〮 データベースの取り扱い場合を考えて見てください。 レコードをその値で並べ替える必要がある
ので、ぐえぐ を使って容積を計算することは出来ません。 しかし、同時に、一覧には volume 〨容積〩 も表示したいでしょう。 目的を達するためには、Room アクティブ・レコード・クラスにおいて追加のフィールドを宣言し、volume の値を格納する必要があります。
class Room extends \yii\db\ActiveRecord{
public $volume;}// ...

そして、部屋の容積を計算して並べ替えを実行するクエリを構築しなけ
ればなりません。
$rooms = Room::find()->select(['{{room}}.*', // 全てのカラムを選択'([[length]] * [[width]] * [[height]]) AS volume', // 容積を計算])->orderBy('volume DESC') // 並べ替えを適用->all();
foreach ($rooms as $room) {echo $room->volume; // SQL によって計算された値を含んでいる}

追加のフィールドが選択できることは、集計クエリに対して特に有効に機能します。 注文の数とともに顧客の一覧を表示する必要がある場合を想定してください。 まず初めに、Customer クラスの中で、orders リレー
ションと、注文数を格納するための追加のフィールドを宣言しなければなりません。
class Customer extends \yii\db\ActiveRecord{
public $ordersCount;// ...

}

public function getOrders(){
return $this->hasMany(Order::class, ['customer_id' => 'id']);}そして、はひつづひ を結合して注文数を計算するクエリを構築することが出来ます。
$customers = Customer::find()->select([〶〮〳〮 アクティブ・レコード〳〴〷'{{customer}}.*', // 顧客の全てのフィールドを選択'COUNT({{order}}.id) AS ordersCount' // 注文数を計算])->joinWith('orders') // テーブルの結合を保証する->groupBy('{{customer}}.id') // 結果をグループ化して、集計関数の動作を保証する->all();

この方法を使うことの短所の一つは、情報が こけが クエリでロードされていない場合には、それを別途計算しなければならない、ということです。 従って、追加のセレクト文を持たない通常のクエリによって特定のレコードを読み出した場合には、追加のフィールドの実際の値を返すことは不可能になります。 同じことが新しく保存されたレコードでも起こります。
$room = new Room();$room->length = 100;$room->width = 50;$room->height = 2;
$room->volume; // まだ指定されていないため、この値は `null` になります。

たたでづぴ〨〩 と たたびづぴ〨〩 のマジック・メソッドを使用すれば、 プロパティの動作をエミュレートすることが出来ます。
class Room extends \yii\db\ActiveRecord{
private $_volume;
public function setVolume($volume){$this->_volume = (float) $volume;}
public function getVolume(){
if (empty($this->length) || empty($this->width) ||empty($this->height)) {return null;}
if ($this->_volume === null) {$this->setVolume($this->length * $this->width * $this->height
);
}
}
}

return $this->_volume;// ...

〳〴〸ぃえぁぐごぅげ 〶〮 データベースの取り扱い

このようにすると、こぅがぅぃご クエリによって容積が提供されていない場
合に、 モデルの他の属性を使って容積を自動的に計算することが出来ます。
集約フィールドも、同じように、定義されたリレーションを使って計算することが出来ます。
class Customer extends \yii\db\ActiveRecord{
private $_ordersCount;public function setOrdersCount($count){$this->_ordersCount = (int) $count;}public function getOrdersCount(){
if ($this->isNewRecord) {return null; // プライマリ・キーが null の場合のリレーショナル・ク
エリを防止}
if ($this->_ordersCount === null) {$this->setOrdersCount(count($this->orders)); // 要求に応じてリレーションから集約を計算}}

return $this->_ordersCount;// ...

}

public function getOrders(){
return $this->hasMany(Order::class, ['customer_id' => 'id']);}

このコードでは、〧はひつづひびぃはふのぴ〧 が だびづぬづっぴ〧 文に存在する場合は、Customer::ordersCountはクエリの結果によって投入されます。 そうでない場合は、要求に応じて、Customer::orders リレーションを使って計算されます。
マジック・メソッドによってプロパティをエミュレートする手法は、ある種のリレーショナル・データ、特に集約のショートカットを作成するためにも使用することが出来ます。 例えば、
class Customer extends \yii\db\ActiveRecord{/*** 読み出し専用の集約データの仮想プロパティを定義*/
public function getOrdersCount()〶〮〴〮 データベース・マイグレーション
{

}

〳〴〹

if ($this->isNewRecord) {return null; // プライマリ・キーが null の場合のリレーショナル・ク
エリを防止}
return empty($this->ordersAggregation) ? 0 :$this->ordersAggregation[0]['counted'];/*** 通常の 'orders' リレーションを宣言*/
public function getOrders(){
return $this->hasMany(Order::class, ['customer_id' => 'id']);}/*** 集約データを提供する新しいリレーションを 'orders' を元にして宣言*/
public function getOrdersAggregation(){
return $this->getOrders()->select(['customer_id', 'counted' => 'count(*)'])->groupBy('customer_id')->asArray(true);}}// ...

foreach (Customer::find()->with('ordersAggregation')->all() as $customer) {echo $customer->ordersCount; // イーガー・ローディングにより、追加のクエリ
なしに、リレーションから集約データを出力}$customer = Customer::findOne($pk);$customer->ordersCount; // レイジーロードされたリレーションから集約データを出
力

6.4

データベース・マイグレーション

データベース駆動型のアプリケーションを開発し保守する途上で、ソース・コードが進化するのと同じように、 使用されるデータベースの構造も進化していきます。 例えば、アプリケーションの開発中に、新しいテーブルが必要であることが分ったり、アプリケーションを配備した後に、 クエリのパフォーマンスを向上させるためにインデックスを作成すべきことが発見されたりします。 データベースの構造の変更が何らかの
ソース・コードの変更を要求する場合はよくありますから、 すどど はいわ〳〵〰

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

ゆる データベース・マイグレーション 機能を提供して、ソース・コード
とともにバージョン管理される データベース・マイグレーション の形式
でデータベースの変更を追跡できるようにしています。
下記の一連のステップは、開発中にチームによってデータベース・マ
イグレーションがどのように使用されるかを示す例です。
〱〮 ごどね が新しいマイグレーション 〨例えば、新しいテーブルを作成したり、カラムの定義を変更したりなど〩 を作る。
〲〮 ごどね が新しいマイグレーションをソース・コントロール・システム〨例えば ぇどぴ や きづひっふひどちぬ〩 にコミットする。
〳〮 いはふで がソース・コントロール・システムから自分のレポジトリを更新して新しいマイグレーションを受け取る。
〴〮 いはふで がマイグレーションを彼のローカルの開発用データベースに適用して、自分のデータベースの同期を取り、 ごどね が行った変更を反映する。
そして、次の一連のステップは、本番環境でデータベース・マイグレー
ションとともに新しいリリースを配備する方法を示すものです。
〱〮 こっはぴぴ は新しいデータベース・マイグレーションをいくつか含むプ
ロジェクトのレポジトリにリリース・タグを作成する。
〲〮 こっはぴぴ は本番サーバでソース・コードをリリース・タグまで更新する。
〳〮 こっはぴぴ は本番のデータベースに対して累積したデータベース・マイ
グレーションを全て適用する。
すどど は一連のマイグレーション・コマンドライン・ツールを提供して、以下の機能をサポートします。
• 新しいマイグレーションの作成• マイグレーションの適用• マイグレーションの取消• マイグレーションの再適用• マイグレーションの履歴と状態の表示
これらのツールは、全て、yii migrate コマンドからアクセスすることが出来ます。 このセクションでは、これらのツールを使用して、さまざ
まなタスクをどうやって達成するかを詳細に説明します。 各ツールの使用方法は、ヘルプコマンド yii help migrate によっても知ることが出来ます。
ヒント〺 マイグレーションはデータベース・スキーマに影響を及ぼすだけでなく、既存のデータを新しいスキーマに合うよ
うに修正したり、げあぁぃ 階層を作成したり、 キャッシュをク
リーンアップしたりするために使うことも出来ます。

〶〮〴〮 データベース・マイグレーション〳〵〱

補足〺 マイグレーションを使ってデータを操作する際に、作成済みのアクティブ・レコード・クラスを使えば 便利かも知れないと気が付くことがあるでしょう。なぜなら、ロジックのいくつかは既にアクティブ・レコードで実装済みなのですから。 しかしながら、永久に不変であり続けることを本質とす
るマイグレーションにおいて書かれるコードとは対照的に、
アプリケーションの ロジックは変化にさらされるものであることに留意しなければなりません。つまり、マイグレーショ
ン・コードにアクティブ・レコードを使った場合、 アクティ
ブ・レコードのレイヤにおけるロジックの変更が既存のマイグレーションを偶発的に破壊する可能性があります。この理由により、 マイグレーション・コードは、アクティブ・レ
コード・クラスなど、他のアプリケーション・ロジックから独立を保つべきです。

6.4.1

マイグレーションを作成する

新しいマイグレーションを作成するためには、次のコマンドを実行します。
yii migrate/create <name>要求される name パラメータには、マイグレーションの非常に短い説明を指定します。 例えば、マイグレーションが news という名前のテーブルを作成するものである場合は、 create_news_table という名前を使って、次のようにコマンドを実行すれば良いでしょう。
yii migrate/create create_news_table

補足〺 この name 引数は、生成されるマイグレーション・クラ
ス名の一部として使用されますので、 アルファベット、数字、および〯または、アンダースコアだけを含むものでなければなりません。
上記のコマンドは、m150101_185401_create_news_table.php という名前の新しい ぐえぐ クラス・ファイルを @app/migrations ディレクトリに作成します。
このファイルは次のようなコードを含み、主として、 スケルトン・コー
ドを持った m150101_185401_create_news_table というマイグレーション・ク
ラスを宣言するためのものす。
<?php
use yii\db\Migration;
class m150101_185401_create_news_table extends Migration{
public function up()

〳〵〲

ぃえぁぐごぅげ 〶〮 データベースの取り扱い{}
public function down(){echo "m101129_185401_create_news_table cannot be reverted.\n";}return false;/*// Use safeUp/safeDown to run migration code within a transaction
public function safeUp(){}}

public function safeDown(){}*/

各データベース・マイグレーションは べどどぜつぢぜきどでひちぴどはの から拡張した ぐえぐ クラスとして定義されます。 マイグレーション・クラスの名
前は、m<YYMMDD_HHMMSS>_<Name> という形式で自動的に生成されます。ここで、• <YYMMDD_HHMMSS> は、マイグレーション作成コマンドが実行された
さごぃ 日時を表し、• <Name> は、あなたがコマンドに与えた name 引数と同じ値になります。
マイグレーション・クラスにおいて、あなたがなすべき事は、データベースの構造に変更を加える up() メソッドにコードを書くことです。
また、up() によって加えられた変更を取り消すための down() メソッドにも、コードを書きたいと思うかもしれません。 up() メソッドは、このマイグレーションによってデータベースをアップグレードする際に呼び出され、down() メソッドはデータベースをダウングレードする際に呼び出されます。 下記のコードは、新しい news テーブルを作成するマイグレー
ション・クラスをどのようにして実装するかを示すものです。
<?php
use yii\db\Schema;
use yii\db\Migration;
class m150101_185401_create_news_table extends Migration{
public function up(){$this->createTable('news', [〶〮〴〮 データベース・マイグレーション

}

}

]);

〳〵〳

'id' => Schema::TYPE_PK,'title' => Schema::TYPE_STRING . ' NOT NULL','content' => Schema::TYPE_TEXT,

public function down(){$this->dropTable('news');}

情報〺 全てのマイグレーションが取り消し可能な訳ではありません。 例えば、up() メソッドがテーブルからある行を削除するものである場合、down() メソッドでその行を回復することは出来ません。 また、データベース・マイグレーションを取り消すことはあまり一般的ではありませんので、場合によっては、面倒くさいというだけの理由で down() を実装しないこともあるでしょう。 そういう場合は、マイグレーションが取り消し不可能であることを示すために、down() メソッドで てちぬびづを返さなければなりません。
基底のマイグレーション・クラス べどどぜつぢぜきどでひちぴどはの は、つぢ プロパティ
によって、 データベース接続にアクセスすることを可能にしています。
このデータベース接続によって、データベース・スキーマを扱う で説明されているメソッドを使い、データベース・スキーマを操作することが出来ます。
テーブルやカラムを作成するときは、物理的な型を使うのでなく、抽象型 を使って、 あなたのマイグレーションが特定の いあきこ に依存しないようにします。 べどどぜつぢぜこっとづねち クラスが、サポートされている抽象型を表す一連の定数を定義しています。 これらの定数は TYPE_<Name>という形式の名前を持っています。 例えば、TYPE_PK は、オート・イン
クリメントのプライマリ・キー型であり、TYPE_STRING は文字列型です。
これらの抽象型は、マイグレーションが特定のデータベースに適用されるときに、対応する物理型に翻訳されます。 きべこけが の場合は、TYPE_PK
は int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY に変換され、TYPE_STRING はvarchar(255) となります。
抽象型を使用するときに、付随的な制約を追加することが出来ます。
上記の例では、Schema::TYPE_STRING に NOT NULL を追加して、このカラムが のふぬぬ を許容しないことを指定しています。
情報〺 抽象型と物理型の対応関係は、それぞれの QueryBuilderの具象クラスの 〤ぴべばづきちば プロパティによって定義されています。
バージョン 〲〮〰〮〶 以降は、カラムのスキーマを定義するための更に便利な方法を提供するスキーマビルダが新たに導入されています。 したがって、上記のマイグレーションは次のように書くことが出来ます。

〳〵〴

ぃえぁぐごぅげ 〶〮 データベースの取り扱い<?php
use yii\db\Migration;
class m150101_185401_create_news_table extends Migration{
public function up(){$this->createTable('news', ['id' => $this->primaryKey(),'title' => $this->string()->notNull(),'content' => $this->text(),
]);
}

}

public function down(){$this->dropTable('news');}

カラムの型を定義するために利用できる全てのメソッドのリストは、べどど
ぜつぢぜこっとづねちあふどぬつづひごひちどぴ の ぁぐぉ ドキュメントで参照することが出来ます。
情報〺 生成されるファイルのパーミッションと所有者は現在の環境によって決定されます。 これが原因でファイルにアクセス出来ない場合が生じ得ます。例えば、つはっにづひ コン
テナ内で作成されたマイグレーションのファイルをホストで編集するとそうなる場合があります。 このような場合には
きどでひちぴづぃはのぴひはぬぬづひ の newFileMode および〯または newFileOwnershipを変更することが出来ます。 例えば、アプリケーション設定
で次のように設定します。 `ばとば 〦ぬぴ〻〿ばとば ひづぴふひの せ'controllerMap' => ['migrate' => ['class' => 'yii\console\controllers\MigrateController','newFileOwnership' => '1000:1000', # Default WSL user id'newFileMode' => 0660,
],
],

そ〻 `

6.4.2

マイグレーションを生成する

バージョン 〲〮〰〮〷 以降では、マイグレーション・コンソールがマイグレー
ションを生成する便利な方法を提供しています。
マイグレーションの名前が特別な形式である場合は、生成される
マイグレーション・ファイルに追加のコードが書き込まれます。 例え〶〮〴〮 データベース・マイグレーション〳〵〵

ば、create_xxx_table や drop_xxx_table であれば、テーブルの作成や削除をするコードが追加されます。 以下で、この機能の全ての変種を説明します。
テーブルの作成
yii migrate/create create_post_table

上記のコマンドは、次のコードを生成します。
/*** Handles the creation for table `post`.
*/class m150811_220037_create_post_table extends Migration{/*** {@inheritdoc}*/
public function up(){$this->createTable('post', ['id' => $this->primaryKey()
]);
}

}

/**
* {@inheritdoc}*/
public function down(){$this->dropTable('post');}

テーブルのフィールドも直接に生成したい場合は、--fields オプションでフィールドを指定します。
yii migrate/create create_post_table --fields="title:string,body:text"

これは、次のコードを生成します。
/*** Handles the creation for table `post`.
*/class m150811_220037_create_post_table extends Migration{/*** {@inheritdoc}*/
public function up(){$this->createTable('post', [〳〵〶

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

}

}

]);

'id' => $this->primaryKey(),'title' => $this->string(),'body' => $this->text(),/*** {@inheritdoc}*/
public function down(){$this->dropTable('post');}

さらに多くのフィールド・パラメータを指定することも出来ます。
yii migrate/create create_post_table--fields="title:string(12):notNull:unique,body:text"

これは、次のコードを生成します。
/*** Handles the creation for table `post`.
*/class m150811_220037_create_post_table extends Migration{/*** {@inheritdoc}*/
public function up(){$this->createTable('post', ['id' => $this->primaryKey(),'title' => $this->string(12)->notNull()->unique(),'body' => $this->text()
]);
}

}

/**
* {@inheritdoc}*/
public function down(){$this->dropTable('post');}補 足〺 プ ラ イ マ リ ・ キ ー が 自 動 的 に 追 加 さ れ て 、 デ フ ォ
ルトでは id と名付けられます。 別の名前を使いたい場合
は、--fields="name:primaryKey" のように、明示的に指定してください。

〶〮〴〮 データベース・マイグレーション〳〵〷

外部キー バージョン 〲〮〰〮〸 からは、foreignKey キーワードを使って外部キーを生成することができます。

yii migrate/create create_post_table--fields="author_id:integer:notNull:foreignKey(user),category_id:integer:defaultValue(1):foreignKey,title:s

これは、次のコードを生成します。
/*** Handles the creation for table `post`.
* Has foreign keys to the tables:** - `user`* - `category`*/class m160328_040430_create_post_table extends Migration{/*** {@inheritdoc}*/
public function up(){$this->createTable('post', ['id' => $this->primaryKey(),'author_id' => $this->integer()->notNull(),'category_id' => $this->integer()->defaultValue(1),'title' => $this->string(),'body' => $this->text(),]);// creates index for column `author_id`$this->createIndex('idx-post-author_id','post','author_id');// add foreign key for table `user`$this->addForeignKey('fk-post-author_id','post','author_id','user','id','CASCADE');// creates index for column `category_id`$this->createIndex('idx-post-category_id','post','category_id'
);

〳〵〸

ぃえぁぐごぅげ 〶〮 データベースの取り扱い}// add foreign key for table `category`$this->addForeignKey('fk-post-category_id','post','category_id','category','id','CASCADE');/*** {@inheritdoc}*/
public function down(){// drops foreign key for table `user`$this->dropForeignKey('fk-post-author_id','post');// drops index for column `author_id`$this->dropIndex('idx-post-author_id','post');// drops foreign key for table `category`$this->dropForeignKey('fk-post-category_id','post');// drops index for column `category_id`$this->dropIndex('idx-post-category_id','post');}}$this->dropTable('post');カラムの記述における foreignKey キーワードの位置によって、生成されるコードが変ることはありません。 つまり、
• author_id:integer:notNull:foreignKey(user)• author_id:integer:foreignKey(user):notNull• author_id:foreignKey(user):integer:notNull
これらはすべて同じコードを生成します。
foreignKey キーワードは括弧の中にパラメータを取ることが出来て、〶〮〴〮 データベース・マイグレーション〳〵〹

これが生成される外部キーの関連テーブルの名前になります。 パラメー
タが渡されなかった場合は、テーブル名はカラム名から推測されます。
上記の例で author_id:integer:notNull:foreignKey(user) は、 user テーブ
ルへの外部キーを持つ author_id という名前のカラムを生成します。 一方、category_id:integer:defaultValue(1):foreignKey は、 category テーブルへの外部キーを持つ category_id というカラムを生成します。
〲〮〰〮〱〱 以降では、foreignKey キーワードは空白で区切られた第二のパラメータを取ることが出来ます。 これは、生成される外部キーに関連づけられるカラム名を表します。 第二のパラメータが渡されなかった場合
は、カラム名はテーブル・スキーマから取得されます。 スキーマが存在しない場合や、プライマリ・キーが設定されていなかったり、複合キーであったりする場合は、デフォルト名として id が使用されます。
テーブルを削除する
yii migrate/create drop_post_table--fields="title:string(12):notNull:unique,body:text"

これは、次のコードを生成します。
class m150811_220037_drop_post_table extends Migration{
public function up(){$this->dropTable('post');}}public function down(){$this->createTable('post', ['id' => $this->primaryKey(),'title' => $this->string(12)->notNull()->unique(),'body' => $this->text()]);}

カラムを追加する
マイグレーションの名前が add_xxx_column_to_yyy_table の形式である場
合、ファイルの内容は、 必要となる addColumn と dropColumn を含むことになります。
カラムを追加するためには、次のようにします。
yii migrate/create add_position_column_to_post_table--fields="position:integer"

これが次のコードを生成します。

〳〶〰

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

class m150811_220037_add_position_column_to_post_table extends Migration{
public function up(){$this->addColumn('post', 'position', $this->integer());}}

public function down(){$this->dropColumn('post', 'position');}

次のようにして複数のカラムを指定することも出来ます。
yii migrate/create add_xxx_column_yyy_column_to_zzz_table--fields="xxx:integer,yyy:text"

カラムを削除する
マイグレーションの名前が drop_xxx_column_from_yyy_table の形式である場
合、 ファイルの内容は、必要となる addColumn と dropColumn を含むことになります。
yii migrate/create drop_position_column_from_post_table--fields="position:integer"

これは、次のコードを生成します。
class m150811_220037_drop_position_column_from_post_table extends Migration{
public function up(){$this->dropColumn('post', 'position');}}public function down(){$this->addColumn('post', 'position', $this->integer());}

中間テーブルを追加する
マイグレーションの名前が create_junction_table_for_xxx_and_yyy_tables の形式である場合は、 中間テーブルを作成するのに必要となるコードが生成されます。
yii migrate/create create_junction_table_for_post_and_tag_tables--fields="created_at:dateTime"

これは、次のコードを生成します。

〶〮〴〮 データベース・マイグレーション

〳〶〱

/**
* Handles the creation for table `post_tag`.
* Has foreign keys to the tables:** - `post`* - `tag`*/class m160328_041642_create_junction_table_for_post_and_tag_tables extends
Migration{/*** {@inheritdoc}*/
public function up(){$this->createTable('post_tag', ['post_id' => $this->integer(),'tag_id' => $this->integer(),'created_at' => $this->dateTime(),'PRIMARY KEY(post_id, tag_id)',]);// creates index for column `post_id`$this->createIndex('idx-post_tag-post_id','post_tag','post_id');// add foreign key for table `post`$this->addForeignKey('fk-post_tag-post_id','post_tag','post_id','post','id','CASCADE');// creates index for column `tag_id`$this->createIndex('idx-post_tag-tag_id','post_tag','tag_id');// add foreign key for table `tag`$this->addForeignKey('fk-post_tag-tag_id','post_tag','tag_id','tag','id','CASCADE'〳〶〲

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

}

);

/**
* {@inheritdoc}*/
public function down(){// drops foreign key for table `post`$this->dropForeignKey('fk-post_tag-post_id','post_tag');// drops index for column `post_id`$this->dropIndex('idx-post_tag-post_id','post_tag');// drops foreign key for table `tag`$this->dropForeignKey('fk-post_tag-tag_id','post_tag');// drops index for column `tag_id`$this->dropIndex('idx-post_tag-tag_id','post_tag'
);

}

}

$this->dropTable('post_tag');〲〮〰〮〱〱 以降では、中間テーブルの外部キーのカラム名はテーブル・スキー
マから取得されます。 スキーマでテーブルが定義されていない場合や、プライマリ・キーが設定されていなかったり複合キーであったりする場
合は、デフォルト名 id が使われます。
トランザクションを使うマイグレーション
複雑な一連の いあ マイグレーションを実行するときは、通常、データベースの一貫性と整合性を保つために、 各マイグレーションが全体として成功または失敗することを保証する必要があります。 この目的を達成するために、各マイグレーションの いあ 操作を トランザクション で囲む
ことが推奨されます。
トランザクションを使うマイグレーションを実装するためのもっと簡単な方法は、マイグレーションのコードを safeUp() と safeDown() のメソッ
ドに入れることです。 この二つのメソッドが up() および down() と違う点〶〮〴〮 データベース・マイグレーション〳〶〳

は、これらが暗黙のうちにトランザクションに囲まれていることです。
結果として、これらのメソッドの中で何か操作が失敗した場合は、先行する全ての操作が自動的にロールバックされます。
次の例では、news テーブルを作成するだけでなく、このテーブルに初期値となる行を挿入しています。
<?php
use yii\db\Migration;
class m150101_185401_create_news_table extends Migration{
public function safeUp(){$this->createTable('news', ['id' => $this->primaryKey(),'title' => $this->string()->notNull(),'content' => $this->text(),]);}$this->insert('news', ['title' => 'test 1','content' => 'content 1',]);

public function safeDown(){$this->delete('news', ['id' => 1]);
$this->dropTable('news');}}

通常、safeUp() で複数の いあ 操作を実行する場合は、safeDown() では実
行の順序を逆にしなければならないことに注意してください。 上記の例では、safeUp() では、最初にテーブルを作って、次に行を挿入し、safeDown() では、先に行を削除して、次にテーブルを削除しています。
補足〺 全ての いあきこ がトランザクションをサポートしている訳ではありません。また、トランザクションに入れることが出来ない いあ クエリもあります。 いくつかの例を 暗黙のコミット28 で見ることが出来ます。 その場合には、代りに、up() と down() を実装しなければなりません。
データベース・アクセス・メソッド
基底のマイグレーション・クラス べどどぜつぢぜきどでひちぴどはの は、データベースにアクセスして操作するための一連のメソッドを提供しています。 あ28https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html

〳〶〴

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

なたは、これらのメソッドが、べどどぜつぢぜぃはねねちのつ クラスによって提供される いぁく メソッド と同じような名前を付けられていることに気付くでしょう。 例えば、べどどぜつぢぜきどでひちぴどはの〺〺っひづちぴづごちぢぬづ〨〩 メソッドは、べどど
ぜつぢぜぃはねねちのつ〺〺っひづちぴづごちぢぬづ〨〩 と全く同じように、 新しいテーブルを作成します。
べどどぜつぢぜきどでひちぴどはの によって提供されているメソッドを使うことの利
点は、べどどぜつぢぜぃはねねちのつ インスタンスを明示的に作成する必要がないこと、そして、各メソッドを実行すると、 どのようなデータベース操作がどれだけの時間をかけて実行されたかを教えてくれる有益なメッセージ
が自動的に表示されることです。
以下がそういうデータベース・アクセス・メソッドの一覧です。
• づへづっふぴづ〨〩〺 こけが 文を実行
• どのびづひぴ〨〩〺 一行を挿入• ぢちぴっとぉのびづひぴ〨〩〺 複数行を挿入• ふばつちぴづ〨〩〺 行を更新
• ふばびづひぴ〨〩〺 一行を挿入または既に存在していれば更新 〨〲〮〰〮〱〴 以降〩• つづぬづぴづ〨〩〺 行を削除
• っひづちぴづごちぢぬづ〨〩〺 テーブルを作成• ひづのちねづごちぢぬづ〨〩〺 テーブルの名前を変更• つひはばごちぢぬづ〨〩〺 テーブルを削除• ぴひふのっちぴづごちぢぬづ〨〩〺 テーブル中の全ての行を削除• ちつつぃはぬふねの〨〩〺 カラムを追加• ひづのちねづぃはぬふねの〨〩〺 カラムの名前を変更• つひはばぃはぬふねの〨〩〺 カラムを削除• ちぬぴづひぃはぬふねの〨〩〺 カラムの定義を変更• ちつつぐひどねちひべかづべ〨〩〺 プライマリ・キーを追加• つひはばぐひどねちひべかづべ〨〩〺 プライマリ・キーを削除• ちつつうはひづどでのかづべ〨〩〺 外部キーを追加• つひはばうはひづどでのかづべ〨〩〺 外部キーを削除• っひづちぴづぉのつづへ〨〩〺 インデックスを作成• つひはばぉのつづへ〨〩〺 インデックスを削除• ちつつぃはねねづのぴくのぃはぬふねの〨〩〺 カラムにコメントを追加• つひはばぃはねねづのぴうひはねぃはぬふねの〨〩〺 カラムからコメントを削除• ちつつぃはねねづのぴくのごちぢぬづ〨〩〺 テーブルにコメントを追加• つひはばぃはねねづのぴうひはねごちぢぬづ〨〩〺 テーブルからコメントを削除
情報〺 べどどぜつぢぜきどでひちぴどはの は、データベース・クエリ・メソッドを提供しません。 これは、通常、データベースからのデー
タ取得については、メッセージを追加して表示する必要がないからです。 更にまた、複雑なクエリを構築して実行するためには、強力な クエリ・ビルダ を使うことが出来るからです。 マイグレーションの中でクエリ・ビルダを使うと、次のようなコードになります。
// 全ユーザについて、status フィールドを更新する〶〮〴〮 データベース・マイグレーション〳〶〵

foreach((new Query)->from('users')->each() as $user) {$this->update('users', ['status' => 1], ['id' => $user['id']]);
}

6.4.3

マイグレーションを適用する

データベースを最新の構造にアップグレードするためには、利用できる
全ての新しいマイグレーションを適用するために、次のコマンドを使わなければなりません。
yii migrate

コマンドを実行すると、まだ適用されていない全てのマイグレーションが一覧表示されます。 リストされたマイグレーションを適用することをあなたが確認すると、タイムスタンプの値の順に、一つずつ、 すべての新しいマイグレーション・クラスの up() または safeUp() メソッドが実行されます。 マイグレーションのどれかが失敗した場合は、コマンドは残りのマイグレーションを適用せずに終了します。
ヒント〺 あなたのサーバでコマンドラインを使用できない場合
は ぷづぢ びとづぬぬ29 エクステンションを使ってみてください。
適用が成功したマイグレーションの一つ一つについて、migration という名前のデータベース・テーブルに行が挿入されて、 マイグレーションの成功が記録されます。この記録によって、マイグレーション・ツール
は、どのマイグレーションが適用され、 どのマイグレーションが適用されていないかを特定することが出来ます。
情報〺 マイグレーション・ツールは、コマンドの つぢ オプショ
ンで指定されたデータベースに migration テーブルを自動的に作成します。デフォルトでは、このデータベースは db アプリ
ケーション・コンポーネント によって指定されます。
時として、利用できる全てのマイグレーションではなく、一つまたは数個の新しいマイグレーションだけを適用したい場合があります。 コマン
ドを実行するときに、適用したいマイグレーションの数を指定することによって、そうすることが出来ます。 例えば、次のコマンドは、次の三個の利用できるマイグレーションを適用しようとするものです。
yii migrate 3

また、そのマイグレーションまでをデータベースに適用するという、特定のマイグレーションを明示的に指定することも出来ます。 そのためには、migrate/to コマンドを、次のどれかの形式で使います。
29

https://github.com/samdark/yii2-webshell〳〶〶

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

yii migrate/to 150101_185401
イグレーションを指定
yii migrate/to "2015-01-01 18:54:01"
できる文字列を使用
yii migrate/to m150101_185401_create_news_tableyii migrate/to 1392853618# タイムスタンプを使ってマ# strtotime() によって解釈# フルネームを使用# UNIX タイムスタンプを使用指定されたマイグレーションよりも古いものが適用されずに残っている
場合は、指定されたものが適用される前に、 すべて適用されます。
指定されたマイグレーションが既に適用済みである場合、それより新しいものが適用されていれば、すべて取り消されます。

6.4.4

マイグレーションを取り消す

適用済みのマイグレーションを一個または複数個取り消したい場合は、下記のコマンドを使うことが出来ます。
yii migrate/down
yii migrate/down 3# 最近に適用されたマイグレーション一個を取り消す# 最近に適用されたマイグレーション三個を取り消す

補足〺 全てのマイグレーションが取り消せるとは限りません。
そのようなマイグレーションを取り消そうとするとエラーとなり、取り消しのプロセス全体が終了させられます。

6.4.5

マイグレーションを再適用する

マイグレーションの再適用とは、指定されたマイグレーションを最初に取り消してから、再度適用することを意味します。 これは次のコマンドによって実行することが出来ます。
yii migrate/redo
yii migrate/redo 3# 最後に適用された一個のマイグレーションを再適用する# 最後に適用された三個のマイグレーションを再適用する

補足〺 マイグレーションが取り消し不可能な場合は、それを再適用することは出来ません。

6.4.6

マイグレーションをリフレッシュする

すどど 〲〮〰〮〱〳 以降、データベースから全てのテーブルと外部キーを削除して、全てのマイグレーションを最初から再適用することが出来ます。
yii migrate/fresh
ら適用する# データベースを削除し、全てのマイグレーションを最初か〳〶〷〶〮〴〮 データベース・マイグレーション

6.4.7

マイグレーションをリスト表示する

どのマイグレーションが適用済みであり、どのマイグレーションが未適用であるかをリスト表示するために、次のコマンドを使うことが出来ます。
yii migrate/history# 最後に適用された 10 個のマイグレーションを表示
yii migrate/history 5# 最後に適用された 5 個のマイグレーションを表示
yii migrate/history all # 適用された全てのマイグレーションを表示
yii migrate/new
yii migrate/new 5
yii migrate/new all

6.4.8# 適用可能な最初の 10 個のマイグレーションを表示# 適用可能な最初の 5 個のマイグレーションを表示# 適用可能な全てのマイグレーションを表示

マイグレーション履歴を修正する時として、実際にマイグレーションを適用したり取り消したりするのではなく、 データベースが特定のマイグレーションまでアップグレードされたとマークしたいだけ、という場合があります。 このようなことがよ
く起るのは、データベースを手作業で特定の状態に変更した後に、その変更のための一つまたは複数のマイグレーションを記録はするが再度適用はしたくない、という場合です。 次のコマンドでこの目的を達することが出来ます。
yii migrate/mark 150101_185401
マイグレーションを指定
yii migrate/mark "2015-01-01 18:54:01"
釈できる文字列を使用
yii migrate/mark m150101_185401_create_news_tableyii migrate/mark 1392853618
用# タイムスタンプを使って# strtotime() によって解# フルネームを使用# UNIX タイムスタンプを使

このコマンドは、一定の行を追加または削除して、migration テーブルを修正し、データベースが指定されたものまでマイグレーションが適用済
みであることを示します。 このコマンドによってマイグレーションが適用されたり取り消されたりはしません。

6.4.9

マイグレーションをカスタマイズする

マイグレーションコマンドをカスタマイズする方法がいくつかあります。
コマンドライン・オプションを使う
マイグレーション・コマンドには、その動作をカスタマイズするために使うことが出来るコマンドライン・オプションがいくつかあります。

〳〶〸ぃえぁぐごぅげ 〶〮 データベースの取り扱い• interactive〺 真偽値 〨デフォルト値は ぴひふづ〩。マイグレーションを対話モードで実行するかどうかを指定します。 ぴひふづ である場合は、コ
マンドが何らかの操作を実行する前に、ユーザは確認を求められます。 コマンドがバックグラウンドのプロセスで使用される場合は、
このオプションを てちぬびづ にセットします。
• migrationPath〺 文字列 〨デフォルト値は @app/migrations〩。 全てのマ
イグレーション・クラス・ファイルを保存しているディレクトリを指定します。 この値は、ディレクトリ・パスか、パス・エイリアスとして指定することが出来ます。 ディレクトリが存在する必要があり、そうでなければコマンドがエラーを発生させることに注意してください。
• migrationTable〺 文字列 〨デフォルト値は migration〩。マイグレーショ
ン履歴の情報を保存するためのデータベース・テーブル名を指定します。 テーブルが存在しない場合は、コマンドによって自動的に作成されます。 version varchar(255) primary key, apply_time integer という構造のテーブルを手作業で作成しても構いません。
• db〺 文字列 〨デフォルト値は db〩。データベース アプリケーション・
コンポーネント の ぉい を指定します。 このコマンドによってマイグ
レーションを適用されるデータベースを表します。
• templateFile〺 文字列 〨デフォルト値は @yii/views/migration.php〩。 ス
ケルトンのマイグレーション・クラス・ファイルを生成するために使用されるテンプレート・ファイルのパスを指定します。 この値は、ファイル・パスか、パス エイリアス として指定することが出来ます。 テンプレート・ファイルは ぐえぐ スクリプトであり、その中で、マイグレーション・クラスの名前を取得するための$className という事前定義された変数を使うことが出来ます。
• generatorTemplateFiles〺 配列 〨デフォルト値は だせ'create_table' => '@yii/views/createTableMigration.php','drop_table' => '@yii/views/dropTableMigration.php','add_column' => '@yii/views/addColumnMigration.php','drop_column' => '@yii/views/dropColumnMigration.php','create_junction' => '@yii/views/createTableMigration.php'

そだ〩。マイグレーション・コードを生成するためのテンプレート・
ファイルを指定します。 詳細は 【マイグレーションを生成する【 を参照してください。
• fields〺 マイグレーション・コードを生成するためのカラム定義文字列の配列。 デフォルト値は []。個々の定義の書式は COLUMN_NAME:COLUMN_TYPE:COLUMN_DECORAです。 例えば、--fields=name:string(12):notNull は、サイズが 〱〲 ののふぬぬ でない文字列カラムを作成します。
次の例は、これらのオプションの使い方を示すものです。
例えば、forum モジュールにマイグレーションを適用しようとしており、 そのマイグレーション・ファイルがモジュールの migrations ディレ
クトリに配置されている場合、 次のコマンドを使うことが出来ます。
# forum モジュールのマイグレーションを非対話的に適用する〶〮〴〮 データベース・マイグレーション〳〶〹yii migrate --migrationPath=@app/modules/forum/migrations --interactive=0

コマンドをグローバルに構成する
マイグレーション・コマンドを実行するたびに同じオプションの値を入力する代りに、次のように、 アプリケーションの構成情報でコマンドを一度だけ構成して済ませることが出来ます。
return ['controllerMap' => ['migrate' => ['class' => 'yii\console\controllers\MigrateController','migrationTable' => 'backend_migration',
],
],
];

上記のように構成しておくと、migrate コマンドを実行するたびに、
backend_migration テーブルがマイグレーション履歴を記録するために使われるようになります。 もう、migrationTable のコマンドライン・オプションを使ってテーブルを指定する必要はなくなります。
名前空間を持つマイグレーション〲〮〰〮〱〰 以降では、マイグレーションのクラスに名前空間を適用することが出来ます。 マイグレーションの名前空間のリストをを ねどでひちぴどはのぎちねづびばちっづび
によって指定することが出来ます。 マイグレーションのクラスに名前空間を使うと、マイグレーションのソースについて、複数の配置場所を使用することが出来ます。例えば、return ['controllerMap' => ['migrate' => ['class' => 'yii\console\controllers\MigrateController','migrationPath' => null, // app\migrations が下記にあげられている
場合に、名前空間に属さないマイグレーションを無効化する'migrationNamespaces' => ['app\migrations', // アプリケーション全体のための共通のマイグ
レーション'module\migrations', // プロジェクトの特定のモジュールのための
マイグレーション'some\extension\migrations', // 特定のエクステンションのためのマイグレーション
],
],
],
];

補足〺 異なる名前空間に属するマイグレーションを適用しても、単一の マイグレーション履歴が生成されます。 つまり、

〳〷〰

ぃえぁぐごぅげ 〶〮 データベースの取り扱い
特定の名前空間に属するマイグレーションだけを適用したり元に戻したりすることは出来ません。

名前空間を持つマイグレーションを操作するときは、新規作成時も、元に戻すときも、マイグレーション名の前にフルパスの名前空間を指定しなければなりません。 バック・スラッシュ 〨\〩 のシンボルは、通常、シェルでは特殊文字として扱われますので、シェルのエラーや誤った動作を防止するために、 適切にエスケープしなければならないことに注意して下さい。例えば、
yii migrate/create app\\migrations\\createUserTable

補足〺 ねどでひちぴどはのぐちぴと によって指定されたマイグレーション
は、 名前空間を持つことが出来ません。 名前空間を持つマイグレーションは べどどぜっはのびはぬづぜっはのぴひはぬぬづひびぜきどでひちぴづぃはのぴひはぬぬづひ〺〺〤ねどでひちぴどはのぎちねづびばちっづび プロパティを通じてのみ適用可能です。
バージョン 〲〮〰〮〱〲 以降は ねどでひちぴどはのぐちぴと プロパティは 名前空間を持たないマイグレーションを含む複数のディレクトリを指定した配列を受け入れるようになりました。 この機能追加は、主として、いろんな場所にあるマイグレーションを使っている既存のプロジェクトによって使われることを意図しています。 これらのマイグレーションは、主として、他の開発者による すどど エクステンションなど、外部ソースに由来するものであり、 新しい手法を使い始めようとしても、名前空間を使うように変更することが簡単には出来ないものだからです。
名前空間を持つマイグレーションを生成する 名前空間を持つマイグレーションは 【ぃちねづぬぃちびづ】 の命名規則 M<YYMMDDHHMMSS><Name> 〨例えば
M190720100234CreateUserTable〩 を持ちます。 このようなマイグレーションを生成するときは、テーブル名が 【ぃちねづのぃちびづ】 形式から 【アンダースコア】 形式に変換されることを 覚えておいて下さい。例えば、
yii migrate/create app\\migrations\\DropGreenHotelTable

上記のコマンドは、名前空間 app\migrations の中で、green_hotel というテーブルを削除するマイグレーションを生成します。そして、
yii migrate/create app\\migrations\\CreateBANANATableというコマンドは、名前空間 app\migrations の中で b_a_n_a_n_a というテーブルを作成するマイグレーションを生成します。
テーブル名が大文字と小文字を含む（例えば studentsExam〩 ときは、名前の先頭にアンダースコアを付ける必要があります。
yii migrate/create app\\migrations\\Create_studentsExamTable

このコマンドは、名前空間 app\migrations の中で studentsExam というテーブルを作成するマイグレーションを生成します。

〶〮〴〮 データベース・マイグレーション〳〷〱分離されたマイグレーション
プロジェクトのマイグレーション全体に単一のマイグレーション履歴を使用することが望ましくない場合もあります。 例えば、完全に独立した機能性とそれ自身のためのマイグレーションを持つような だぢぬはで〧 エクス
テンションをインストールする場合には、 メインのプロジェクトの機能
専用のマイグレーションに影響を与えたくないでしょう。
これらをお互いに完全に分離して適用かつ追跡したい場合は、別々の名前空間とマイグレーション履歴テーブルを使う 複数のマイグレーショ
ンコマンドを構成することが出来ます。
return ['controllerMap' => [// アプリケーション全体のための共通のマイグレーション'migrate-app' => ['class' => 'yii\console\controllers\MigrateController','migrationNamespaces' => ['app\migrations'],'migrationTable' => 'migration_app','migrationPath' => null,],// 特定のモジュールのためのマイグレーション'migrate-module' => ['class' => 'yii\console\controllers\MigrateController','migrationNamespaces' => ['module\migrations'],'migrationTable' => 'migration_module','migrationPath' => null,],// 特定のエクステンションのためのマイグレーション'migrate-rbac' => ['class' => 'yii\console\controllers\MigrateController','migrationPath' => '@yii/rbac/migrations','migrationTable' => 'migration_rbac',
],
],
];

データベースを同期するためには、一つではなく複数のコマンドを実行しなければならなくなることに注意してください。
yii migrate-app
yii migrate-moduleyii migrate-rbac

6.4.10

複数のデータベースにマイグレーションを適用する

デフォルトでは、マイグレーションは db アプリケーション・コンポーネント によって指定された同じデータベースに対して適用されます。 マイ
グレーションを別のデータベースに適用したい場合は、次のように、db
コマンドライン・オプションを指定することが出来ます。
yii migrate --db=db2

〳〷〲

ぃえぁぐごぅげ 〶〮 データベースの取り扱い

上記のコマンドはマイグレーションを db2 データベースに適用します。
場合によっては、いくつかの マイグレーションはあるデータベースに適用し、別のいくつかの マイグレーションはもう一つのデータベースに適用したい、ということがあります。 この目的を達するためには、マイグレーション・クラスを実装する時に、そのマイグレーションが使用する いあ コンポーネントの ぉい を明示的に指定しなければなりません。 例
えば、次のようにします。
<?php
use yii\db\Migration;
class m150101_185401_create_news_table extends Migration{
public function init(){$this->db = 'db2';
parent::init();}}

上記のマイグレーションは、db コマンドライン・オプションで別のデー
タベースを指定した場合でも、db2 に対して適用されます。 ただし、マイグレーション履歴は、db コマンドライン・オプションで指定されたデー
タベースに記録されることに注意してください。
同じデータベースを使う複数のマイグレーションがある場合は、上記の init() コードを持つ基底のマイグレーション・クラスを作成することを推奨します。 そうすれば、個々のマイグレーション・クラスは、その基底クラスから拡張することが出来ます。
ヒント〺 異なるデータベースを操作するためには、つぢ プロパ
ティを設定する以外にも、 マイグレーション・クラスの中で新しいデータベース接続を作成するという方法があります。
そうすれば、そのデータベース接続で いぁく メソッド を使って、違うデータベースを操作することが出来ます。
複数のデータベースに対してマイグレーションを適用するために採用できるもう一つの戦略としては、異なるデータベースに対するマイグレー
ションは異なるマイグレーションパスに保持する、というものがあります。 そうすれば、次のように、異なるデータベースのマイグレーション
を別々のコマンドで適用することが出来ます。
yii migrate --migrationPath=@app/migrations/db1 --db=db1
yii migrate --migrationPath=@app/migrations/db2 --db=db2...

最初のコマンドは @app/migrations/db1 にあるマイグレーションを db1 デー
タベースに適用し、 第二のコマンドは @app/migrations/db2 にあるマイグ
レーションを db2 データベースに適用する、という具合です。

Chapter 7

ユーザからのデータ取得
7.1

フォームを作成する

7.1.1

アクティブ・レコードに基づくフォーム : ActiveForm

すどど においてフォームを使用するときは、主として べどどぜぷどつでづぴびぜぁっぴどぶづうはひね
による方法を使います。 フォームがモデルに基づくものである場合はこの方法を選ぶべきです。 これに加えて、べどどぜとづぬばづひびぜえぴねぬ にはいくつかの有用なメソッドがあり、どんなフォームでも、ボタンやヘルプ・テキ
ストを追加するのには、通常、それらのメソッドを使います。
フォームは、クライアント・サイドで表示されるものですが、たいていの場合、対応する モデル を持ち、それを使ってサーバ・サイドでフォームの入力を検証します 〨入力の検証の詳細については、入力を検証
する のセクションを参照してください〩。 モデルに基づくフォームを作成する場合、最初のステップは、モデルそのものを定義することです。
モデルは、データベースの何らかのデータを表現するために アクティ
ブ・レコード から派生させたクラスか、 あるいは、任意の入力、例えば
ログイン・フォームの入力を保持するための 〨べどどぜぢちびづぜきはつづぬ から派生させた〩 汎用的な きはつづぬ クラスか、どちらかにすることが出来ます。
ヒント〺 フォームのフィールドがデータベースのカラムと異なっていたり、そのフォーム特有のフォーマット形式やロジックがあったりする場合は、 べどどぜぢちびづぜきはつづぬ を拡張した独自のモデルを作るほうを選んで下さい。
以下の例においては、ログイン・フォームのために汎用的なモデルを使う方法を示します。
<?phpclass LoginForm extends \yii\base\Model{public $username;public $password;

〳〷〳

〳〷〴

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得

public function rules(){return [// 検証規則をここで定義];}

コントローラにおいて、このモデルのインスタンスをビューに渡し、ビューでは ぁっぴどぶづうはひね ウィジェットがフォームを表示するのに使われます。
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;$form = ActiveForm::begin(['id' => 'login-form','options' => ['class' => 'form-horizontal'],]) ?><? = $form->field($model, 'username') ?><? = $form->field($model, 'password')->passwordInput() ?><div class="form-group"><div class="col-lg-offset-1 col-lg-11"><? = Html::submitButton('ログイン', ['class' => 'btn
btn-primary']) ?></div></div><?php ActiveForm::end() ?>と で囲む
上記のコードでは、ぁっぴどぶづうはひね〺〺ぢづでどの〨〩 がフォームのインスタンスを作成するとともに、フォームの開始をマークしています。 ぁっぴどぶづうはひね〺〺ぢづでどの〨〩 と ぁっぴどぶづうはひね〺〺づのつ〨〩 の間に置かれた全てのコンテントがえごきが の <form> タグによって囲まれます。 どのウィジェットでも同じですが、ウィジェットをどのように構成すべきかに関するオプションを指定するために、begin メソッドに配列を渡すことが出来ます。 この例では、追加の ぃここ クラスと要素を特定するための ぉい が渡されて、<form>の開始タグに適用されています。 利用できるオプションの全ては べどど
ぜぷどつでづぴびぜぁっぴどぶづうはひね の ぁぐぉ ドキュメントに記されていますので参照してください。
ぁっぴどぶづうどづぬつ
フォームの中では、フォームの要素を作成するために、ぁっぴどぶづうはひね ウィジェットの ぁっぴどぶづうはひね〺〺てどづぬつ〨〩 メソッドが呼ばれています。 このメ
ソッドは、フォームの要素だけでなく、そのラベルも作成し、適用でき〷〮〱〮 フォームを作成する〳〷〵

る おちぶちこっひどばぴ の検証メソッドがあれば、それも追加します。ぁっぴどぶづうはひね〺〺てどづぬつ〨〩 メソッドは、 べどどぜぷどつでづぴびぜぁっぴどぶづうどづぬつ のインスタンスを返します。このメソッドの呼び出し結果を直接にエコーすると、結果は通常の 〨ぴづへぴ の〩 インプットになります。 このメソッドの呼び出しに追加のぁっぴどぶづうどづぬつ のメソッドをチェーンして、出力結果をカスタマイズすることが出来ます。
// パスワードのインプット<?= $form->field($model, 'password')->passwordInput() ?>// ヒントとカスタマイズしたラベルを追加<? = $form->field($model, 'username')->textInput()->hint('お名前を入力してください')->label('お名前') ?>// HTML5 のメール・インプット要素を作成<? = $form->field($model, 'email')->input('email') ?>これで、フォームのフィールドによって定義された テンプレート に従って、<label>、<input> など、全てのタグが生成されます。 インプット・フィールドの名前は、モデルの フォーム名 と属性から自動的に決定されます。 例えば、上記の例における username 属性のインプット・フィー
ルドの名前は LoginForm[username] となります。 この命名規則の結果として、ログイン・フォームの全ての属性が配列として、サーバ・サイドにおいては $_POST['LoginForm'] に格納されて利用できることになります。
ヒント〺 一つのフォームに一つのモデルだけがある場合、インプットの名前を単純化したいときは、 モデルの てはひねぎちねづ〨〩
メソッドをオーバーライドして空文字列を返すようにして、配列の部分をスキップすることが出来ます。 この方法を使え
ば、ぇひどつざどづぷ で使われるフィルター・モデルで、もっと見栄
えの良い さげが を生成させることが出来ます。
モデルの属性を指定するために、もっと洗練された方法を使うことも出来ます。 例えば、複数のファイルをアップロードしたり、複数の項目を選択したりする場合に、属性の名前に [] を付けて、 属性が配列の値を取り得ることを指定することが出来ます。
// 複数のファイルのアップロードを許可する
echo $form->field($model,'uploadFile[]')->fileInput(['multiple'=>'multiple']);// 複数の項目をチェックすることを許可する
echo $form->field($model, 'items[]')->checkboxList(['a' => 'Item A', 'b' =>'Item B', 'c' => 'Item C']);

送信ボタンなどのフォーム要素に名前をつけるときには注意が必要です。 なけふづひべ ドキュメント1 によれば、衝突を生じさせ得る予約された名前がいくつかあります。
1

https://api.jquery.com/submit/〳〷〶

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得
フォームおよびフォームの子要素は、フォームのプロパティと衝突するインプット名や どつ、たとえば submit、length、methodなどを使ってはなりません。 名前の衝突は訳の分らない失敗を生じさせることがあります。 命名規則の完全なリストを知り、この問題についてあなたのマークアップをチェックする
ためには、いくきがどのぴ2 を参照してください。

フォームに えごきが タグを追加するためには、素の えごきが を使うか、または、上記の例の えぴねぬ〺〺びふぢねどぴあふぴぴはの〨〩 のように、 えぴねぬ ヘルパ・クラ
スのメソッドを使うことが出来ます。
ヒント〺 あなたのアプリケーションで ごぷどぴぴづひ あははぴびぴひちば ぃここを使っている場合は、べどどぜぷどつでづぴびぜぁっぴどぶづうはひね の代りに べどど
ぜぢははぴびぴひちばぜぁっぴどぶづうはひね を使うのが良いでしょう。 後者は前者の拡張であり、ぢははぴびぴひちば ぃここ フレームワークで使用するための追加のスタイルをサポートしています。
ヒント〺 必須フィールドをアスタリスク付きのスタイルにする
ために、次の ぃここ を使うことが出来ます。
div.required label.control-label:after {content: " *";color: red;
}

7.1.2

リストを作る

三種類のリストがあります〺• ドロップダウン・リスト• ラジオ・リスト• チェックボックス・リスト
リストを作るためには、項目の配列を準備しなければなりません。これは、手作業でやることも出来ます。
$items = [1 => '項目 1',
2 => '項目 2']

または、いあ から取得することも出来ます。
$items = Category::find()->select(['label'])->indexBy('id')->column();

このような $items が、いろんなリスト・ウィジェットによって処理されるべきものとなります。 フォームのフィールドの値〨および現在アクティ
ブな項目〩は、 $model の属性の現在の値に従って自動的に設定されます。
2https://kangax.github.io/domlint/〷〮〱〮 フォームを作成する〳〷〷

ドロップダウン・リストを作る ぁっぴどぶづうどづぬつ の べどどぜぷどつでづぴびぜぁっぴどぶづうどづぬつ〺〺つひはばいはぷのがどびぴ〨〩 メソッドを使って、ドロップダウン・リストを作ることが出来ます。
/* @var $form yii\widgets\ActiveForm */echo $form->field($model, 'category')->dropdownList([
1 => '項目 1',
2 => '項目 2'],['prompt'=>'カテゴリーを選択してください']);

ラジオ・リストを作る ぁっぴどぶづうどづぬつ の べどどぜぷどつでづぴびぜぁっぴどぶづうどづぬつ〺〺ひちつどはがどびぴ〨〩
メソッドを使ってラジオ・リストを作ることが出来ます。
/* @var $form yii\widgets\ActiveForm */echo $form->field($model, 'category')->radioList([
1 => 'ラジオ 1',
2 => 'ラジオ 2']);

チェックボックス・リストを作る ぁっぴどぶづうどづぬつ の べどどぜぷどつでづぴびぜぁっぴどぶづうどづぬつ〺〺っとづっにぢはへがどびぴ〨〩 メソッドを使ってチェックボックス・リストを作ることが出来ます。
/* @var $form yii\widgets\ActiveForm */echo $form->field($model, 'category')->checkboxList([
1 => 'チェックボックス 1',
2 => 'チェックボックス 2'
]);

7.1.3

Pjax を使う

ぐなちへ ウィジェットを使うと、ページ全体をリロードせずに、 ページの一部分だけを更新することが出来ます。 これを使うと、送信後にフォームだけを更新して、その中身を入れ替えることが出来ます。
〤てはひねこづぬづっぴはひ を構成すると、どのフォームの送信が ばなちへ を起動するかを指定することが出来ます。 それが指定されていない場合は、ぐなちへに囲まれたコンテントの中にあって data-pjax 属性を持つすべてのフォー
ムが ばなちへ リクエストを起動することになります。
use yii\widgets\Pjax;
use yii\widgets\ActiveForm;
Pjax::begin([// Pjax のオプション

〳〷〸
]);

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得$form = ActiveForm::begin(['options' => ['data' => ['pjax' => true]],// ActiveForm の追加のオプション]);// ActiveForm のコンテント

ActiveForm::end();
Pjax::end();

ヒント〺 ぐなちへ ウィジェット内部のリンクに注意してください。 と言うのは、リンクに対するレスポンスもウィジェッ
ト内部でレンダリングされるからです。 これを防ぐためには、data-pjax="0" という えごきが 属性を使用します。
送信ボタンの値とファイルのアップロード jQuery.serializeArray() については、 ファイル3 および 送信ボタンの値4 を扱うときに問題があることが知られています。 この問題は解決される見込みがなく、関数自体もえごきが〵 で導入された FormData クラスによって置き換えられるべきものとして、廃止予定となっています。
このことは、すなわち、ちなちへ または ぐなちへ ウィジェットを使う場合、ファイルと送信ボタンの値に対する唯一の公式なサポートは、 FormData
クラスに対する ブラウザのサポート5 に依存しているということを意味
します。

7.1.4

さらに読むべき文書

次のセクション 入力を検証する は、送信されたフォームデータのサー
バ・サイドでの検証と、ちなちへ 検証およびクライアント・サイドでの検証を扱います。
フォームのもっと複雑な使用方法については、以下のセクションを読んで下さい。
• 表形式インプットのデータ収集 〭 同じ種類の複数のモデルのデータを収集する。
• 複数のモデルのデータを取得する 〭 同じフォームの中で複数の異なるモデルを扱う。
• ファイルをアップロードする 〭 フォームを使ってファイルをアップロードする方法。
https://github.com/jquery/jquery/issues/2321
https://github.com/jquery/jquery/issues/2321
5
https://developer.mozilla.org/ja/docs/Web/API/FormData#%E3%83%96%E3%83%
A9%E3%82%A6%E3%82%B6%E5%AE%9F%E8%A3%85%E7%8A%B6%E6%B3%81
34〷〮〲〮 入力を検証する

7.2

〳〷〹

入力を検証する経験則として言えることは、エンド・ユーザから受信したデータは決して信用せず、 利用する前に検証しなければならない、ということです。
モデル にユーザの入力が投入されたら、モデルの べどどぜぢちびづぜきはつづぬ〺〺
ぶちぬどつちぴづ〨〩 メソッドを呼んで入力を検証することが出来ます。 このメ
ソッドは検証が成功したか否かを示す真偽値を返します。 検証が失敗した場合は、べどどぜぢちびづぜきはつづぬ〺〺〤づひひはひび プロパティからエラー・メッセー
ジを取得することが出来ます。例えば、$model = new \app\models\ContactForm();// モデルの属性にユーザ入力を投入する$model->load(\Yii::$app->request->post());// これは次と等価// $model->attributes = \Yii::$app->request->post('ContactForm');
if ($model->validate()) {// 全ての入力が有効} else {// 検証が失敗。$errors はエラー・メッセージを含む配列$errors = $model->errors;
}

7.2.1

規則を宣言する

validate() を現実に動作させるためには、検証する予定の属性に対して検証規則を宣言しなければなりません。 規則は べどどぜぢちびづぜきはつづぬ〺〺
ひふぬづび〨〩 メソッドをオーバーライドすることで宣言します。 次の例
は、ContactForm モデルに対して検証規則を宣言する方法を示すものです。
public function rules(){return [// 名前、メール・アドレス、主題、本文が必須項目[['name', 'email', 'subject', 'body'], 'required'],}];// email 属性は有効なメール・アドレスでなければならない['email', 'email'],

ひふぬづび〨〩 メソッドは規則の配列を返すべきものですが、 その配列の各要
素は次の形式の配列でなければなりません。
[// 必須。この規則によって検証されるべき属性を指定する。
// 属性が一つだけの場合は、属性の名前を直接に書いてもよい。
// (配列の中に入れずに)〳〸〰

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得['属性1', '属性2', ...],// 必須。この規則のタイプを指定する。
// クラス名、バリデータのエイリアス、または、バリデーション・メソッドの名前。
'バリデータ',// オプション。この規則が適用されるべき一つまたは複数のシナリオを指定する。
// 指定しない場合は、この規則が全てのシナリオに適用されることを意味する。
// "except" オプションを構成して、列挙したシナリオを除く全てのシナリオに// この規則が適用されるべきことを指定してもよい。
'on' => ['シナリオ1', 'シナリオ2', ...],]// オプション。バリデータ・オブジェクトに対する追加の構成情報を指定する。
'プロパティ1' => '値1', 'プロパティ2' => '値2', ...

各規則について、最低限、規則がどの属性に適用されるか、そして、規則がどのタイプであるかを指定しなければなりません。 規則のタイプ
は、次に挙げる形式のどれか一つを選ぶことが出来ます。
• コア・バリデータのエイリアス。例えば、required、in、date、等々。
コア・バリデータの完全なリストは コア・バリデータ を参照してください。
• モデル・クラス内のバリデーション・メソッドの名前、または無名関数。 詳細は、インライン・バリデータ の項を参照してください。
• 完全修飾のバリデータ・クラス名。詳細は スタンドアロン・バリ
データ の項を参照してください。
一つの規則は、一つまたは複数の属性を検証するために使用することが出来ます。そして、一つの属性は、一つまたは複数の規則によって検証され得ます。 on オプションを指定することで、規則を特定の シナリオにおいてのみ適用することが出来ます。 on オプションを指定しない場合
は、規則が全てのシナリオに適用されることになります。
validate() メソッドが呼ばれると、次のステップを踏んで検証が実行されます。
〱〮 現在の シナリオ を使って べどどぜぢちびづぜきはつづぬ〺〺びっづのちひどはび〨〩 から属性のリストを取得し、どの属性が検証されるべきかを決定します。 検
証されるべき属性が アクティブな属性 と呼ばれます。
〲〮 現在の シナリオ を使って べどどぜぢちびづぜきはつづぬ〺〺ひふぬづび〨〩 から規則のリストを取得し、どの検証規則が使用されるべきかを決定します。 使
用されるべき規則が アクティブな規則 と呼ばれます。
〳〮 全てのアクティブな規則を一つずつ使って、その規則に関連付けられた全てのアクティブな属性を一つずつ検証します。 検証規則はリストに挙げられている順に評価されます。

〷〮〲〮 入力を検証する〳〸〱

属性は、上記の検証のステップに従って、scenarios() でアクティブな属性であると宣言されており、 かつ、rules() で宣言された一つまたは複数のアクティブな規則と関連付けられている場合に、 また、その場合に限って、検証されます。
補足〺 規則に名前を付けると便利です。すなわち、
public function rules(){return [// ...
'password' => [['password'], 'string', 'max' => 60],];}

これを子のモデルで使うことが出来ます。
public function rules(){$rules = parent::rules();
unset($rules['password']);return $rules;}

エラー・メッセージをカスタマイズする
たいていのバリデータはデフォルトのエラー・メッセージを持っていて、属性の検証が失敗した場合にそれを検証の対象であるモデルに追加します。 例えば、ひづぱふどひづつ バリデータは、このバリデータを使ってusername 属性を検証したとき、 規則に合致しない場合は「ユーザ名は空ではいけません。」というエラー・メッセージをモデルに追加します。
規則のエラー・メッセージは、次に示すように、規則を宣言するときに message プロパティを指定することによってカスタマイズすることが出来ます。
public function rules(){return [['username', 'required', 'message' => 'ユーザ名を選んでください。'],];}

バリデータの中には、検証を失敗させたさまざまな原因をより詳しく説明するための追加のエラー・メッセージをサポートしているものがあります。 例えば、のふねぢづひ バリデータは、検証される値が大きすぎたり小さ
すぎたりしたときに、 検証の失敗を説明するために、それぞれ、ぴははあどでおよび ぴははこねちぬぬ のメッセージをサポートしています。 これらのエラー・メッセージも、バリデータの他のプロパティと同様、検証規則の中で構成することが出来ます。

〳〸〲ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得

検証のイベント
べどどぜぢちびづぜきはつづぬ〺〺ぶちぬどつちぴづ〨〩 は、呼び出されると、 検証のプロセスを
カスタマイズするためにオーバーライドできる二つのメソッドを呼び出します。
• べどどぜぢちびづぜきはつづぬ〺〺ぢづてはひづざちぬどつちぴづ〨〩〺 デフォルトの実装は べどどぜぢちびづ
ぜきはつづぬ〺〺ぅざぅぎごたあぅうくげぅたざぁがぉいぁごぅ イベントをトリガするものです。
このメソッドをオーバーライドするか、または、イベントに反応して、検証が実行される前に、 何らかの前処理 〨例えば入力されたデータの正規化〩 をすることが出来ます。 このメソッドは、検証を続行すべきか否かを示す真偽値を返さなくてはなりません。
• べどどぜぢちびづぜきはつづぬ〺〺ちてぴづひざちぬどつちぴづ〨〩〺 デフォルトの実装は べどどぜぢちびづ
ぜきはつづぬ〺〺ぅざぅぎごたぁうごぅげたざぁがぉいぁごぅ イベントをトリガするものです。
このメソッドをオーバーライドするか、または、イベントに反応して、検証が完了した後に、 何らかの後処理をすることが出来ます。
条件付きの検証
特定の条件が満たされる場合に限って属性を検証したい場合、例えば、ある属性の検証が他の属性の値に依存する場合には、 ぷとづの プロパティを使って、そのような条件を定義することが出来ます。 例えば、['state', 'required', 'when' => function($model) {return $model->country == 'USA';}],

ぷとづの プロパティは、次のシグニチャを持つ ぐえぐ コーラブルを値として
取ります。
/**
* @param Model $model 検証されるモデル* @param string $attribute 検証される属性* @return bool 規則が適用されるか否か*/
function ($model, $attribute)

クライアント・サイドでも条件付きの検証をサポートする必要がある場
合は、ぷとづのぃぬどづのぴ プロパティを構成しなければなりません。 このプロパ
ティは、規則を適用すべきか否かを返す おちぶちこっひどばぴ 関数を表す文字列を値として取ります。 例えば、['state', 'required', 'when' => function ($model) {return $model->country == 'USA';}, 'whenClient' => "function (attribute, value) {return $('#country').val() == 'USA';}"]〷〮〲〮 入力を検証する〳〸〳

データのフィルタリング
ユーザ入力をフィルタまたは前処理する必要があることがよくあります。 例えば、username の入力値の前後にある空白を除去したいというような場合です。この目的を達するために検証規則を使うことが出来ます。
次の例では、入力値の前後にある空白を除去して、空の入力値を のふぬぬに変換することを、 ぴひどね および つづてちふぬぴ のコア・バリデータで行っています。
return [[['username', 'email'], 'trim'],[['username', 'email'], 'default'],];

もっと汎用的な 〜ぬぴづひ バリデータを使って、 もっと複雑なデータ・フィ
ルタリングをすることも出来ます。
お分かりのように、これらの検証規則は実際には入力を検証しません。 そうではなくて、検証される属性の値を処理して書き戻すのです。
ユーザ入力の完全な処理を次のサンプル・コードで示します。 これは、ある属性に整数の値だけが保存されるように保証しようとするものです。
['age', 'trim'],['age', 'default', 'value' => null],['age', 'integer', 'min' => 0],['age', 'filter', 'filter' => 'intval', 'skipOnEmpty' => true],

上記のコードは入力に対して以下の操作を実行します。
〱〮 入力値から先頭と末尾のホワイト・スペースをトリムします。
〲〮 空の入力値がデータベースで null として保存されることを保証します。 【のはぴ びづぴ〨未設定〩】 という値と、実際の値である 0 は区別します。null が許されない時は、ここで別のデフォルト値を設定することが出来ます。
〳〮 空でない場合は、値は 〰 以上の整数であることを検証します。 通常のバリデータでは 〤びにどばくのぅねばぴべ が true に設定されています。
〴〮 例えば、文字列 '42' は、整数 42 にキャストして、値が整数型になることを保証します。 デフォルトでは false である てどぬぴづひ バリ
データの 〤びにどばくのぅねばぴべ をtrue に設定しています。
空の入力値を扱う
えごきが フォームから入力データが送信されたとき、入力値が空である場
合には何らかのデフォルト値を割り当てなければならないことがよくあります。 つづてちふぬぴ バリデータを使ってそうすることが出来ます。例えば、〳〸〴

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得

return [// 空の時は "username" と "email" を null にする[['username', 'email'], 'default'],];// 空の時は "level" を 1 にする['level', 'default', 'value' => 1],

デフォルトでは、入力値が空であると見なされるのは、それが、空文字列であるか、空配列であるか、のふぬぬ であるときです。 空を検知するこの
デフォルトのロジックは、べどどぜぶちぬどつちぴはひびぜざちぬどつちぴはひ〺〺どびぅねばぴべ〨〩 プロ
パティを ぐえぐ コーラブルで構成することによって、 カスタマイズすることが出来ます。例えば、['agree', 'required', 'isEmpty' => function ($value) {return empty($value);}]補足〺 たいていのバリデータは、べどどぜぶちぬどつちぴはひびぜざちぬどつちぴはひ〺〺〤びにどばくのぅねばぴべ プロパティがデフォルト値 true を取っている
場合は、 空の入力値を処理しません。そのようなバリデータ
は、関連付けられた属性が空の入力値を受け取ったときは、
検証の過程ではスキップされるだけになります。コア・バリ
データ の中では、 captcha、default、filter、required、そしてtrim だけが空の入力値を処理します。

7.2.2

その場限りの検証時として、何らかのモデルに結び付けられていない値に対する その場限りの検証 を実行しなければならない場合があります。
実行する必要がある検証が一種類 〨例えば、メール・アドレスの検証〩だけである場合は、 使いたいバリデータの ぶちぬどつちぴづ〨〩 メソッドを次のように呼び出すことが出来ます。
$email = 'test@example.com';$validator = new yii\validators\EmailValidator();if ($validator->validate($email, $error)) {echo 'メール・アドレスは有効。';} else {echo $error;}補足〺 全てのバリデータがこの種の検証をサポートしている
訳ではありません。 その一例が ふのどぱふづ コア・バリデータであり、これはモデルとともに使用されることだけを前提にして設計されています。

〷〮〲〮 入力を検証する〳〸〵

補足〺 べどどぜぢちびづぜざちぬどつちぴはひ〺〺びにどばくのぅねばぴべ プロパティは べどど
ぜぢちびづぜきはつづぬ の検証の場合にのみ使用されます。モデル無し
で使っても効果はありません。
いくつかの値に対して複数の検証を実行する必要がある場合は、属性と規則の両方をその場で宣言することが出来る べどどぜぢちびづぜいべのちねどっきはつづぬ を使うことが出来ます。 これは、次のような使い方をします。
public function actionSearch($name, $email){$model = DynamicModel::validateData(['name' => $name, 'email' =>$email], [[['name', 'email'], 'string', 'max' => 128],['email', 'email'],]);}

if ($model->hasErrors()) {// 検証が失敗} else {// 検証が成功}

べどどぜぢちびづぜいべのちねどっきはつづぬ〺〺ぶちぬどつちぴづいちぴち〨〩 メソッドは DynamicModel のインスタンスを作成し、 与えられた値 〨この例では name と email〩 を使って属性を定義し、そして、与えられた規則で べどどぜぢちびづぜきはつづぬ〺〺ぶちぬどつちぴづ〨〩を呼び出します。
別の選択肢として、次のように、もっと「クラシック」な構文を使って、その場限りのデータ検証を実行することも出来ます。
public function actionSearch($name, $email){$model = new DynamicModel(compact('name', 'email'));$model->addRule(['name', 'email'], 'string', ['max' => 128])->addRule('email', 'email')->validate();}if ($model->hasErrors()) {// 検証が失敗} else {// 検証が成功}

検証を実行した後は、通常のモデルで行うのと同様に、検証が成功したか否かを とちびぅひひはひび〨〩 メソッドを呼んでチェックして、 づひひはひび プ
ロパティから検証エラーを取得することが出来ます。 また、このモデルのインスタンスによって定義された動的な属性に対しても、例えば$model->name や $model->email のようにして、アクセスすることが出来ま
す。

〳〸〶

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得

7.2.3

バリデータを作成する

すどど のリリースに含まれている コア・バリデータ を使う以外に、あなた自身のバリデータを作成することも出来ます。 インライン・バリデータとスタンドアロン・バリデータを作ることが出来ます。
インライン・バリデータ
インライン・バリデータは、モデルのメソッドまたは無名関数として定義されるバリデータです。 メソッド〯関数 のシグニチャは、/*** @param string $attribute 現在検証されている属性* @param mixed $params 規則に与えられる "params" の値* @param \yii\validators\InlineValidator $validator 関係する
InlineValidator のインスタンス。
* このパラメータは、バージョン 2.0.11 以降で利用可能。
* @param mixed $current 現在検証されている属性の値* このパラメータは、バージョン 2.0.36 以降で利用可能。
*/
function ($attribute, $params, $validator, $current)

属 性 が 検 証 に 失 敗 し た 場 合 は 、 メ ソ ッ ド〯関 数 は べどどぜぢちびづぜきはつづぬ〺〺
ちつつぅひひはひ〨〩 を呼んでエラー・メッセージをモデルに保存し、 後で読み出してエンド・ユーザに表示することが出来るようにしなければなりません。
下記にいくつかの例を示します。
use yii\base\Model;
class MyForm extends Model{public $country;
public $token;
public function rules(){return [// モデル・メソッド validateCountry() として定義されるインライン・
バリデータ['country', 'validateCountry'],}];// 無名関数として定義されるインライン・バリデータ['token', function ($attribute, $params, $validator) {if (!ctype_alnum($this->$attribute)) {$this->addError($attribute, 'トークンは英数字で構成しなけ
ればなりません。');}}],

〷〮〲〮 入力を検証する}〳〸〷

public function validateCountry($attribute, $params, $validator){
if (!in_array($this->$attribute, ['USA', 'Indonesia'])) {$this->addError($attribute, '国は "USA" または "Indonesia" でな
ければなりません。');}}

補足〺 バージョン 〲〮〰〮〱〱 以降では、代わりに、べどどぜぶちぬどつちぴはひびぜぉのぬどのづざちぬどつちぴはひ〺〺ちつつぅひひはひ〨〩 を使ってエラー・メッセージを追加することが出来ます。 そうすれば、エラー・メッセー
ジはそのまま べどどぜど〱〸のぜぉ〱〸ぎ〺〺てはひねちぴ〨〩 を使ってフォーマッ
トされます。 属性のラベルと値を参照するためには、それぞれ、{attribute} と {value} を使ってください〨手作業で取得する必要はありません〩。
$validator->addError($this, $attribute, 'The value "{value}" is not
acceptable for {attribute}.');

補足〺 デフォルトでは、インライン・バリデータは、関連付けられている属性が空の入力値を受け取ったり、 既に何らかの検証規則に失敗したりしている場合には、適用されません。
規則が常に適用されることを保証したい場合は、 規則の宣言において びにどばくのぅねばぴべ および〯または びにどばくのぅひひはひ のプロパ
ティを てちぬびづ に設定することが出来ます。例えば、[]['country', 'validateCountry', 'skipOnEmpty' => false,'skipOnError' => false],

スタンドアロン・バリデータ
ス タ ン ド ア ロ ン ・ バ リ デ ー タ は 、べどどぜぶちぬどつちぴはひびぜざちぬどつちぴはひ ま た は
そ の 子 ク ラ ス を 拡 張 す る ク ラ ス で す 。 べどどぜぶちぬどつちぴはひびぜざちぬどつちぴはひ〺〺
ぶちぬどつちぴづぁぴぴひどぢふぴづ〨〩 メソッドをオーバーライドすることによって、その検証ロジックを実装することが出来ます。 インライン・バリデータでするのと同じように、属性が検証に失敗した場合は、 べどどぜぢちびづぜきはつづぬ〺〺ちつつぅひひはひ〨〩 を呼んでエラー・メッセージをモデルに保存します。
例えば、上記のインライン・バリデータは、新しい せせっはねばはのづのぴび〯ぶちぬどつちぴはひび〯ぃはふのぴひべざちぬどつちぴはひそそクラスに作りかえることが出来ます。 この場合、べどどぜぶちぬどつちぴはひびぜざちぬどつちぴはひ〺〺ちつつぅひひはひ〨〩 を使って特製のメッセージをモデルに設定することが出来ます。
namespace app\components;〳〸〸

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得

use yii\validators\Validator;
class CountryValidator extends Validator{
public function validateAttribute($model, $attribute){if (!in_array($model->$attribute, ['USA', 'Indonesia'])) {$this->addError($model, $attribute, '国は "{coutry1}" または"{coutry2}" でなければなりません。', ['country1' => 'USA','country2' => 'Indonesia']);}}}あなたのバリデータで、モデルを使わない値の検証をサポートしたい場
合は、べどどぜぶちぬどつちぴはひびぜざちぬどつちぴはひ〺〺ぶちぬどつちぴづ〨〩 もオーバーライドしな
ければなりません。または、validateAttribute() と validate() の代りに、べどどぜぶちぬどつちぴはひびぜざちぬどつちぴはひ〺〺ぶちぬどつちぴづざちぬふづ〨〩 をオーバーライドしても構いません。 と言うのは、前の二つは、デフォルトでは、validateValue()を呼び出すことによって実装されているからです。
次の例は、上記のバリデータ・クラスをあなたのモデルの中でどのように使用することが出来るかを示すものです。
namespace app\models;use Yii;
use yii\base\Model;
use app\components\validators\CountryValidator;
class EntryForm extends Model{public $name;public $email;public $country;}

public function rules(){return [[['name', 'email'], 'required'],['country', CountryValidator::class],['email', 'email'],
];
}

7.2.4

複数の属性の検証時として、バリデータが複数の属性に関係する場合があります。次のようなフォームを考えてみてください。
class MigrationForm extends \yii\base\Model{〳〸〹〷〮〲〮 入力を検証する/*** 成人一人のための最低限の生活費*/
const MIN_ADULT_FUNDS = 3000;/*** こども一人のための最低限の生活費*/
const MIN_CHILD_FUNDS = 1500;
public $personalSalary;
public $spouseSalary;
public $childrenCount;public $description;

}

// 給与
// 配偶者の給与// こどもの数

public function rules(){return [[['personalSalary', 'description'], 'required'],[['personalSalary', 'spouseSalary'], 'integer', 'min' =>
self::MIN_ADULT_FUNDS],['childrenCount', 'integer', 'min' => 0, 'max' => 5],[['spouseSalary', 'childrenCount'], 'default', 'value' => 0],['description', 'string'],];}

バリデータを作成する
家族の収入が子ども達のために十分であるかどうかをチェックする必要があるとしましょう。 そのためには、childrenCount が 〱 以上である場合にのみ実行される validateChildrenFunds というインライン・バリデータを作れば良いわけです。
検証されるすべての属性 〨['personalSalary', 'spouseSalary', 'childrenCount']〩にこのバリデータをアタッチすることは出来ない、ということに注意してください。 そのようにすると、同じバリデータが属性ごとに 〨合計で三回〩 走ることになりますが、 属性のセット全体に対してこのバリデー
タを一度だけ走らせれば十分なのです。
これらの属性のどれを使っても構いません 〨あるいは、もっとも関係が深いと思うものを使ってください〩。
['childrenCount', 'validateChildrenFunds', 'when' => function ($model) {return $model->childrenCount > 0;}],
validateChildrenFunds の実装は次のようにすることが出来ます。
public function validateChildrenFunds($attribute, $params){$totalSalary = $this->personalSalary + $this->spouseSalary;// 配偶者の給与が指定されているときは、成人の最低生活費を倍にする

〳〹〰

}

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得$minAdultFunds = $this->spouseSalary ? self::MIN_ADULT_FUNDS * 2 :self::MIN_ADULT_FUNDS;$childFunds = $totalSalary - $minAdultFunds;
if ($childFunds / $this->childrenCount < self::MIN_CHILD_FUNDS) {$this->addError('childrenCount', '子どもの数に対して給与が不足しています。');}

この検証は属性一つだけに関係するものではないので、$attribute のパラ
メータは無視することが出来ます。
エラー・メッセージを追加する
複数の属性の場合のエラー・メッセージの追加は、フォームをどのように設計するかによって異なってきます。
• もっとも関係が深いとあなたが思うフィールドを選んで、その属性にエラー・メッセージを追加する。
$this->addError('childrenCount', '子どもの数に対して給与が不足しています。');• 重要な複数の属性、または、すべての属性を選んで、同じエラー・
メッセージを追加する。 メッセージを独立した変数に格納してからaddError に渡せば、コードを いげす に保つことが出来ます。
$message = '子どもの数に対して給与が不足しています。';$this->addError('personalSalary', $message);$this->addError('wifeSalary', $message);$this->addError('childrenCount', $message);

あるいは、ループを使います。
$attributes = ['personalSalary', 'wifeSalary', 'childrenCount'];
foreach ($attributes as $attribute) {$this->addError($attribute, '子どもの数に対して給与が不足しています。');}• 〨特定の属性に結び付かない〩 共通のエラー・メッセージを追加する。 その時点では属性の存在はチェックされませんので、存在しな
い属性の名前、例えば * を使ってエラー・メッセージを追加することが出来ます。
$this->addError('*', '子どもの数に対して給与が不足しています。');

結果として、フォームのフィールドの近くにはこのエラー・メッセージは表示されません。これを表示するためには、ビューにエラー・サマリ
を含めます。
<?= $form->errorSummary($model) ?>〷〮〲〮 入力を検証する〳〹〱

補足〺 複数の属性を一度に検証するバリデータを作成する方法
が っはねねふのどぴべ っははにぢははに6 で分り易く解説されています。〮

7.2.5

クライアント・サイドでの検証

エンド・ユーザが えごきが フォームで値を入力する際には、おちぶちこっひどばぴ に基づくクライアント・サイドでの検証を提供することが望まれます。 というのは、クライアント・サイドでの検証は、ユーザが入力のエラーを早く見つけることが出来るようにすることによって、より良いユーザ体
験を提供するものだからです。 あなたも、サーバ・サイドでの検証 に加えて クライアント・サイドでの検証をサポートするバリデータを使用したり実装したりすることが出来ます。
情報〺 クライアント・サイドでの検証は望ましいものですが、不可欠なものではありません。 その主たる目的は、ユーザにより良い体験を提供することにあります。 エンド・ユーザ
から来る入力値と同じように、クライアント・サイドでの検証を決して信用してはいけません。 この理由により、これまでの項で説明したように、常に べどどぜぢちびづぜきはつづぬ〺〺ぶちぬどつちぴづ〨〩を呼び出してサーバ・サイドでの検証を実行しなければなりません。
クライアント・サイドでの検証を使う
多くの コア・バリデータ は、そのままで、クライアント・サイドでの検証をサポートしています。 あなたがする必要があるのは、べどどぜぷどつでづぴび
ぜぁっぴどぶづうはひね を使って えごきが フォームを作るということだけです。 例えば、下の LoginForm は二つの規則を宣言しています。 一つは、ひづぱふどひづつ コ
ア・バリデータを使っていますが、これはクライアント・サイドとサー
バ・サイドの両方でサポートされています。 もう一つは validatePassword
インライン・バリデータを使っていますが、こちらはサーバ・サイドでのみサポートされています。
namespace app\models;
use yii\base\Model;
use app\models\User;class LoginForm extends Model{public $username;public $password;
public function rules(){
6
https://github.com/samdark/yii2-cookbook/blob/master/book/forms-validator-multiple-attributes.md〳〹〲

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得
return [// username と password はともに必須[['username', 'password'], 'required'],}];// password は validatePassword() によって検証される['password', 'validatePassword'],public function validatePassword(){$user = User::findByUsername($this->username);}}if (!$user || !$user->validatePassword($this->password)) {$this->addError('password', 'ユーザ名またはパスワードが違います。');}

次のコードによって構築される えごきが フォームは、username と passwordの二つの入力フィールドを含みます。 何も入力せずにこのフォームを送信すると、何かを入力するように要求するエラー・メッセージが、 サー
バと少しも交信することなく、ただちに表示されることに気付くでしょう。
<?php $form = yii\widgets\ActiveForm::begin(); ?><? = $form->field($model, 'username') ?><? = $form->field($model, 'password')->passwordInput() ?><? = Html::submitButton('ログイン') ?><?php yii\widgets\ActiveForm::end(); ?>舞台裏では、べどどぜぷどつでづぴびぜぁっぴどぶづうはひね がモデルで宣言されている検証規則を読んで、 クライアント・サイドの検証をサポートするバリデータのために、適切な おちぶちこっひどばぴ コードを生成します。 ユーザが入力フィール
ドの値を変更したりフォームを送信したりすると、クライアント・サイ
ドの検証の おちぶちこっひどばぴ が起動されます。
ク ラ イ ア ン ト ・ サ イ ド の 検 証 を 完 全 に 無 効 に し た い 場 合 は 、べどどぜぷどつでづぴびぜぁっぴどぶづうはひね〺〺〤づのちぢぬづぃぬどづのぴざちぬどつちぴどはの プロパティを false に設定することが出来ます。 また、個々の入力フィールドごとにクライ
アント・サイドの検証を無効にしたい場合には、 入力フィールドの べどど
ぜぷどつでづぴびぜぁっぴどぶづうどづぬつ〺〺〤づのちぢぬづぃぬどづのぴざちぬどつちぴどはの プロパティを てちぬびづ に設定することが出来ます。 eanbleClientValidation が入力フィールドのレ
ベルとフォームのレベルの両方で構成されている場合は前者が優先されます。
情報〺 バージョン 〲〮〰〮〱〱 以降、べどどぜぶちぬどつちぴはひびぜざちぬどつちぴはひ を拡張する全てのバリデータは、クライアント・サイドのオプションを 独立したメソッド 〭 べどどぜぶちぬどつちぴはひびぜざちぬどつちぴはひ〺〺〷〮〲〮 入力を検証する〳〹〳

でづぴぃぬどづのぴくばぴどはのび〨〩 から受け取るようになりました。これを使うと、次のことが可能になります。
• 独自のクライアント・サイド検証を実装しながら、 サー
バ・サイド検証のオプションとの同期はそのまま残す• 特殊な要求に合うように拡張またはカスタマイズする
public function getClientOptions($model, $attribute){$options = parent::getClientOptions($model, $attribute);// ここで $options を修正}

return $options;

クライアント・サイドの検証を実装する
クライアント・サイドの検証をサポートするバリデータを作成するためには、 クライアント・サイドでの検証を実行する おちぶちこっひどばぴ コードを返す べどどぜぶちぬどつちぴはひびぜざちぬどつちぴはひ〺〺っぬどづのぴざちぬどつちぴづぁぴぴひどぢふぴづ〨〩 メソッドを実装しなければなりません。 その おちぶちこっひどばぴ の中では、次の事前定義された変数を使用することが出来ます。
• attribute〺 検証される属性の名前。
• value〺 検証される値。
• messages〺 属性に対する検証のエラー・メッセージを保持するために使用される配列。
• deferred〺 いづてづひひづつ オブジェクトをプッシュして入れることが出来る
配列 〨次の項で説明します〩。
次の例では、入力された値が既存のステータスのデータに含まれる有効なステータス値であるかどうかを検証する StatusValidator を作成します。 このバリデータは、サーバ・サイドとクライアント・サイドの両方の検証をサポートします。
namespace app\components;
use yii\validators\Validator;
use app\models\Status;class StatusValidator extends Validator{
public function init(){
parent::init();$this->message = '無効なステータスが入力されました。';}
public function validateAttribute($model, $attribute){$value = $model->$attribute;if (!Status::find()->where(['id' => $value])->exists()) {〳〹〴

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得}}$model->addError($attribute, $this->message);

public function clientValidateAttribute($model, $attribute, $view){$statuses =json_encode(Status::find()->select('id')->asArray()->column());$message = json_encode($this->message, JSON_UNESCAPED_SLASHES |JSON_UNESCAPED_UNICODE);
return <<<JS
if ($.inArray(value, $statuses) === -1) {messages.push($message);
}
JS;
}
}

ヒント〺 上記のコード例の主たる目的は、クライアント・サイドの検証をサポートする方法を説明することにあります。 実
際の仕事では、どの コア・バリデータを使って、同じ目的を達することが出来ます。 次のように検証規則を書けばよいのです。
[]['status', 'in', 'range' =>Status::find()->select('id')->asArray()->column()],ヒント〺 クライアント・サイドの検証を手動で操作する必要がある場合、すなわち、動的にフィールドを追加したり、何か特殊な さぉ ロジックを実装する場合は、 すどど 〲〮〰 ぃははにぢははにの しはひにどので ぷどぴと ぁっぴどぶづうはひね ぶどち おちぶちこっひどばぴ7 を参照してください。
いづてづひひづつ 検証
非同期のクライアント・サイドの検証をサポートする必要がある場合
は、いづてづひづつ オブジェクト8 を作成することが出来ます。 例えば、ぁおぁじ
によるカスタム検証を実行するために、次のコードを使うことが出来ます。
public function clientValidateAttribute($model, $attribute, $view){
return <<<JS
deferred.push($.get("/check", {value: value}).done(function(data) {https://github.com/samdark/yii2-cookbook/blob/master/book/forms-activeform-js.md
8https://api.jquery.com/category/deferred-object/7〷〮〲〮 入力を検証する

JS;
}

〳〹〵

if ('' !== data) {messages.push(data);}}));

上のコードにおいて、deferred は すどど が提供する変数で、いづてづひひづつ オブ
ジェクトの配列です。 なけふづひべ の $.get() メソッドによって作成された
いづてづひひづつ オブジェクトが deferred 配列にプッシュされています。
いづてづひひづつ オブジェクトを明示的に作成して、非同期のコールバックが呼ばれたときに、いづてづひひづつ オブジェクトの resolve() メソッドを呼ぶことも出来ます。 次の例は、アップロードされる画像ファイルの大きさをク
ライアント・サイドで検証する方法を示すものです。
public function clientValidateAttribute($model, $attribute, $view){
return <<<JS
var def = $.Deferred();var img = new Image();
img.onload = function() {if (this.width > 150) {messages.push('画像の幅が大きすぎます。');}
def.resolve();}var reader = new FileReader();reader.onloadend = function() {img.src = reader.result;}reader.readAsDataURL(file);JS;}

deferred.push(def);

補足〺 属性が検証された後に、resolve() メソッドを呼び出さなければなりません。 そうしないと、主たるフォームの検証が完了しません。
簡潔に記述できるように、deferred 配列はショートカット・メソッド
add() を装備しており、このメソッドを使うと、自動的に いづてづひひづつ オブ
ジェクトを作成して deferred 配列に追加することが出来ます。このメ
ソッドを使えば、上記の例は次のように簡潔に記すことが出来ます。
public function clientValidateAttribute($model, $attribute, $view){
return <<<JS
deferred.add(function(def) {var img = new Image();〳〹〶

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得

});

JS;
}

7.2.6

img.onload = function() {if (this.width > 150) {messages.push('画像の幅が大きすぎます。');}
def.resolve();}var reader = new FileReader();reader.onloadend = function() {img.src = reader.result;}reader.readAsDataURL(file);

AJAX 検証

場合によっては、サーバだけが必要な情報を持っているために、サーバ・サイドでしか検証が実行できないことがあります。 例えば、ユーザ
名がユニークであるか否かを検証するためには、サーバ・サイドで ふびづひ
テーブルを調べることが必要になります。 このような場合には、ぁおぁじ
ベースの検証を使うことが出来ます。 ぁおぁじ 検証は、通常のクライアン
ト・サイドでの検証と同じユーザ体験を保ちながら、入力値を検証するためにバックグラウンドで ぁおぁじ リクエストを発行します。
単一のインプット・フィールドに対して ぁおぁじ 検証を有効にするた
めには、そのフィールドの づのちぢぬづぁなちへざちぬどつちぴどはの プロパティを ぴひふづ に設定し、フォームに一意の id を指定します。
use yii\widgets\ActiveForm;$form = ActiveForm::begin(['id' => 'registration-form',]);echo $form->field($model, 'username', ['enableAjaxValidation' => true]);// ...
ActiveForm::end();

フォームの全てのインプットに対して ぁおぁじ 検証を有効にするためには、フォームのレベルで づのちぢぬづぁなちへざちぬどつちぴどはの を ぴひふづ に設定します。
$form = ActiveForm::begin(['id' => 'contact-form','enableAjaxValidation' => true,]);補足〺 enableAjaxValidation プロパティがインプット・フィールドのレベルとフォームのレベルの両方で構成された場合は、前者が優先されます。

〷〮〳〮 ファイルをアップロードする〳〹〷

また、サーバ・サイドでは、ぁおぁじ 検証のリクエストを処理できるように準備しておく必要があります。 これは、コントローラのアクションにおいて、次のようなコード断片を使用することで達成できます。
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())){
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);}上記のコードは、現在のリクエストが ぁおぁじ であるかどうかをチェックします。 もし ぁおぁじ であるなら、リクエストに応えて検証を実行し、エラーを おこくぎ 形式で返します。
情報〺 ぁおぁじ 検証を実行するためには、いづてづひひづつ 検証 を使うことも出来ます。 しかし、ここで説明された ぁおぁじ 検証の機能の方がより体系化されており、コーディングの労力も少なくて済みます。
enableClientValidation と enableAjaxValidation が両方とも true に設定されているときは、 クライアント検証が成功した後でだけ ぁおぁじ 検証のリクエストが起動されます。 validateOnChange〬 validateOnBlur またはvalidateOnType が true に設定されている単一のフィールドを検証する場
合、 当該フィールドが単独でクライアント検証を通ったら ぁおぁじ リクエ
ストが送信されることに注意して下さい。

7.3

ファイルをアップロードする

すどど におけるファイルのアップロードは、通常、アップロードされる個々のファイルを UploadedFile としてカプセル化する べどどぜぷづぢぜさばぬはちつづつうどぬづの助けを借りて実行されます。これを べどどぜぷどつでづぴびぜぁっぴどぶづうはひね および
モデル と組み合わせることで、安全なファイル・アップロード・メカニ
ズムを簡単に実装することが出来ます。

7.3.1

モデルを作成する

プレーンなテキスト・インプットを扱うのと同じように、一つのファイ
ルをアップロードするためには、モデル・クラスを作成して、 そのモデルの一つの属性を使ってアップロードされるファイルのインスタンスを保持します。 また、ファイルのアップロードを検証するために、検証規則も宣言しなければなりません。例えば、
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;〳〹〸

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得

class UploadForm extends Model{/*** @var UploadedFile*/
public $imageFile;public function rules(){return [[['imageFile'], 'file', 'skipOnEmpty' => false, 'extensions' =>'png, jpg'],];}
public function upload(){
if ($this->validate()) {$this->imageFile->saveAs('uploads/' . $this->imageFile->baseName. '.' . $this->imageFile->extension);
return true;} else {return false;}}}

上記のコードにおいては、imageFile 属性がアップロードされたファイルのインスタンスを保持するのに使われます。 この属性が関連付けられている file 検証規則は、べどどぜぶちぬどつちぴはひびぜうどぬづざちぬどつちぴはひ を使って、png ま
たは jpg の拡張子を持つファイルがアップロードされることを保証しています。 upload() メソッドは検証を実行して、アップロードされたファ
イルをサーバに保存します。
file バリデータによって、ファイル拡張子、サイズ、きぉきぅ タイプなどをチェックすることが出来ます。 詳細については、コア・バリデータのセクションを参照してください。
ヒント〺 画像をアップロードしようとする場合は、image バリ
データを代りに使うことを考慮しても構いません。 image バリ
データは べどどぜぶちぬどつちぴはひびぜぉねちでづざちぬどつちぴはひ によって実装されており、属性が有効な画像、すなわち、 保存したり ぉねちでどのづ
エクステンション9 を使って処理したりすることが可能な有効な画像を、受け取ったかどうかを検証します。

7.3.2

ファイル・インプットをレンダリングする

次に、ビューでファイル・インプットを作成します。
9https://github.com/yiisoft/yii2-imagine〷〮〳〮 ファイルをアップロードする

〳〹〹

<?php
use yii\widgets\ActiveForm;?><?php $form = ActiveForm::begin(['options' => ['enctype' =>'multipart/form-data']]) ?><? = $form->field($model, 'imageFile')->fileInput() ?><button>送信</button><?php ActiveForm::end() ?>ファイルが正しくアップロードされるように、フォームに enctype オプ
ションを追加することを憶えておくのは重要なことです。 fileInput() を呼ぶと <input type="file"> のタグがレンダリングされて、ユーザがアップロードするファイルを選ぶことが出来るようになります。
ヒント〺 バージョン 〲〮〰〮〸 以降では、ファイル・インプットのフィールドが使われているときは、 てどぬづぉのばふぴ がフォームにenctype オプションを自動的に追加します。

7.3.3

繋ぎ合せる

そして、コントローラ・アクションの中で、モデルとビューを繋ぎ合せるコードを書いて、ファイルのアップロードを実装します。
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\UploadForm;use yii\web\UploadedFile;class SiteController extends Controller{
public function actionUpload(){$model = new UploadForm();
if (Yii::$app->request->isPost) {$model->imageFile = UploadedFile::getInstance($model,'imageFile');if ($model->upload()) {// ファイルのアップロードが成功
return;}}}}return $this->render('upload', ['model' => $model]);〴〰〰

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得

上記のコードでは、フォームが送信されると べどどぜぷづぢぜさばぬはちつづつうどぬづ〺〺でづぴぉのびぴちのっづ〨〩 メソッドが呼ばれて、 アップロードされたファイルがUploadedFile のインスタンスとして表現されます。 そして、次に、モデルの検証によってアップロードされたファイルが有効なものであることを確かめ、サーバにファイルを保存します。

7.3.4

複数のファイルをアップロードする

ここまでの項で示したコードに若干の修正を加えれば、複数のファイル
を一度にアップロードすることも出来ます。
最初に、モデル・クラスを修正して、file 検証規則に maxFiles オプ
ションを追加して、アップロードを許可されるファイルの最大数を制限しなければなりません。 maxFiles を 0 に設定することは、同時にアップロード出来るファイル数に制限がないことを意味します。 同時にアップロードすることを許されるファイルの数は、また、ぐえぐ のディレク
ティブ max_file_uploads10 〨デフォルト値は 〲〰〩 によっても制限されます。
upload() メソッドも、アップロードされた複数のファイルを一つずつ保存するように修正しなければなりません。
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;class UploadForm extends Model{/*** @var UploadedFile[]*/
public $imageFiles;
public function rules(){return [[['imageFiles'], 'file', 'skipOnEmpty' => false, 'extensions' =>'png, jpg', 'maxFiles' => 4],];}
public function upload(){
if ($this->validate()) {foreach ($this->imageFiles as $file) {$file->saveAs('uploads/' . $file->baseName . '.' .
$file->extension);}
return true;} else {10https://www.php.net/manual/ja/ini.core.php#ini.max-file-uploads

〷〮〳〮 ファイルをアップロードする

}

}

}

〴〰〱

return false;

ビュー・ファイルでは、fileInput() の呼び出しに multiple オプションを追加して、ファイル・アップロードのフィールドが複数のファイルを受け取ることが出来るようにしなければなりません。 また、imageFiles を
imageFiles[] に変更して、属性の値が配列として送信されるようにする必要があります。
<?php
use yii\widgets\ActiveForm;?><?php $form = ActiveForm::begin(['options' => ['enctype' =>'multipart/form-data']]) ?><? = $form->field($model, 'imageFiles[]')->fileInput(['multiple' =>true, 'accept' => 'image/*']) ?><button>送信</button><?php ActiveForm::end() ?>そして、最後に、コントローラ・アクションの中では、UploadedFile::getInstance()の代りに UploadedFile::getInstances() を呼んで、 UploadedFile インスタン
スの配列を UploadForm::imageFiles に代入しなければなりません。
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\UploadForm;use yii\web\UploadedFile;class SiteController extends Controller{
public function actionUpload(){$model = new UploadForm();
if (Yii::$app->request->isPost) {$model->imageFiles = UploadedFile::getInstances($model,'imageFiles');if ($model->upload()) {// ファイルのアップロードが成功
return;}}return $this->render('upload', ['model' => $model]);

〴〰〲

}

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得}

7.4

表形式インプットでデータを収集する時として、一つのフォームで同じ種類の複数のモデルを扱わなければならないことがあります。 例えば、それぞれが「名前〭値」の形で保存され、Setting アクティブ・レコード モデルとして表される複数の設定項目を扱うフォームです。 この種のフォームは「表形式インプット」と呼ばれることもよくあります。 これとは対照的な、異なる種類のさまざまなモデルを扱うことについては、複数のモデルを持つ複雑なフォーム のセクションで扱います。
以下に、表形式インプットを すどど で実装する方法を示します。
カバーすべき三つの異なる状況があり、それぞれ少しずつ異なる処理をしなければなりません。
• 特定の数のデータベース・レコードを更新する• 不特定の数の新しいレコードを作成する• 一つのページでレコードを更新、作成、および、削除する
前に説明した単一モデルのフォームとは対照的に、モデルの配列を扱うことになります。 この配列がビューに渡されて、各モデルのためのイン
プット・フィールドが表のような形式で表示されます。 そして、複数のモデルを一度にロードしたり検証したりするために べどどぜぢちびづぜきはつづぬ のヘ
ルパ・メソッドを使用します。
• きはつづぬ〺〺ぬはちつきふぬぴどばぬづ〨〩 〭 送信されたデータをモデルの配列にロードします。
• きはつづぬ〺〺ぶちぬどつちぴづきふぬぴどばぬづ〨〩 〭 モデルの配列を検証します。
特定の数のレコードを更新する
コントローラのアクションから始めましょう。
<?php
namespace app\controllers;
use Yii;
use yii\base\Model;
use yii\web\Controller;
use app\models\Setting;class SettingsController extends Controller{// ...
public function actionUpdate(){〷〮〴〮 表形式インプットでデータを収集する〴〰〳$settings = Setting::find()->indexBy('id')->all();if (Model::loadMultiple($settings, Yii::$app->request->post()) &&Model::validateMultiple($settings)) {foreach ($settings as $setting) {$setting->save(false);}
return $this->redirect('index');}}}return $this->render('update', ['settings' => $settings]);

上記のコードでは、データベースからモデルを読み出すときに どのつづへあべ〨〩を使って、 モデルのプライマリ・キーでインデックスされた配列にデータを投入しています。このインデックスが、後で、 フォーム・フィールドを特定するために使われます。きはつづぬ〺〺ぬはちつきふぬぴどばぬづ〨〩 がぐくこご から来るフォーム・データを複数のモデルに代入し、きはつづぬ〺〺
ぶちぬどつちぴづきふぬぴどばぬづ〨〩 が全てのモデルを一度に検証します。 保存するときには、validateMultiple() を使ってモデルの検証を済ませていますので、びちぶづ〨〩 のパラメータに false を渡して、二度目の検証を実行しないようにしています。
次に、update ビューの中にあるフォームです。
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;$form = ActiveForm::begin();foreach ($settings as $index => $setting) {echo $form->field($setting, "[$index]value")->label($setting->name);}
ActiveForm::end();

ここで全ての設定項目について、それぞれ、項目名を示すラベルと、項目の値を入れたインプットをレンダリングしています。 インプットの名前に適切なインデックスを追加することが肝腎です。というのは、loadMultiple がそれを見て、どのモデルにどの値を代入するかを決定するからです。
不特定の数の新しいレコードを動的に作成する
新しいレコードを作成するのは、モデルのインスタンスを作成する部分を除いて、更新の場合と同じです。
public function actionCreate(){〴〰〴

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得$count = count(Yii::$app->request->post('Setting', []));$settings = [new Setting()];for($i = 1; $i < $count; $i++) {$settings[] = new Setting();}}// ...

ここでは、デフォルトで一個のモデルを含む $settings 配列を初期値として作成し、少なくとも一個のテキスト・フィールドが常にビューに表示されるようにしています。 そして、受信したインプットの行数に合せて、配列にモデルを追加しています。
ビューでは なちぶちびっひどばぴ を使ってインプットの行を動的に追加することが出来ます。
更新、作成、削除を一つのページに組み合わせる補足〺 このセクションはまだ執筆中です。
まだ内容がありません。
〨未定〩

7.5

複数のモデルのデータを取得する

複雑なデータを扱う場合には、複数の異なるモデルを使用してユーザの入力を収集する必要があることがあり得ます。 例えば、ユーザのログイ
ン情報は user テーブルに保存されているけれども、ユーザのプロファイ
ル情報は profile テーブルに保存されているという場合を考えて見ると、ユーザに関して入力されたデータを User モデルと Profile モデルによって収集しなければならないでしょう。 すどど のモデルとフォームのサポートを使えば、単一のモデルを扱うのとそれほど違いのない方法によってこの問題を解決することが出来ます。
下記において、User と Profile の二つのモデルのデータを収集することが出来るフォームをどのようにして作成することが 出来るかを示します。
最初に、ユーザとプロファイルのデータを収集するためのコントロー
ラ・アクションは、次のように書くことが出来ます。
namespace app\controllers;
use Yii;
use yii\base\Model;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use app\models\User;use app\models\Profile;〷〮〵〮 複数のモデルのデータを取得する〴〰〵

class UserController extends Controller{
public function actionUpdate($id){$user = User::findOne($id);if (!$user) {throw new NotFoundHttpException("ユーザが見つかりませんでした。");}$profile = Profile::findOne($id);if (!$profile) {throw new NotFoundHttpException("ユーザのプロファイルがありません。");}$user->scenario = 'update';$profile->scenario = 'update';
if ($user->load(Yii::$app->request->post()) &&$profile->load(Yii::$app->request->post())) {$isValid = $user->validate();$isValid = $profile->validate() && $isValid;if ($isValid) {$user->save(false);$profile->save(false);
return $this->redirect(['user/view', 'id' => $id]);
}
}

}

}

return $this->render('update', ['user' => $user,'profile' => $profile,]);

この update アクションでは、最初に、更新の対象になる $user と $profileのモデルをデータベースからロードします。 次に べどどぜぢちびづぜきはつづぬ〺〺
ぬはちつ〨〩 を呼んで、これら二つのモデルにユーザ入力を代入します。 代入が成功すれば、二つのモデルを検証して保存します。 〦ねつちびと〻 モデルの中では、ユーザの入力データは既に検証済みであるため、過剰な検証を避けるために save(false) を使っていることに注意して下さい。 そうでない場合は、次の内容を持つ update ビューをレンダリングします。
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;$form = ActiveForm::begin([〴〰〶ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得'id' => 'user-update-form','options' => ['class' => 'form-horizontal'],]) ?><? = $form->field($user, 'username') ?>...other input fields...
<? = $form->field($profile, 'website') ?><? = Html::submitButton('更新', ['class' => 'btn btn-primary']) ?><?php ActiveForm::end() ?>ご覧のように、update ビューでは、二つのモデル、すなわち $user と$profile を使ってインプット・フィールドをレンダリングすることになり
ます。

7.6

クライアント・サイドで ActiveForm を拡張する

べどどぜぷどつでづぴびぜぁっぴどぶづうはひね ウィジェットは、クライアント・サイドの検証に使う一連の おちぶちこっひどばぴ メソッドを備えています。 その実装は非常に柔軟で、様々な方法で拡張することが可能になっています。 下記でそれについて解説します。

7.6.1

ActiveForm イベント

ぁっぴどぶづうはひね は、一連の専用のイベントを発生させます。 次のようなコードを使って、これらのイベントを購読して処理することが出来ます。
$('#contact-form').on('beforeSubmit', function (e) {if (!confirm("全てオーケー。送信しますか?")) {return false;}
return true;});

以下、利用できるイベントを見ていきましょう。

beforeValidate は、フォーム全体を検証する前にトリガされます。

イベント・ハンドラのシグニチャは以下の通り〺
function (event, messages, deferreds)

引数は以下の通り〺• event〺 イベントのオブジェクト。
• messages〺 連想配列で、キーは属性の ぉい、 値は対応する属性のエ
ラー・メッセージの配列です。

〷〮〶〮 クライアント・サイドで ぁぃごぉざぅうくげき を拡張する〴〰〷• deferreds〺 いづてづひひづつ オブジェクトの配列。deferreds.add(callback) を使って、 新しい つづてづひひつ な検証を追加することが出来ます。
ハンドラが真偽値 false を返すと、このイベントに続くフォームの検証は中止されます。 その結果、afterValidate イベントもトリガされません。

afterValidate イベントは、フォーム全体を検証した後でトリガされます。

イベント・ハンドラのシグニチャは以下の通り〺
function (event, messages, errorAttributes)

引数は以下の通り〺• event〺 イベントのオブジェクト。
• messages〺 連想配列で、キーは属性の ぉい、 値は対応する属性のエ
ラー・メッセージの配列です。
• errorAttributes〺 検証エラーがある属性の配列。 この引数の構造については attributeDefaults を参照して下さい。

beforeValidateAttribute イベントは、属性を検証する前にトリガされます。 イベント・ハンドラのシグニチャは以下の通り〺
function (event, attribute, messages, deferreds)

引数は以下の通り〺• event〺 イベントのオブジェクト。
• attribute〺 検証される属性。 この引数の構造については attributeDefaults
を参照して下さい。
• messages〺 指定された属性に対する検証エラー・メッセージを追加することが出来る配列。
• deferreds〺 いづてづひひづつ オブジェクトの配列。 deferreds.add(callback) を使って、新しい つづてづひひつ な検証を追加することが出来ます。
ハンドラが真偽値 false を返すと、指定された属性の検証は中止されます。 その結果、afterValidateAttribute イベントもトリガされません。

afterValidateAttribute イベントは、フォーム全体および各属性の検証の後にトリガされます。
イベント・ハンドラのシグニチャは以下の通り〺
function (event, attribute, messages)

引数は以下の通り〺〴〰〸

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得• event〺 イベントのオブジェクト。
• attribute〺 検証される属性。 この引数の構造については attributeDefaults
を参照して下さい。
• messages〺 指定された属性に対する追加の検証エラー・メッセージを追加することが 出来る配列。

beforeSubmit イベントは、全ての検証が通った後、フォームを送信する前にトリガされます。
イベント・ハンドラのシグニチャは以下の通り〺
function (event)

ここで、event は、イベントのオブジェクトです。
ハンドラが真偽値 false を返すと、フォームの送信は中止されます。

ajaxBeforeSend イベントは、ぁおぁじ ベースの検証のための ぁおぁじ リクエス

トを送信する前にトリガされます。
イベント・ハンドラのシグニチャは以下の通り〺
function (event, jqXHR, settings)

引数は以下の通り〺• event〺 イベントのオブジェクト。
• jqXHR〺 なぱじえげ のオブジェクト。
• settings〺 ぁおぁじ リクエストの設定。

ajaxComplete イベントはぁおぁじ ベースの検証のための ぁおぁじ リクエストが完了した後にトリガされます。
イベント・ハンドラのシグニチャは以下の通り〺
function (event, jqXHR, textStatus)

引数は以下の通り〺• event〺 イベントのオブジェクト。
• jqXHR〺 なぱじえげ のオブジェクト。
• textStatus〺 リクエストの状態 〨〢びふっっづびび】〬 【のはぴねはつど〜づつ】〬 【づひひはひ】〬 【ぴどねづ〭
はふぴ】〬 【ちぢはひぴ】〬 または 【ばちひびづひづひひはひ】〩。

〷〮〶〮 クライアント・サイドで ぁぃごぉざぅうくげき を拡張する

7.6.2

〴〰〹

AJAX でフォームを送信する

検証〨バリデーション〩は、クライアント・サイドまたは ぁおぁじ リクエス
トによって行うことが出来ますが、 フォームの送信そのものはデフォル
トでは通常のリクエストとして実行されます。 フォームを ぁおぁじ で送信したい場合は、次のように、フォームの beforeSubmit イベントを処理することによって達成することが出来ます。
var $form = $('#formId');$form.on('beforeSubmit', function() {var data = $form.serialize();$.ajax({url: $form.attr('action'),type: 'POST',
data: data,
success: function (data) {// 成功したときの実装},
error: function(jqXHR, errMsg) {alert(errMsg);}});
return false; // デフォルトの送信を抑止});

なけふづひべ の ajax() 関数について更に学習するためには、なけふづひべ つはっふねづのぴち〭
ぴどはの11 を参照して下さい。

7.6.3

フィールドを動的に追加する

現在のウェブ・アプリケーションでは、ユーザに対して表示した後でフォームを変更する必要がある場合がよくあります。 例えば、】追加】ア
イコンをクリックするとフィールドが追加される場合などです。 このようなフィールドに対するクライアント・サイドの検証を有効にするためには、フィールドを ぁっぴどぶづうはひね おちぶちこっひどばぴ プラグインに登録しなければなりません。
フィールドそのものを追加して、そして、検証のリストに追加しなけ
ればなりません。
$('#contact-form').yiiActiveForm('add', {id: 'address',
name: 'address',container: '.field-address',
input: '#address',
error: '.help-block',validate: function (attribute, value, messages, deferred, $form) {yii.validation.required(value, messages, {message: "Validation
Message Here"});11

https://api.jquery.com/jQuery.ajax/

〴〱〰

});

ぃえぁぐごぅげ 〷〮 ユーザからのデータ取得}

フィールドを検証のリストから削除して検証されないようにするためには、次のようにします。
$('#contact-form').yiiActiveForm('remove', 'address');

Chapter 8

データの表示8.1

データのフォーマット

ユーザにとってより読みやすい形式でデータを表示するために、formatter
アプリケーション・コンポーネント を使ってデータをフォーマットすることが出来ます。デフォルトでは、フォーマッタは べどどぜど〱〸のぜうはひねちぴぴづひ
によって実装されており、 これが、日付〯時刻、数字、通貨、その他のよく使われる形式にデータをフォーマットする一連のメソッドを提供します。このフォーマッタは次のようにして使うことが出来ます。
$formatter = \Yii::$app->formatter;// 出力: January 1, 2014
echo $formatter->asDate('2014-01-01', 'long');// 出力: 12.50%
echo $formatter->asPercent(0.125, 2);// 出力: <a href="mailto:cebe@example.com">cebe@example.com</a>echo $formatter->asEmail('cebe@example.com');// 出力: Yesecho $formatter->asBoolean(true);// it also handles display of null values:// 出力: (not set)echo $formatter->asDate(null);

ご覧のように、これらのメソッドは全て asXyz() という名前を付けられており、Xyz がサポートされている形式を表しています。 別の方法として、
汎用メソッド てはひねちぴ〨〩 を使ってデータをフォーマットすることも出来ます。 この方法を使うと望む形式をプログラム的に制御することが可能になりますので、べどどぜでひどつぜぇひどつざどづぷ や べどどぜぷどつでづぴびぜいづぴちどぬざどづぷ などのウィジェットでは、こちらがよく使われています。例えば、
〴〱〱

〴〱〲

ぃえぁぐごぅげ 〸〮 データの表示// 出力: January 1, 2014
echo Yii::$app->formatter->format('2014-01-01', 'date');// 配列を使ってフォーマット・メソッドのパラメータを指定することも出来ます。
// `2` は asPercent() メソッドの $decimals パラメータの値です。
// 出力: 12.50%
echo Yii::$app->formatter->format(0.125, ['percent', 2]);

補足〺 フォーマッタ・コンポーネントは、エンド・ユーザへの表示用に値をフォーマットすることを目的に設計されています。 ユーザの入力を機械が読み取れる形式にフォーマットしたい場合、また、日付を機械が読み取れる形式にフォーマッ
トしたいだけ、という場合には、 フォーマッタは適切なツールではありません。 日付と数値についてユーザ入力を変換するためには、それぞれ、べどどぜぶちぬどつちぴはひびぜいちぴづざちぬどつちぴはひ と
べどどぜぶちぬどつちぴはひびぜぎふねぢづひざちぬどつちぴはひ を使うことが出来ます。機械が読み取れる日付と時刻のフォーマットの単純な相互変換には、ぐえぐ の つちぴづ〨〩1 関数で十分です。

8.1.1

フォーマッタを構成する

アプリケーションの構成情報 の中で formatter コンポーネントを構成して、 フォーマットの規則をカスタマイズすることが出来ます。例えば、return ['components' => ['formatter' => ['dateFormat' => 'dd.MM.yyyy','decimalSeparator' => ',',
'thousandSeparator' => ' ','currencyCode' => 'EUR',
],
],
];

構成可能なプロパティについては、べどどぜど〱〸のぜうはひねちぴぴづひ を参照してくだ
さい。

8.1.2

日付と時刻の値をフォーマットする

フォーマッタは日付と時刻に関連した下記の出力形式をサポートしています。
• つちぴづ 〭 値は日付としてフォーマットされます。例えば January 01,
2014。
• ぴどねづ 〭 値は時刻としてフォーマットされます。例えば 14:23。
• つちぴづぴどねづ 〭 値は日付および時刻としてフォーマットされます。例えば January 01, 2014 14:23。
1

https://www.php.net/manual/ja/function.date.php〸〮〱〮 データのフォーマット

〴〱〳• ぴどねづびぴちねば 〭 値は ふのどへ タイムスタンプ2 としてフォーマットされます。例えば 1412609982。
• ひづぬちぴどぶづごどねづ 〭 値は、その日時と現在との間隔として、人間に分かりやすい言葉でフォーマットされます。 例えば 1 hour ago。
• つふひちぴどはの 〭 値は継続時間として、人間に分かりやすい言葉でフォーマットされます。例えば 1 day, 2 minutes。
つちぴづ、ぴどねづ、つちぴづぴどねづ メソッドに使われるデフォルトの日時書式は、
フォーマッタの 〤つちぴづうはひねちぴ、 〤ぴどねづうはひねちぴ、〤つちぴづぴどねづうはひねちぴ を構成することで、 グローバルにカスタマイズすることが出来ます。
日付と時刻のフォーマットは、ぉぃさ 構文3 によって指定することが出来ます。 また、ぉぃさ 構文と区別するために php: という接頭辞を付けて、ぐえぐ の つちぴづ〨〩 構文4 を使うことも出来ます。例えば、// ICU 形式
echo Yii::$app->formatter->asDate('now', 'yyyy-MM-dd'); // 2014-10-06// PHP date() 形式
echo Yii::$app->formatter->asDate('now', 'php:Y-m-d'); // 2014-10-06

情報〺 ぐえぐ 形式の書式の文字の中には ぉぃさ でサポートされておらず、従って ぐえぐ どのぴぬ エクステンションでもサポートされていないため、 すどど のフォーマッタで使用できないものがあります。それらの文字のほとんどのもの 〨w〬 t〬 L〬 B〬 u〬 I〬 Z〩 は、日付の書式としては大して有用ではなく、 むしろ日数の計算をするのに使われるものです。しかし、S と U は有用かも知れません。これらの動作は次のようにして達成することが出来ます。
• S は、月の何日目かを示す英語の序数接尾詞序詞 〨すなわ
びぴ〬 のつ〬 ひつ または ぴと 〩 ですが、これの代りに以下のような代替手段が使用出来ます。
$f = Yii::$app->formatter;$d = $f->asOrdinal($f->asDate('2017-05-15', 'php:j'));echo "On the $d day of the month."; // "On the 15th day of themonth." と表示• U、すなわち さのどへ エポックに対しては、ぴどねづびぴちねば 形式
を使うことが出来ます。
複数の言語をサポ ートする必要がある アプリケー ションを扱う場合には、 ロケールご とに異なる日付と時刻のフォ ーマットを指定しなければならないことがよくあります。 この仕事を単純化するためには、〨long、short などの〩 フォーマットのショートカットを代りに使うことが出来ます。 フォーマッタは、現在アクティブな ぬはっちぬづ に従って、
https://ja.wikipedia.org/wiki/UNIX%E6%99%82%E9%96%93
https://unicode-org.github.io/icu/userguide/format_parse/datetime/4
https://www.php.net/manual/ja/function.date.php
2
3

〴〱〴

ぃえぁぐごぅげ 〸〮 データの表示

フォーマットのショートカットを適切なフォーマットに変換します。
フォーマットのショートカットとして、次のものがサポートされています 〨例は en_GB がアクティブなロケールであると仮定したものです〩。
• short〺 日付は 06/10/2014、時刻は 15:58 を出力• medium〺 6 Oct 2014 と 15:58:42 を出力• long〺 6 October 2014 と 15:58:42 GMT を出力• full〺 Monday, 6 October 2014 と 15:58:42 GMT を出力
情報〺 なちたおぐ ロケールでは、次のようになります。
びとはひぴ〺 2014/10/06 と 15:58 ねづつどふね〺 2014/10/06 と 15:58:42 ぬはので〺
2014年10月6日 と 15:58:42 JST てふぬぬ〺 2014年10月6日月曜日 と 15時58分42秒
日本標準時

バージョン 〲〮〰〮〷 以降では、さまざまな暦法に従って日付をフォーマット
することが可能です。 通常とは異なる暦法を使用する方法については、
フォーマッタの 〤っちぬづのつちひ プロパティの ぁぐぉ ドキュメントを参照して下さい。
タイム・ゾーン
日時の値をフォーマットするときに、すどど はその値をターゲット・タイ
ム・ゾーン に変換します。 フォーマットされる日付の値は、タイム・ゾーンが明示的に指定されるか、べどどぜど〱〸のぜうはひねちぴぴづひ〺〺〤つづてちふぬぴごどねづずはのづが構成されるかしていない限り、 さごぃ であると見なされます。
次の例では、ターゲット・タイム・ゾーン が Europe/Berlin に設定されているものとします。
// UNIX タイムスタンプを時刻としてフォーマット
echo Yii::$app->formatter->asTime(1412599260); // 14:41:00// UTC の日付時刻文字列を時刻としてフォーマット
echo Yii::$app->formatter->asTime('2014-10-06 12:41:00'); // 14:41:00// CEST の日付時刻文字列を時刻としてフォーマット
echo Yii::$app->formatter->asTime('2014-10-06 14:41:00 CEST'); // 14:41:00

ぉのては〺 ターゲット・タイム・ゾーン が Asia/Tokyo である場合
は、次のようになります。
echo Yii::$app->formatter->asTime(1412599260); // 21:41:00
echo Yii::$app->formatter->asTime('2014-10-06 12:41:00'); // 21:41:00
echo Yii::$app->formatter->asTime('2014-10-06 21:41:00 JST'); //21:41:00

フォーマッタ・コンポーネントに対して タイム・ゾーン が明示的に設定されていない場合は、 アプリケーションで設定されたタイム・ゾーン〨ぐえぐ の構成で設定されたタイム・ゾーンと同じ〩 が使用されます。

〸〮〱〮 データのフォーマット

〴〱〵補足〺 タイム・ゾーンは世界中のさまざまな政府によって作られる規則に従うものであり、頻繁に変更されるものであるた
め、 あなたのシステムにインストールされたタイム・ゾーンのデータベースが最新の情報を持っていない可能性が大いにあります。 タイム・ゾーン・データベースの更新についての詳細は、 ぉぃさ マニュアル5 で参照することが出来ます。 ぐえぐ
環境を国際化のために設定する も参照してください。

8.1.3

数値をフォーマットする

フォーマッタは、数値に関連した下記の出力フォーマットをサポートしています。
• どのぴづでづひ 〭 値は整数としてフォーマットされます。例えば 42。
• つづっどねちぬ 〭 値は小数点と三桁ごとの区切りを考慮して十進数としてフォーマットされます。 例えば 2,542.123 または 2.542,123。
• ばづひっづのぴ 〭 値は百分率としてフォーマットされます。例えば 42%。
• びっどづのぴどてどっ 〭 値は科学記法による数値としてフォーマットされます。例えば 4.2E4。
• っふひひづのっべ 〭 値は通貨の値としてフォーマットされます。例えば£420.00。 この関数が正しく働くためには、en_GB や en_US のように、ロケールが国コードを含んでいる必要があります。 なぜなら、
この場合は言語だけでは曖昧になるからです。
• びどぺづ 〭 バイト数である値が人間にとって読みやすいサイズとしてフォーマットされます。例えば 410 キビバイト。
• びとはひぴこどぺづ 〭 びどぺづ の短いバージョンです。例えば 410 KiB。
数値のフォーマットに使われる書式は、デフォルトではロケールに従って設定される つづっどねちぬこづばちひちぴはひ と ぴとはふびちのつこづばちひちぴはひ を使って調整することが出来ます。
更に高度な設定のためには、べどどぜど〱〸のぜうはひねちぴぴづひ〺〺〤のふねぢづひうはひねちぴぴづひくばぴどはのびと べどどぜど〱〸のぜうはひねちぴぴづひ〺〺〤のふねぢづひうはひねちぴぴづひごづへぴくばぴどはのび を使って、内部的に使用される ぎふねぢづひうはひねちぴぴづひ クラス6 を構成することが出来ます。
例えば、小数部の最大桁数と最小桁数を調整するためには、次のように
べどどぜど〱〸のぜうはひねちぴぴづひ〺〺〤のふねぢづひうはひねちぴぴづひくばぴどはのび プロパティを構成します。
'numberFormatterOptions' => [NumberFormatter::MIN_FRACTION_DIGITS => 0,
NumberFormatter::MAX_FRACTION_DIGITS => 2,
]

8.1.4

その他のフォーマット

日付〯時刻と数値のフォーマット以外にも、すどど はよく使われるフォー
https://unicode-org.github.io/icu/userguide/datetime/timezone/#updating-the-time-zone-data
6
https://www.php.net/manual/ja/class.numberformatter.php
5〴〱〶

ぃえぁぐごぅげ 〸〮 データの表示

マットをサポートしています。その中には、次のものが含まれます。
• ひちぷ 〭 値はそのまま出力されます。 null 値が のふぬぬいどびばぬちべ を使ってフォーマットされる以外は、何の効果もない擬似フォーマッタです。
• ぴづへぴ 〭 値は えごきが エンコードされます。 これは ぇひどつざどづぷ いちぴち〭
ぃはぬふねの で使われるデフォルトのフォーマットです。
• のぴづへぴ 〭 値は えごきが エンコードされ、 改行文字が強制改行に変換された平文テキストとしてフォーマットされます。
• ばちひちでひちばとび 〭 値は えごきが エンコードされ、 <p> タグに囲まれた段落としてフォーマットされます。
• とぴねぬ 〭 値は じここ 攻撃を避けるために えぴねぬぐふひどてどづひ を使って浄化されます。 ['html', ['Attr.AllowedFrameTargets' => ['_blank']]] のような追加のオプションを渡すことが出来ます。
• づねちどぬ 〭 値は mailto リンクとしてフォーマットされます。
• どねちでづ 〭 値は image タグとしてフォーマットされます。
• ふひぬ 〭 値はハイパーリンクとしてフォーマットされます。
• ぢははぬづちの 〭 値は真偽値としてフォーマットされます。 デフォルトでは、true は Yes、false は No とレンダリングされ、現在のアプリケー
ションの言語に翻訳されます。 この動作は べどどぜど〱〸のぜうはひねちぴぴづひ〺〺〤ぢははぬづちのうはひねちぴ プロパティを構成して調整できます。

8.1.5

値

ぎふぬぬ 値は特殊な方法でフォーマットされます。空文字列を表示する代りに、フォーマッタは のふぬぬ 値を事前定義された文字列 〨そのデフォルト値
は (not set) です〩 に変換し、それを現在のアプリケーションの言語に翻訳します。 この文字列は のふぬぬいどびばぬちべ プロパティを構成してカスタマイズすることが出来ます。

8.1.6

データのフォーマットをローカライズする

既に述べたように、フォーマッタは現在のアクティブな ぬはっちぬづ を使って、 ターゲットの国〯地域にふさわしい値のフォーマットを決定することが出来ます。 例えば、同じ日時の値でも、ロケールによって異なる書式にフォーマットされます。
Yii::$app->formatter->locale = 'en-US';echo Yii::$app->formatter->asDate('2014-01-01'); // 出力: January 1, 2014
Yii::$app->formatter->locale = 'de-DE';echo Yii::$app->formatter->asDate('2014-01-01'); // 出力: 1. Januar 2014
Yii::$app->formatter->locale = 'ru-RU';
echo Yii::$app->formatter->asDate('2014-01-01'); // 出力: 1 января 2014 г.
Yii::$app->formatter->locale = 'ja-JP';echo Yii::$app->formatter->asDate('2014-01-01'); // 出力: 2014/01/01

〸〮〲〮 ページネーション〴〱〷

デフォルトでは、現在のアクティブな ぬはっちぬづ は べどどぜぢちびづぜぁばばぬどっちぴどはの〺〺〤ぬちのでふちでづ の値によって決定されます。 これは べどどぜど〱〸のぜうはひねちぴぴづひ〺〺〤ぬはっちぬづ プロパティを明示的に指定することによってオーバーライドすることが出来ます。
補足〺 すどど のフ ォーマッ タは、ぐえぐ どのぴぬ 拡張7 に依存してデータのフォーマットの ローカライズをサポートしています。ぐえぐ にコンパイルされた ぉぃさ ライブラリのバージョンによってフォーマットの結果が異なる場合がありますので、 あなたの全ての環境で、同じ ぉぃさ バージョンを使うことが推奨されます。 詳細については、ぐえぐ 環境を国際化のために設定
する を参照してください。
どのぴぬ 拡張がインストールされていない場合は、データはローカ
ライズされません。
〱〹〰〱年より前、または、〲〰〳〸年より後の日時の値は、たとえどのぴぬ 拡張がインストールされていても、〳〲〭ぢどぴ システムでは
ローカライズされないことに注意してください。 これは、この場合、ぉぃさ ライブラリが日時の値に対して 〳〲〭ぢどぴ の さぎぉじ
タイムスタンプを使用しているのが原因です。

8.2

ページネーション

一つのページに表示するにはデータの数が多すぎるという場合に、デー
タを複数のページに分割して、それぞれのページでは一部分だけを表示
する、 という戦略がよく使われます。この戦略が ページネーション として知られるものです。
すどど は べどどぜつちぴちぜぐちでどのちぴどはの オブジェクトを使って、ページネーショ
ンのスキームに関する情報を表します。具体的に言えば、• ぴはぴちぬぃはふのぴ データ・アイテムの総数を指定します。 通常、デー
タ・アイテムの総数は、一つのページを表示することが可能なデー
タ・アイテムの数より、ずっと大きなものになることに注意してください。
• ばちでづこどぺづ 各ページが含むアイテムの数を指定します。 デフォルト
値は 〲〰 です。
• ばちでづ 現在のページ番号 〨〰 から始まる〩 を示します。デフォルト値
は 〰 であり、最初のページを意味します。
これらの情報を全て定義した べどどぜつちぴちぜぐちでどのちぴどはの オブジェクトを使って、データの一部分を取得して表示することが出来ます。 例えば、デー
タ・プロバイダからデータを取得する場合であれば、ページネーション
によって提供される値によって、それに対応する OFFSET と LIMIT の句を
いあ クエリに指定することが出来ます。下記に例を挙げます。
7https://www.php.net/manual/ja/book.intl.php〴〱〸ぃえぁぐごぅげ 〸〮 データの表示

use yii\data\Pagination;// status = 1 である全ての記事を取得する DB クエリを構築する$query = Article::find()->where(['status' => 1]);// 記事の総数を取得する (ただし、記事のデータはまだ取得しない)$count = $query->count();// 記事の総数を使ってページネーション・オブジェクトを作成する$pagination = new Pagination(['totalCount' => $count]);// ページネーションを使ってクエリの OFFSET と LIMIT を修正して記事を取得する$articles = $query->offset($pagination->offset)->limit($pagination->limit)->all();

上記の例で返される記事のページ番号はどうなるでしょう〿 それは pageという名前のクエリ・パラメータがリクエストに含まれるかどうかによって決ります。 デフォルトでは、ページネーション・オブジェクトは
ばちでづ に page パラメータの値をセットしようと試みます。 そして、このパラメータが提供されていない場合には、デフォルト値である 〰 が使用されます。
ページネーションをサポートする さぉ 要素の構築を容易にするために、すどど はページ・ボタンのリストを表示する べどどぜぷどつでづぴびぜがどのにぐちでづひ
ウィジェットを提供しています。 これは、ユーザがページ・ボタンをクリックして、どのページを表示すべきかを指示することが出来るものです。 このウィジェットは、ページネーション・オブジェクトを受け取って、現在のページ番号が何であるかを知り、何個のページ・ボタンを表示すべきかを知ります。 例えば、
use yii\widgets\LinkPager;echo LinkPager::widget(['pagination' => $pagination,]);

さぉ 要素を手動で構築したい場合は、べどどぜつちぴちぜぐちでどのちぴどはの〺〺っひづちぴづさひぬ〨〩を使って、いろんなページに跳ぶ さげが を作成することが出来ます。 このメソッドは ばちでづ パラメータを要求し、その ばちでづ パラメータを含む正
しくフォーマットされた さげが を作成します。 例えば、// 作成される URL が使用すべきルートを指定する// 指定しない場合は、現在リクエストされているルートが使用される$pagination->route = 'article/index';// /index.php?r=article%2Findex&page=100 を表示
echo $pagination->createUrl(100);// /index.php?r=article%2Findex&page=101 を表示
echo $pagination->createUrl(101);〸〮〳〮 並べ替え〴〱〹ヒント〺 page クエリ・パラメータの名前をカスタマイズする
ためには、ページネーション・オブジェクトを作成する際にばちでづぐちひちね プロパティを構成します。

8.3

並べ替え

複数のデータ行を表示する際に、エンド・ユーザによって指定されるカラムに従ってデータを並べ替えなければならないことがよくあります。
すどど は べどどぜつちぴちぜこはひぴ オブジェクトを使って並べ替えのスキーマに関する情報を表します。 具体的に言えば、• ちぴぴひどぢふぴづび データの並べ替えに使用できる 属性 を指定します。 単
純で良ければ、モデルの属性 をこの属性とすることが出来ます。
また、複数のモデル属性や いあ のカラムを結合した合成的な属性を指定することも出来ます。詳細については後述します。
• ちぴぴひどぢふぴづくひつづひび 各属性について、 現在リクエストされている並べ
替えの方向を指定します。
• はひつづひび 並べ替えの方向をカラムを使う低レベルな形式で示します。
べどどぜつちぴちぜこはひぴ を使用するためには、最初にどの属性が並べ替え可能であるかを宣言します。 次に、現在リクエストされている並べ替え情報を
ちぴぴひどぢふぴづくひつづひび または はひつづひび から取得して、データのクエリをカスタ
マイズします。例えば、
use yii\data\Sort;$sort = new Sort(['attributes' => ['age','name' => ['asc' => ['first_name' => SORT_ASC, 'last_name' => SORT_ASC],'desc' => ['first_name' => SORT_DESC, 'last_name' => SORT_DESC],'default' => SORT_DESC,'label' => '氏名',
],
],
]);
$articles = Article::find()->where(['status' => 1])->orderBy($sort->orders)->all();

上記の例では、こはひぴ オブジェクトに対して二つの属性が宣言されています。すなわち、age と name です。
age 属性は Article アクティブ・レコード・クラスの age 属性に対応す
る 単純な 属性です。 これは、次の宣言と等価です。

〴〲〰

ぃえぁぐごぅげ 〸〮 データの表示'age' => ['asc' => ['age' => SORT_ASC],'desc' => ['age' => SORT_DESC],'default' => SORT_ASC,'label' => Inflector::camel2words('age'),]name 属性は Article の first_name と last_name によって定義される 合成的な 属性です。 これは次のような配列構造を使って宣言されています。
• asc および desc の要素は、それぞれ、この属性を昇順および降順に並べ替える方法を指定します。 この値が、データの並べ替えに使用されるべき実際のカラムと方向を表します。 一つまたは複数のカラムを指定して、単純な並べ替えや合成的な並べ替えを示すことが出来ます。
• default 要素は、最初にリクエストされたときの属性の並べ替えに使用されるべき方向を指定します。 デフォルト値は昇順です。 つまり、以前に並べ替えられたことがない状態でこの属性による並べ替
えをリクエストすると、この属性の昇順に従ってデータが並べ替えられることになります。
• label 要素は、並べ替えのリンクを作成するために べどどぜつちぴちぜこはひぴ〺〺ぬどのに〨〩 を呼んだときに、どういうラベルを使用すべきかを指定するものです。 設定されていない場合は、べどどぜとづぬばづひびぜぉのてぬづっぴはひ〺〺っちねづぬ〲ぷはひつび〨〩 が呼ばれて、属性名からラベルが生成されます。
ラベルは えごきが エンコードされないことに注意してください。
情報〺 はひつづひび の値をデータベースのクエリに直接に供給して、 ORDER BY 句を構築することが出来ます。 データベースのクエリが認識できない合成的な属性が入っている場合がある
ため、 ちぴぴひどぢふぴづくひつづひび を使ってはいけません。
べどどぜつちぴちぜこはひぴ〺〺ぬどのに〨〩 を呼んでハイパーリンクを生成すれば、それをクリックして、指定した属性によるデータの並べ替えをリクエストする
ことが出来るようになります。 べどどぜつちぴちぜこはひぴ〺〺っひづちぴづさひぬ〨〩 を呼んで並べ替えを実行する さげが を生成することも出来ます。 例えば、// 生成される URL が使用すべきルートを指定する// これを指定しない場合は、現在リクエストされているルートが使用される$sort->route = 'article/index';// 氏名による並べ替えと年齢による並べ替えを実行するリンクを表示
echo $sort->link('name') . ' | ' . $sort->link('age');// /index.php?r=article%2Findex&sort=age を表示
echo $sort->createUrl('age');

べどどぜつちぴちぜこはひぴ は、リクエストの sort クエリ・パラメータをチェックして、どの属性による並べ替えがリクエストされたかを判断します。 こ〸〮〴〮 データ・プロバイダ〴〲〱のクエリ・パラメータが存在しない場合のデフォルトの並べ替え方法は
べどどぜつちぴちぜこはひぴ〺〺〤つづてちふぬぴくひつづひ によって指定することが出来ます。 また、びはひぴぐちひちね プロパティを構成して、このクエリ・パラメータの名前をカスタマイズすることも出来ます。

8.4

データ・プロバイダ

ページネーション と 並べ替え のセクションにおいて 、エンド・ユー
ザが特定のページのデータを選んで表示し、いずれかのカラムによってデータを並べ替えることが出来るようにする方法を説明しました。 デー
タのページネーションと並べ替えは非常によくあるタスクですから、すどどはこれをカプセル化した一連の データ・プロバイダ を提供しています。
データ・プロバイダは べどどぜつちぴちぜいちぴちぐひはぶどつづひぉのぴづひてちっづ を実装するクラスであり、主として、ページ分割され並べ替えられたデータの取得をサポートするものです。 通常は、データ・ウィジェット と共に使用して、 エンド・ユーザが対話的にデータのページネーションと並べ替えをすることが出来るようにします。
すどど のリリースには次のデータ・プロバイダのクラスが含まれています。
• べどどぜつちぴちぜぁっぴどぶづいちぴちぐひはぶどつづひ〺 べどどぜつぢぜけふづひべ または べどどぜつぢぜぁっぴどぶづけふづひべを使ってデータベースからデータを取得して、 配列または アク
ティブ・レコード・インスタンスの形式でデータを返します。
• べどどぜつちぴちぜこぱぬいちぴちぐひはぶどつづひ〺 こけが 文を実行して、データベースのデータを配列として返します。
• べどどぜつちぴちぜぁひひちべいちぴちぐひはぶどつづひ〺 大きな配列を受け取り、ページネー
ションと並べ替えの指定に基づいて、 一部分を切り出して返します。
これら全てのデータ・プロバイダの使用方法は、次の共通のパターンを持っています。
// ページネーションと並べ替えのプロパティを構成してデータ・プロバイダを作成する$provider = new XyzDataProvider(['pagination' => [...],'sort' => [...],]);// ページ分割されて並べ替えられたデータを取得する$models = $provider->getModels();// 現在のページにあるデータ・アイテムの数を取得する$count = $provider->getCount();// 全ページ分のデータ・アイテムの総数を取得する$totalCount = $provider->getTotalCount();

データ・プロバイダのページネーションと並べ替えの振る舞いを指定するためには、その ばちでどのちぴどはの と びはひぴ のプロパティを構成します。 二つ〴〲〲

ぃえぁぐごぅげ 〸〮 データの表示のプロパティは、それぞれ、べどどぜつちぴちぜぐちでどのちぴどはの と べどどぜつちぴちぜこはひぴ の構成情報に対応します。 これらを false に設定して、ページネーション
や並べ替えの機能を無効にすることも出来ます。
データ・ウィジェット、例えば べどどぜでひどつぜぇひどつざどづぷ は、dataProviderという名前のプロパティを持っており、 これにデータ・プロバイダのイ
ンスタンスを受け取らせて、それが提供するデータを表示させることが出来ます。例えば、
echo yii\grid\GridView::widget(['dataProvider' => $dataProvider,]);

これらのデータ・プロバイダの主たる相異点は、データソースがどのように指定されるかという点にあります。 次に続く項において、各デー
タ・プロバイダの詳細な使用方法を説明します。

8.4.1

アクティブ・データ・プロバイダ

べどどぜつちぴちぜぁっぴどぶづいちぴちぐひはぶどつづひ を使用するためには、その ぱふづひべ プロパティを構成しなければなりません。 これは、べどどぜつぢぜけふづひべ または べどど
ぜつぢぜぁっぴどぶづけふづひべ のオブジェクトを取ることが出来ます。 前者であれ
ば、返されるデータは配列になります。後者であれば、返されるデータ
は配列または アクティブ・レコード インスタンスとすることが出来ます。例えば、
use yii\data\ActiveDataProvider;$query = Post::find()->where(['status' => 1]);$provider = new ActiveDataProvider(['query' => $query,'pagination' => ['pageSize' => 10,],'sort' => ['defaultOrder' => ['created_at' => SORT_DESC,'title' => SORT_ASC,]],]);// Post オブジェクトの配列を返す$posts = $provider->getModels();

上記の例における $query が次のコードによって作成される場合は、提供されるデータは生の配列になります。
use yii\db\Query;$query = (new Query())->from('post')->where(['status' => 1]);

〸〮〴〮 データ・プロバイダ〴〲〳

補足〺 クエリが既に orderBy 句を指定しているものである場
合、〨sort の構成を通して〩 エンド・ユーザによって与えられる並べ替えの指定は、 既存の orderBy 句に追加されます。一方、limit と offset の句が存在している場合は、 〨pagenation の構成を通して〩 エンド・ユーザによって指定されるページネー
ションのリクエストによって上書きされます。
デフォルトでは、べどどぜつちぴちぜぁっぴどぶづいちぴちぐひはぶどつづひ はデータベース接続として db アプリケーション・コンポーネントを使用します。 べどどぜつちぴち
ぜぁっぴどぶづいちぴちぐひはぶどつづひ〺〺〤つぢ プロパティを構成すれば、別のデータベース
接続を使用することが出来ます。

8.4.2

SQL データ・プロバイダ

べどどぜつちぴちぜこぱぬいちぴちぐひはぶどつづひ は、生の こけが 文を使用して、必要なデータを取得します。 このデータ・プロバイダは、びはひぴ と ばちでどのちぴどはの の指定に基づいて、こけが 文の ORDER BY と OFFSET/LIMIT の句を修正し、 指定された順序に並べ替えられたデータを要求されたページの分だけ取得します。
べどどぜつちぴちぜこぱぬいちぴちぐひはぶどつづひ を使用するためには、びぱぬ プロパティだ
けでなく、 ぴはぴちぬぃはふのぴ プロパティを指定しなければなりません。例えば、use yii\data\SqlDataProvider;$count = Yii::$app->db->createCommand('
SELECT COUNT(*) FROM post WHERE status=:status', [':status' => 1])->queryScalar();$provider = new SqlDataProvider(['sql' => 'SELECT * FROM post WHERE status=:status','params' => [':status' => 1],'totalCount' => $count,'pagination' => ['pageSize' => 10,],'sort' => ['attributes' => ['title','view_count','created_at',
],
],
]);
// データ行の配列を返す$models = $provider->getModels();

情報〺 ぴはぴちぬぃはふのぴ プロパティは、データにページネーション
を適用しなければならない 場合にだけ要求されます。これ〴〲〴

ぃえぁぐごぅげ 〸〮 データの表示
は、びぱぬ によって指定される こけが 文は、 現在要求されているページのデータだけを返すように、データ・プロバイダによって修正されてしまうからです。 データ・プロバイダは、
総ページ数を正しく計算するためには、データ・アイテムの総数を知る必要があります。

8.4.3

配列データ・プロバイダ

べどどぜつちぴちぜぁひひちべいちぴちぐひはぶどつづひ は、一つの大きな配列を扱う場合に最も適しています。 このデータ・プロバイダによって、一つまたは複数のカラムで並べ替えた配列データの 〱 ページ分を返すことが出来ます。 べどど
ぜつちぴちぜぁひひちべいちぴちぐひはぶどつづひ を使用するためには、全体の大きな配列として ちぬぬきはつづぬび プロパティを指定しなければなりません。 この大きな配列の要素は、連想配列 〨例えば いぁく のクエリ結果〩 またはオブジェクト 〨例
えば アクティブ・レコード インスタンス〩 とすることが出来ます。例えば、use yii\data\ArrayDataProvider;$data = [['id' => 1, 'name' => 'name 1', ...],['id' => 2, 'name' => 'name 2', ...],...
['id' => 100, 'name' => 'name 100', ...],];$provider = new ArrayDataProvider(['allModels' => $data,'pagination' => ['pageSize' => 10,],'sort' => ['attributes' => ['id', 'name'],],]);// 現在リクエストされているページの行を返す$rows = $provider->getModels();補足〺 アクティブ・データ・プロバイダ および こけが データ・プロバイダ と比較すると、 配列データ・プロバイダは効率の面では劣ります。何故なら、全ての データをメモリにロードしなければならないからです。

8.4.4

データのキーを扱う

データ・プロバイダによって返されたデータ・アイテムを使用する場
合、各データ・アイテムを一意のキーで 特定しなければならないことがよくあります。例えば、データ・アイテムが顧客情報を表す場合、顧客〸〮〴〮 データ・プロバイダ〴〲〵

ぉい を各顧客データのキーとして使用したいでしょう。データ・プロバイ
ダは、べどどぜつちぴちぜいちぴちぐひはぶどつづひぉのぴづひてちっづ〺〺でづぴきはつづぬび〨〩 によって返されたデータ・アイテムに対応するそのようなキーのリストを返すことが出来ます。例えば、
use yii\data\ActiveDataProvider;$query = Post::find()->where(['status' => 1]);$provider = new ActiveDataProvider(['query' => $query,]);// Post オブジェクトの配列を返す$posts = $provider->getModels();// $post に対応するプライマリ・キーの値を返す$ids = $provider->getKeys();

上記の例では、べどどぜつちぴちぜぁっぴどぶづいちぴちぐひはぶどつづひ に対して べどどぜつぢぜぁっぴどぶづけふづひべ
オブジェクトを供給していますから、 キーとしてプライマリ・キーの値を返すのが理にかなっています。キーの値の計算方法を明示的に指定するために、 べどどぜつちぴちぜぁっぴどぶづいちぴちぐひはぶどつづひ〺〺〤にづべ にカラム名を設定した
り、キーの値を計算するコーラブルを設定したりすることも出来ます。
例えば、// "slug" カラムをキーの値として使用する$provider = new ActiveDataProvider(['query' => Post::find(),'key' => 'slug',]);// md5(id) の結果をキーの値として使用する$provider = new ActiveDataProvider(['query' => Post::find(),'key' => function ($model) {return md5($model->id);
}
]);

8.4.5

カスタム・データ・プロバイダを作成する

あなた自身のカスタム・データ・プロバイダ・クラスを作成するためには、べどどぜつちぴちぜいちぴちぐひはぶどつづひぉのぴづひてちっづ を実装しなければなりません。
べどどぜつちぴちぜあちびづいちぴちぐひはぶどつづひ を拡張するのが比較的簡単な方法です。そうすれば、データ・プロバイダのコアのロジックに集中することが出来ます。 具体的に言えば、実装する必要があるのは、主として次のメソッドです。
• ばひづばちひづきはつづぬび〨〩〺 現在のページで利用できるデータ・モデルを準備して、 それを配列として返します。

〴〲〶ぃえぁぐごぅげ 〸〮 データの表示• ばひづばちひづかづべび〨〩〺 現在利用できるデータ・モデルの配列を受け取って、 それと関連付けられるキーの配列を返します。
• ばひづばちひづごはぴちぬぃはふのぴ〺 データ・プロバイダにある データ・モデルの総数を示す値を返します。
下記は、ぃこざ ファイルを効率的に読み出すデータ・プロバイダのサンプ
ルです。
<?php
use yii\data\BaseDataProvider;class CsvDataProvider extends BaseDataProvider{/*** @var string 読み出す CSV ファイルの名前*/
public $filename;/*** @var string|callable キーカラムの名前またはそれを返すコーラブル*/
public $key;/*** @var SplFileObject*/
protected $fileObject; // ファイルの特定の行までシークするのに
SplFileObject が非常に便利/*** {@inheritdoc}*/
public function init(){
parent::init();}// ファイルを開く$this->fileObject = new SplFileObject($this->filename);/*** {@inheritdoc}*/
protected function prepareModels(){$models = [];$pagination = $this->getPagination();if ($pagination === false) {// ページネーションが無い場合、全ての行を読む
while (!$this->fileObject->eof()) {$models[] = $this->fileObject->fgetcsv();$this->fileObject->next();〸〮〴〮 データ・プロバイダ}} else {// ページネーションがある場合、一つのページだけを読む$pagination->totalCount = $this->getTotalCount();$this->fileObject->seek($pagination->getOffset());$limit = $pagination->getLimit();}}for ($count = 0; $count < $limit; ++$count) {$models[] = $this->fileObject->fgetcsv();$this->fileObject->next();}

return $models;/*** {@inheritdoc}*/
protected function prepareKeys($models){if ($this->key !== null) {$keys = [];foreach ($models as $model) {if (is_string($this->key)) {$keys[] = $model[$this->key];} else {$keys[] = call_user_func($this->key, $model);}}}return $keys;} else {return array_keys($models);}/*** {@inheritdoc}*/
protected function prepareTotalCount(){$count = 0;
while (!$this->fileObject->eof()) {$this->fileObject->next();++$count;}}}

return $count;

〴〲〷

〴〲〸

ぃえぁぐごぅげ 〸〮 データの表示

8.4.6

データ・フィルタを使ってデータ・プロバイダをフィルタリングする

データをフィルタリングする や 独立したフィルタ・フォーム で述べられているように、 アクティブ・データ・プロバイダの条件を手作業で構築することも可能ですが、 柔軟なフィルタ条件を必要とする場合には、すどどが持っているデータ・フィルタが非常に役に立ちます。 データ・フィル
タは次のようにして使うことが出来ます。
$filter = new ActiveDataFilter(['searchModel' => 'app\models\PostSearch']);$filterCondition = null;// どのようなソースからでもフィルタをロードすることが出来ます。
// 例えば、リクエスト・ボディの JSON からロードしたい場合は、// 下記のように Yii::$app->request->getBodyParams() を使います。
if ($filter->load(\Yii::$app->request->get())) {$filterCondition = $filter->build();
if ($filterCondition === false) {// シリアライザがエラーを抽出するだろう
return $filter;}}$query = Post::find();if ($filterCondition !== null) {$query->andWhere($filterCondition);}
return new ActiveDataProvider(['query' => $query,]);
PostSearch モデルは、どういうプロパティと値がフィルタリングに使用できるかを定義するという目的のために使用されています。
use yii\base\Model;
class PostSearch extends Model{public $id;
public $title;}

public function rules(){return [['id', 'integer'],['title', 'string', 'min' => 2, 'max' => 200],
];
}

〴〲〹

〸〮〵〮 データ・ウィジェット

データ・フィルタは極めて柔軟で、どのようにして条件が構築される
か、また、どんな演算子が許容されるかをカスタマイズすることが可能です。 詳細は ぁぐぉ リファレンスで べどどぜつちぴちぜいちぴちうどぬぴづひ を参照して下
さい。

8.5

データ・ウィジェット

すどど はデータを表示するために使うことが出来る一連の ウィジェット を提供しています。 いづぴちどぬざどづぷ は、単一のレコードのデータを表示するのに使うことが出来ます。 それに対して、がどびぴざどづぷ と ぇひどつざどづぷ は、複数のデータ・レコードをリストまたはテーブルで表示することが出来るもので、 ページネーション、並べ替え、フィルタリングなどの機能を提供するものです。

8.5.1

DetailView

いづぴちどぬざどづぷ は単一のデータ モデル の詳細を表示します。
モデルを標準的な書式で表示する場合 〨例えば、全てのモデル属性をそれぞれテーブルの一行として表示する場合〩 に最も適しています。 モ
デルは べどどぜぢちびづぜきはつづぬ またはそのサブ・クラス、例えば アクティブ・レコード のインスタンスか、連想配列かのどちらかにすることが出来ます。
いづぴちどぬざどづぷ は べどどぜぷどつでづぴびぜいづぴちどぬざどづぷ〺〺〤ちぴぴひどぢふぴづび プロパティを使って、モデルのどの属性が表示されるべきか、また、どういうフォー
マットで表示されるべきかを決定します。 利用できるフォーマットのオプションについては、フォーマッタのセクション を参照してください。
次に いづぴちどぬざどづぷ の典型的な用例を示します。
echo DetailView::widget(['model' => $model,'attributes' => ['title',
文テキストで)'description:html',
性は HTML としてフォーマットされる[の名前'label' => '所有者','value' => $model->owner->name,'contentOptions' => ['class' => 'bg-red'],
タマイズする HTML 属性'captionOptions' => ['tooltip' => 'Tooltip'],
カスタマイズする HTML 属性],'created_at:datetime',
datetime としてフォーマットされる// title 属性 (平// description 属// モデルの所有者// 値のタグをカス// ラベルのタグを// 作成日時は

〴〳〰

]);

ぃえぁぐごぅげ 〸〮 データの表示],

べどどぜぷどつでづぴびぜぇひどつざどづぷ が 一 組 の モ デ ル を 処 理 す る の と は 異 な っ て 、
いづぴちどぬざどづぷ は一つのモデルしか処理しないということを覚えておいてください。 表示すべきモデルはビューの変数としてアクセスできる$model 一つだけですから、たいていの場合、クロージャを使用する必要はありません。
しかし、クロージャが役に立つ場合もあります。例えば、visible が指定されており、それが false と評価される場合には value の計算を避けた
い場合です。
echo DetailView::widget(['model' => $model,'attributes' => [['attribute' => 'owner','value' => function ($model) {return $model->owner->name;},'visible' => \Yii::$app->user->can('posts.owner.view'),
],
],
]);

8.5.2

ListView

がどびぴざどづぷ ウィジェットは、データ・プロバイダ からのデータを表示するのに使用されます。 各データ・モデルは指定された ビュー・ファイ
ル を使って表示されます。 がどびぴざどづぷ は、特に何もしなくても、ページ
ネーション、並べ替え、フィルタリングなどの機能を提供してくれます
ので、 エンド・ユーザに情報を表示するためにも、データ管理 さぉ を作成するためにも、非常に便利なウィジェットです。
典型的な使用方法は以下の通りです。
use yii\widgets\ListView;
use yii\data\ActiveDataProvider;$dataProvider = new ActiveDataProvider(['query' => Post::find(),'pagination' => ['pageSize' => 20,],]);
echo ListView::widget(['dataProvider' => $dataProvider,'itemView' => '_post',]);_post ビューは次のような内容を含むことが出来ます。

〸〮〵〮 データ・ウィジェット

〴〳〱

<?php
use yii\helpers\Html;
use yii\helpers\HtmlPurifier;?><div class="post"><h2><? = Html::encode($model->title) ?> </h2><? = HtmlPurifier::process($model->text) ?></div>

上記のビュー・ファイルでは、現在のデータ・モデルを $model として
アクセスすることが出来ます。追加で次のものを利用することも出来ます。
• $key〺 ねどへづつ 〭 データ・アイテムと関連付けられたキーの値。
• $index〺 どのぴづでづひ 〭 データ・プロバイダによって返されるアイテムの配列の 〰 から始まるインデックス。
• $widget〺 がどびぴざどづぷ 〭 ウィジェットのインスタンス。
追加のデータを各ビューに渡す必要がある場合は、次のように、〤ぶどづぷぐちひちねびを使って「キー・値」のペアを渡すことが出来ます。
echo ListView::widget(['dataProvider' => $dataProvider,'itemView' => '_post','viewParams' => ['fullView' => true,'context' => 'main-page',// ...
],]);

このようにすると、これらをビューで変数として利用できるようになり
ます。

8.5.3

GridView

データ・グリッドすなわち ぇひどつざどづぷ は すどど の最も強力なウィジェットの一つです。これは、システムの管理セクションを素速く作らねばならな
い時に、 この上なく便利なものです。このウィジェットは データ・プロ
バイダ からデータを受けて、 テーブルの形式で、行ごとに一組の カラ
ム を使ってデータを表示します。
テーブルの各行が一つのデータ・アイテムを表します。そして、一つのカラムは通常はアイテムの一属性を表します 〨カラムの中に、複数の属性を組み合わせた複雑な式に対応するものや、静的なテキストを表すものを含めることも出来ます〩。
ぇひどつざどづぷ を使うために必要な最小限のコードは次のようなものです。
use yii\grid\GridView;
use yii\data\ActiveDataProvider;〴〳〲

ぃえぁぐごぅげ 〸〮 データの表示$dataProvider = new ActiveDataProvider(['query' => Post::find(),'pagination' => ['pageSize' => 20,],]);
echo GridView::widget(['dataProvider' => $dataProvider,]);

上記のコードは、最初にデータ・プロバイダを作成し、次に ぇひどつざどづぷ を使って、データ・プロバイダから受け取る全ての行の全ての属性を表示するものです。 表示されるテーブルには、特に何も設定しなくても、並べ替えとページネーションの機能が装備されます。
グリッドのカラム
グリッドのテーブルのカラムは べどどぜでひどつぜぃはぬふねの クラスとして表現され、ぇひどつざどづぷ の構成情報の っはぬふねのび プロパティで構成されます。カラム
は、タイプや設定の違いに応じて、 データをさまざまな形で表現することが出来ます。デフォルトのクラスは べどどぜでひどつぜいちぴちぃはぬふねの です。 これは、モデルの一つの属性を表現し、その属性による並べ替えとフィルタリングを可能にするものです。
echo GridView::widget(['dataProvider' => $dataProvider,'columns' => [['class' => 'yii\grid\SerialColumn'],// $dataProvider に含まれるデータによって定義される単純なカラム// モデルのカラムのデータが使われる'id','username',// 複雑なカラム定義['class' => 'yii\grid\DataColumn', // 省略可。これがデフォルト値。
'value' => function ($data) {return $data->name; // 配列データの場合は $data['name']。例えば、SqlDataProvider を使う場合。
},
],
],
]);

構成情報の っはぬふねのび の部分が指定されない場合は、すどど は、 データ・プ
ロバイダのモデルの表示可能な全てのカラムを表示しようとすることに注意してください。

〸〮〵〮 データ・ウィジェット

〴〳〳カラム・クラス
グリッドのカラムは、いろいろなカラム・クラスを使うことでカスタマ
イズすることが出来ます。
echo GridView::widget(['dataProvider' => $dataProvider,'columns' => [['class' => 'yii\grid\SerialColumn', // <-- ここ// ここで追加のプロパティを構成することが出来ます],

すどど によって提供されるカラム・クラスを以下で見ていきますが、それらに加えて、あなた自身のカラム・クラスを作成することも出来ます。
全てのカラム・クラスは べどどぜでひどつぜぃはぬふねの を拡張するものですので、グリッドのカラムを構成するときに設定できる 共通のオプションがいく
つかあります。
• とづちつづひ によって、ヘッダ行のコンテントを設定することが出来ます。
• てははぴづひ によって、フッタ行のコンテントを設定することが出来ます。
• ぶどびどぢぬづ はカラムの可視性を定義します。
• っはのぴづのぴ によって、行のデータを返す有効な ぐえぐ コールバックを渡すことが出来ます。書式は以下の通りです。
function ($model, $key, $index, $column) {return '文字列';}

下記のオプションに配列を渡して、コンテナ要素のさまざまな えごきが オ
プションを指定することが出来ます。
• とづちつづひくばぴどはのび• てははぴづひくばぴどはのび• てどぬぴづひくばぴどはのび• っはのぴづのぴくばぴどはのび
データ・カラム データ・カラム は、データの表示と並べ替えに使用されます。 これがデフォルトのカラムタイプですので、これを使用するときはクラスの指定を省略することが出来ます。
データ・カラムの主要な設定項目は、その てはひねちぴ プロパティです。
その値が、デフォルトでは うはひねちぴぴづひ である formatter アプリケーショ
ン・コンポーネント のメソッドに対応します。
echo GridView::widget(['columns' => [['attribute' => 'name','format' => 'text'〴〳〴ぃえぁぐごぅげ 〸〮 データの表示
],
[

]);

],

'attribute' => 'birthday','format' => ['date', 'php:Y-m-d']],'created_at:datetime', // shortcut format['label' => '教育','attribute' => 'education','filter' => ['0' => '初等教育', '1' => '中等教育', '2' => '高等教
育'],'filterInputOptions' => ['prompt' => '全ての教育', 'class' =>'form-control', 'id' => null]],

上記において、text は べどどぜど〱〸のぜうはひねちぴぴづひ〺〺ちびごづへぴ〨〩 に対応し、カラムの値が最初の引数として渡されます。 二番目のカラムの定義では、dateが べどどぜど〱〸のぜうはひねちぴぴづひ〺〺ちびいちぴづ〨〩 に対応します。 カラムの値が、ここでも、最初の引数として渡され、〧ばとば〺す〭ね〭つ〧 が二番目の引数の値として渡されます。
利用できるフォーマッタの一覧については、データのフォーマット のセクションを参照してください。
データカラムを構成するためには、ショートカット形式を使うことも出来ます。 それについては、っはぬふねのび の ぁぐぉ ドキュメントで説明されています。
フィルタ・インプットの えごきが を制御するためには、てどぬぴづひ とてどぬぴづひぉのばふぴくばぴどはのび を使用して下さい。
デフォルトでは、カラム・ヘッダは べどどぜつちぴちぜこはひぴ〺〺ぬどのに〨〩 によってレンダリングされますが、べどどぜでひどつぜぃはぬふねの〺〺〤とづちつづひ を使って調整することが出来ます。 ヘッダのテキストを変更するには、上の例のよ
うに、べどどぜでひどつぜいちぴちぃはぬふねの〺〺〤ぬちぢづぬ を設定しなければなりません。 デフォルトでは、ラベルはデータ・モデルによって設定されます。詳細は
べどどぜでひどつぜいちぴちぃはぬふねの〺〺でづぴえづちつづひぃづぬぬがちぢづぬ〨〩 を参照して下さい。
アクション・カラム アクション・カラム は、各行について、更新や削除などのアクション・ボタンを表示します。
echo GridView::widget(['dataProvider' => $dataProvider,'columns' => [['class' => 'yii\grid\ActionColumn',// ここで追加のプロパティを構成することが出来ます],

構成が可能なプロパティは、以下の通りです。

〸〮〵〮 データ・ウィジェット

〴〳〵• っはのぴひはぬぬづひ は、アクションを処理すべきコントローラの ぉい です。
設定されていない場合は、現在アクティブなコントローラが使われます。
• ぴづねばぬちぴづ は、アクション・カラムの各セルを構成するのに使用されるテンプレートを定義します。 波括弧に囲まれたトークンは、コントローラのアクション ぉい として扱われます 〨アクション・
カラムのコンテキストでは ボタンの名前 とも呼ばれます〩。 これらは、ぢふぴぴはのび によって定義される、対応するボタン表示コール
バックによって置き換えられます。 例えば、{view} というトーク
ンは、buttons['view'] のコールバックの結果によって置き換えられます。 コールバックが見つからない場合は、トークンは空文字列
によって置き換えられます。デフォルトのテンプレートは {view}{update} {delete} です。
• ぢふぴぴはのび はボタン表示コールバックの配列です。 配列のキーはボタンの名前 〨波括弧を除く〩 であり、値は対応するボタン表示コール
バックです。コールバックは下記のシグニチャを使わなければなりません。
function ($url, $model, $key) {// ボタンの HTML コードを返す}

上記のコードで、$url はカラムがボタンのために生成する さげが、$modelは現在の行に表示されるモデル・オブジェクト、 そして $key は
データ・プロバイダの配列の中にあるモデルのキーです。
• ふひぬぃひづちぴはひ は、指定されたモデルの情報を使って、ボタンの さげがを生成するコールバックです。 コールバックのシグニチャは べどど
ぜでひどつぜぁっぴどはのぃはぬふねの〺〺っひづちぴづさひぬ〨〩 のそれと同じでなければなりま
せん。 このプロパティが設定されていないときは、ボタンの さげがは べどどぜでひどつぜぁっぴどはのぃはぬふねの〺〺っひづちぴづさひぬ〨〩 を使って生成されます。
• ぶどびどぢぬづあふぴぴはのび は、各ボタンの可視性の条件を定義する配列です。 配列のキーはボタンの名前 〨波括弧を除く〩 であり、値は真偽
値 true〯false または無名関数です。 ボタンの名前がこの配列の中で指定されていない場合は、デフォルトで、ボタンが表示されます。
コールバックは次のシグニチャを使わなければなりません。
function ($model, $key, $index) {return $model->status === 'editable';}

または、真偽値を渡すことも出来ます。
[]'update' => \Yii::$app->user->can('update')

チェックボックス・カラム チェックボックス・カラム はチェックボッ
クスのカラムを表示します。

〴〳〶

ぃえぁぐごぅげ 〸〮 データの表示

ぇひどつざどづぷ に ぃとづっにぢはへぃはぬふねの を追加するためには、以下のようにして、っはぬふねのび 構成情報にカラムを追加します。
echo GridView::widget(['id' => 'grid','dataProvider' => $dataProvider,'columns' => [// ...
['class' => 'yii\grid\CheckboxColumn',// ここで追加のプロパティを構成することが出来ます],],

ユーザはチェックボックスをクリックして、グリッドの行を選択することが出来ます。 選択された行は、次の おちぶちこっひどばぴ コードを呼んで取得することが出来ます。
var keys = $('#grid').yiiGridView('getSelectedRows');// keys は選択された行と関連付けられたキーの配列

シリアル・カラム シリアルカラム は、1 から始まる行番号を表示します。
使い方は、次のように、とても簡単です。
echo GridView::widget(['dataProvider' => $dataProvider,'columns' => [['class' => 'yii\grid\SerialColumn'], // <-- ここ// ...

データを並べ替える
補足〺 このセクションはまだ執筆中です。
• とぴぴばび〺〯〯でどぴとふぢ〮っはね〯べどどびはてぴ〯べどど〲〯どびびふづび〯〱〵〷〶
データをフィルタリングする
データをフィルタリングするためには、ぇひどつざどづぷ は検索基準を表す モデ
ル を必要とします。 検索基準は、通常は、グリッド・ビューのテーブルのフィルタのフィールドから取得されます。 アクティブ・レコード を使用している場合は、必要な機能を提供する検索用のモデル・クラスを 作成するのが一般的なプラクティスです 〨あなたに代って ぇどど が生成してくれます〩。 このクラスが、グリッド・ビューのテーブルに表示されるフィ
ルタ・コントロールのための検証規則を定義し、 検索基準に従って修正されたクエリを持つデータ・プロバイダを返す search() メソッドを提供します。
Post モデルに対して検索機能を追加するために、次の例のようにして、PostSearch モデルを作成することが出来ます。

〸〮〵〮 データ・ウィジェット

〴〳〷

<?php
namespace app\models;use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;class PostSearch extends Post{
public function rules(){// rules() にあるフィールドだけが検索可能
return [[['id'], 'integer'],[['title', 'creation_date'], 'safe'],];}public function scenarios(){// 親クラスの scenarios() の実装をバイパスする
return Model::scenarios();}
public function search($params){$query = Post::find();$dataProvider = new ActiveDataProvider(['query' => $query,]);// 検索フォームのデータをロードして検証する
if (!($this->load($params) && $this->validate())) {return $dataProvider;}// フィルタを追加してクエリを修正する$query->andFilterWhere(['id' => $this->id]);$query->andFilterWhere(['like', 'title', $this->title])->andFilterWhere(['like', 'creation_date',$this->creation_date]);}}return $dataProvider;

ヒント〺 フィルタのクエリを構築する方法を学ぶためには、クエリ・ビルダ、 中でも特に フィルタ条件 を参照してください。
この search() メソッドをコントローラで使用して、ぇひどつざどづぷ のための〴〳〸

ぃえぁぐごぅげ 〸〮 データの表示

データ・プロバイダを取得することが出来ます。
$searchModel = new PostSearch();$dataProvider = $searchModel->search(Yii::$app->request->get());
return $this->render('myview', ['dataProvider' => $dataProvider,'searchModel' => $searchModel,]);

そしてビューでは、$dataProvider と $searchModel を ぇひどつざどづぷ に与えます。
echo GridView::widget(['dataProvider' => $dataProvider,'filterModel' => $searchModel,'columns' => [// ...
],]);

独立したフィルタ・フォーム
たいていの場合はグリッド・ビューのヘッダのフィルタで十分でしょう。しかし、独立したフィルタのフォームが必要な場合でも、 簡単に追加することができます。まず、以下の内容を持つパーシャル・ビュー_search.php を作成します。
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;/* @var $this yii\web\View *//* @var $model app\models\PostSearch *//* @var $form yii\widgets\ActiveForm */?><div class="post-search"><?php $form = ActiveForm::begin(['action' => ['index'],'method' => 'get',]); ?><? = $form->field($model, 'title') ?><? = $form->field($model, 'creation_date') ?><div class="form-group"><? = Html::submitButton('Search', ['class' => 'btn btn-primary']) ?><? = Html::submitButton('Reset', ['class' => 'btn btn-default']) ?></div>

〸〮〵〮 データ・ウィジェット

〴〳〹<?php ActiveForm::end(); ?></div>

そして、これを以下のように index.php ビューにインクルードします。
<?= $this->render('_search', ['model' => $searchModel]) ?>補足〺 ぇどど を使って ぃげさい コードを生成する場合、デフォルト
で、独立したフィルタ・フォーム 〨_search.php〩 が生成されます。 ただし、index.php ビューの中ではコメント・アウトされています。コメントを外せば、すぐに使うことが出来ます。
独立したフ ィルタ・フ ォームは、 グリッド・ ビューに表示されな いフィールドによってフィルタをかけたり、 または日付の範囲のような特殊なフィルタ条件を使う必要があったりする場合に便利です。 日付の範囲によってフィルタする場合は、いあ には存在しない createdFrom とcreatedTo という属性を検索用のモデルに追加すると良いでしょう。
class PostSearch extends Post{/**
* @var string*/
public $createdFrom;}/*** @var string*/
public $createdTo;

そして、search() メソッドでクエリの条件を次のように拡張します。
$query->andFilterWhere(['>=', 'creation_date', $this->createdFrom])->andFilterWhere(['<=', 'creation_date', $this->createdTo]);

そして、フィルタ・フォームに、日付の範囲を示すフィールドを追加します。
<?= $form->field($model, 'creationFrom') ?><? = $form->field($model, 'creationTo') ?>モデルのリレーションを扱う
ぇひどつざどづぷ でアクティブ・レコードを表示するときに、例えば、単に投稿者の id ではなく、 投稿者の名前のような関連するカラムの値を表示するという場合に遭遇するかも知れません。 Post モデルが author という名前〴〴〰

ぃえぁぐごぅげ 〸〮 データの表示のリレーションを持っていて、その投稿者のモデルが name という属性を持っているなら、 べどどぜでひどつぜぇひどつざどづぷ〺〺〤っはぬふねのび の属性名を author.nameと定義します。 そうすれば、ぇひどつざどづぷ が投稿者の名前を表示するようになります。ただし、並べ替えとフィルタリングは、デフォルトでは有効になりません。 これらの機能を追加するためには、前の項で導入した
PostSearch モデルを修正しなければなりません。
リレーションのカラムによる並べ替えを有効にするためには、リレー
ションのテーブルを結合し、 データ・プロバイダの こはひぴ コンポーネントに並べ替えの規則を追加します。
$query = Post::find();$dataProvider = new ActiveDataProvider(['query' => $query,]);// リレーション `author` を結合します。これはテーブル `users` に対するリレー
ションであり、// テーブル・エイリアスを `author` とします。
$query->joinWith(['author' => function($query) { $query->from(['author' =>'users']); }]);// バージョン 2.0.7 以降では、上の行は $query->joinWith('author AS author');として単純化することが出来ます。
// リレーションのカラムによる並べ替えを有効にします。
$dataProvider->sort->attributes['author.name'] = ['asc' => ['author.name' => SORT_ASC],'desc' => ['author.name' => SORT_DESC],];// ...

フィルタリングも上記と同じ なはどのしどぴと の呼び出しを必要とします。また、次のように、attributes と rules の中で、検索可能なカラムを追加で定義する必要があります。
public function attributes(){// 検索可能な属性にリレーションのフィールドを追加する
return array_merge(parent::attributes(), ['author.name']);}public function rules(){return [[['id'], 'integer'],[['title', 'creation_date', 'author.name'], 'safe'],];}search() メソッドでは、次のように、もう一つのフィルタ条件を追加するだけです。

〸〮〵〮 データ・ウィジェット

〴〴〱$query->andFilterWhere(['LIKE', 'author.name',$this->getAttribute('author.name')]);

情報〺 上の例では、リレーション名とテーブル・エイリアスに同じ文字列を使用しています。 しかし、エイリアスとリレーション名が異なる場合は、どこでエイリアスを使い、どこでリレーション名を使うかに注意を払わなければなりま
せん。 これに関する簡単な規則は、データベース・クエリを構築するために使われる全ての場所でエイリアスを使い、
attributes() や rules() など、その他の全ての定義においてリ
レーション名を使う、というものです。
例えば、投稿者のリレーションテーブルに au というエイリア
スを使う場合は、なはどのしどぴと の文は以下のようになります。
$query->joinWith(['author au']);リレーションの定義においてエイリアスが定義されている場
合は、単に $query->joinWith(['author']); として呼び出すことも可能です。
フィルタ条件においてはエイリアスが使われなければなりま
せんが、属性の名前はリレーション名のままで変りません。
$query->andFilterWhere(['LIKE', 'au.name',$this->getAttribute('author.name')]);

並べ替えの定義についても同じことです。
$dataProvider->sort->attributes['author.name'] = ['asc' => ['au.name' => SORT_ASC],'desc' => ['au.name' => SORT_DESC],];

さらに、並べ替えの つづてちふぬぴくひつづひ を指定するときも、 エイ
リアスではなくリレーション名を使う必要があります。
$dataProvider->sort->defaultOrder = ['author.name' => SORT_ASC];情報〺 joinWith およびバックグラウンドで実行されるクエリの詳細については、 アクティブ・レコード 〭 リレーションを使ってテーブルを結合する を参照してください。
こけが ビューを使って、データのフィルタリング・並べ替え・表示をする
もう一つ別に、もっと高速で便利な手法があります。こけが ビューです。
例えば、ユーザとユーザのプロファイルを一緒にグリッド・ビューに表示する必要がある場合、次のような こけが ビューを作成することが出来ま
す。

〴〴〲

ぃえぁぐごぅげ 〸〮 データの表示

CREATE OR REPLACE VIEW vw_user_info AS
SELECT user.*, user_profile.lastname, user_profile.firstname
FROM user, user_profile
WHERE user.id = user_profile.user_id

そして、このビューを表す ぁっぴどぶづげづっはひつ を作成します。
namespace app\models\views\grid;use yii\db\ActiveRecord;class UserView extends ActiveRecord{/*** {@inheritdoc}*/
public static function tableName(){
return 'vw_user_info';}
public static function primaryKey(){
return ['id'];}/*** {@inheritdoc}*/
public function rules(){return [// ここで規則を定義];}/*** {@inheritdoc}*/
public function attributeLabels(){
return [// ここで属性のラベルを定義];}}

このようにした後は、この さびづひざどづぷ アクティブ・レコードを検索用のモデルとともに使うことが出来ます。並べ替えやフィルタリングの属性を追加で定義する必要はありません。 全ての属性がそのままで動作し

〸〮〵〮 データ・ウィジェット

〴〴〳ます。この手法にはいくつかの長所と短所があることに注意してください。
• 並べ替えとフィルタリングの条件をいろいろと定義する必要はありません。全てそのままで動きます。
• データサイズが小さく、実行される こけが クエリの数が少ない 〨通常なら全てのリレーションについて一つずつ必要になる追加のクエリが要らない〩 ため、非常に高速になり得ます。
• これは こけが ビューにかぶせた単純な さぉ に過ぎないもので、エンティティに含まれるドメイン・ロジックを欠いています。 従って、isActive や isDeleted などのような さぉ に影響するメソッドがある場合は、それらをこのクラスの中に複製する必要があります。
一つのページに複数のグリッド・ビュー
一つのページで二つ以上のグリッド・ビューを使うことが出来ますが、お互いが干渉しないように、追加の構成がいくつか必要になります。 グ
リッド・ビューの複数のインスタンスを使う場合は、並べ替えとページネーションのリンクが違うパラメータ名を持って生成されるように構成して、 それぞれのグリッド・ビューが独立した並べ替えとページ
ネーションを持つことが出来るようにしなければなりません。 そのためには、データ・プロバイダの びはひぴ と ばちでどのちぴどはの インスタンスのびはひぴぐちひちね と ばちでづぐちひちね を設定します。
Post と User のリストを表示するために、二つのプロバイダ、$userProviderと $postProvider を準備済みであると仮定します。
use yii\grid\GridView;$userProvider->pagination->pageParam = 'user-page';$userProvider->sort->sortParam = 'user-sort';$postProvider->pagination->pageParam = 'post-page';$postProvider->sort->sortParam = 'post-sort';echo '<h1>ユーザ</h1>';echo GridView::widget(['dataProvider' => $userProvider,]);echo '<h1>投稿</h1>';echo GridView::widget(['dataProvider' => $postProvider,]);ぇひどつざどづぷ を ぐなちへ とともに使う
ぐなちへ ウィジェットを使うと、ページ全体をリロードせずに、 ページの一部分だけを更新することが出来ます。 これを使うと、フィルタを使うときに、ぇひどつざどづぷ の中身だけを更新することが出来ます。

〴〴〴

ぃえぁぐごぅげ 〸〮 データの表示

use yii\widgets\Pjax;
use yii\grid\GridView;
Pjax::begin([// PJax のオプション]);
Gridview::widget([// GridView のオプション]);
Pjax::end();

ぐなちへ は、ぐなちへ ウィジェットの内側にあるリンク、および、ぐなちへ〺〺〤ぬどのにこづぬづっぴはひで指定されているリンクに対しても動作します。 しかし、これはぁっぴどはのぃはぬふねの の リ ン ク に 対 し て は 問 題 と な り 得 ま す 。 こ の 問 題 を
防 止 す る た め に は 、ぁっぴどはのぃはぬふねの〺〺〤ぢふぴぴはのび プ ロ パ テ ィ を 編 集 し て
data-pjax="0" という えごきが 属性を追加します。
ぇどど における ぐなちへ を伴う ぇひどつざどづぷ〯がどびぴざどづぷ バージョン 〲〮〰〮〵 以
降、ぇどど の ぃげさい ジェネレータでは $enablePjax というオプションがウェ
ブ・インタフェイスまたはコマンドラインで使用可能になっています。
yii gii/crud --controllerClass="backend\\controllers\PostController" \--modelClass="common\\models\\Post" \--enablePjax=1

これによって、ぇひどつざどづぷ または がどびぴざどづぷ を囲む ぐなちへ ウィジェットが生成されます。

8.5.4

さらに読むべき文書• ぁひのは こぬちぴどふび に よ る げづのつづひどので いちぴち どの すどど 〲 ぷどぴと ぇひどつざどづぷ ちのつがどびぴざどづぷ8 。

8.6

クライアント・スクリプトを扱う

今日のウェブ・アプリケーションでは、静的な えごきが ページがレンダリングされてブラウザに送信されるだけでなく、 おちぶちこっひどばぴ によって、既存の要素を操作したり、新しいコンテントを ぁおぁじ でロードしたりして、 ブラウザに表示されるページを修正します。 このセクションでは、おちぶちこっひどばぴ と ぃここ をウェブ・サイトに追加したり、 それらを動的に調整するために すどど によって提供されているメソッドを説明します。
8https://www.sitepoint.com/rendering-data-in-yii-2-with-gridview-and-listview/

〸〮〶〮 クライアント・スクリプトを扱う

8.6.1

〴〴〵

スクリプトを登録する

べどどぜぷづぢぜざどづぷ オブジェクトを扱う際には、フロントエンド・スクリプトを動的に登録することが出来ます。 このための専用のメソッドが二つあります。
• インライン・スクリプトのための ひづでどびぴづひおび〨〩• 外部スクリプトのための ひづでどびぴづひおびうどぬづ〨〩
インライン・スクリプトを登録する
インライン・スクリプトは、設定のためのコード、動的に生成される
コード、および、ウィジェット に含まれる再利用可能なフロントエン
ド・コードが生成する コード断片などです。インライン・スクリプトを追加するためのメソッド ひづでどびぴづひおび〨〩 は、次のようにして使うことが出来ます。
$this->registerJs("$('#myButton').on('click', function() { alert('ボタンがクリックされました'); });",
View::POS_READY,'my-button-handler');

最 初 の 引 数 は 、 ペ ー ジ に 挿 入 し た い 実 際 の おこ コ ー ド で す 。 こ れ が<script> タグに包まれて挿入されます。 二番目の引数は、スクリプト
がページのどの位置に挿入されるべきかを決定します。 取りうる値は以下のとおりです。
• ざどづぷ〺〺ぐくこたえぅぁい 〭 とづちつ セクション。
• ざどづぷ〺〺ぐくこたあぅぇぉぎ 〭 開始の <body> の直後。
• ざどづぷ〺〺ぐくこたぅぎい 〭 終了の </body> の直前。
• ざどづぷ〺〺ぐくこたげぅぁいす 〭 ドキュメントの ready イベント9 でコードを実行するための指定。 これを指定すると、なけふづひべ が自動的に登録
され、コードは適切な なけふづひべ コードの中に包まれます。これがデフォルトの位置指定です。
• ざどづぷ〺〺ぐくこたがくぁい 〭 ドキュメントの load イベント10 でコードを実行するための指定。 上記と同じく、これを指定すると、なけふづひべ が自動的に登録されます。
最後の引数は、スクリプトのコード・ブロックを一意に特定するために使われるスクリプトのユニークな ぉい です。同じ ぉい のスクリプトが既にある場合は、新しいものを追加するのでなく、 それを置き換えます。ぉい
を指定しない場合は、おこ コードそれ自身が ぉい として扱われます。このぉい によって、同じコードが複数回登録されるのを防止します。
910

https://learn.jquery.com/using-jquery-core/document-ready/https://learn.jquery.com/using-jquery-core/document-ready/〴〴〶

ぃえぁぐごぅげ 〸〮 データの表示

スクリプト・ファイルを登録する
ひづでどびぴづひおびうどぬづ〨〩 の引数は、 ひづでどびぴづひぃびびうどぬづ〨〩 の引数と同様なものです。 以下に示す例では、main.js ファイルを、べどどぜぷづぢぜおぱふづひべぁびびづぴ への依存関係とともに、登録します。 これは、main.js ファイルは jquery.jsの後に追加される、ということを意味します。 このような依存関係の仕様が無ければ、main.js と jquery.js の間の相対的な順序は未定義となり、コードは動作しなくなるでしょう。
外部スクリプトは次のようにして追加することが出来ます。
$this->registerJsFile('@web/js/main.js',['depends' => [\yii\web\JqueryAsset::class]]);

これによって、アプリケーションの ぢちびづ さげが の下に配置されている/js/main.js スクリプトを読み込むタグが追加されます。
ただし、外部 おこ ファイルを登録するのには、 ひづでどびぴづひおびうどぬづ〨〩 を使わずに、アセット・バンドル を使うことが強く推奨されます。 なぜなら、そうする方が、柔軟性も高く、依存関係の構成も粒度を細かく出来るからです。また、アセット・バンドルを使えば、複数の おこ ファイルを結合して圧縮すること 〨アクセスの多いウェブ・サイトではそうすることが望まれます〩 が可能になります。

8.6.2

CSS を登録する

おちぶちびっひどばぴ と同様に、ひづでどびぴづひぃびび〨〩 または ひづでどびぴづひぃびびうどぬづ〨〩 を使って ぃここ を登録することが出来ます。 前者は ぃここ のコードブロックを登録し、後者は外部 ぃここ ファイルを登録するものです。
インライン ぃここ を登録する$this->registerCss("body { background: #f00; }");

上記のコードによって、結果として、下記の出力がページの <head> セクションに追加されます。
<style>body { background: #f00; }</style>style タグに追加の属性を指定したい場合は、名前〭値 の配列を二番目の引数として渡します。最後の引数は、スタイルのブロックを一意に特定するために使われるユニークな ぉい です。 同じスタイルがコードの別の箇所で重複して登録されたとしても、このスタイルのブロックが一度だ
け追加されることを保証するものです。

〸〮〶〮 クライアント・スクリプトを扱う〴〴〷

ぃここ ファイルを登録する
ぃここ ファイルは次のようにして登録することが出来ます。
$this->registerCssFile("@web/css/themes/black-and-white.css", ['depends' => [\yii\bootstrap\BootstrapAsset::class],'media' => 'print',], 'css-print-theme');

上記のコードは /css/themes/black-and-white.css という ぃここ ファイルに対するリンクをページの <head> セクションに追加します。
• 最初の引数が、登録される ぃここ ファイルを指定します。 この例における @web どの ぴとどび づへちねばぬづ どび ちの アプリケーションのベース さげが に対するエイリアス です。
• 二番目の引数は、結果として出力される <link> タグの えごきが 属性を指定するものです。 ただし、depends というオプションは特別な処理を受けます。これは、この ぃここ ファイルが依存するアセット・
バンドルを指定するものです。 この例の場合は、べどどぜぢははぴびぴひちば
ぜあははぴびぴひちばぁびびづぴ が依存するアセット・バンドルです。 これは、この ぃここ ファイルが べどどぜぢははぴびぴひちばぜあははぴびぴひちばぁびびづぴ に属する ぃここ
ファイルの後に追加されることを意味します。
• 最後の引数はこの ぃここ ファイルを特定する ぉい を指定するものです。 省略された場合は、ぃここ ファイルの さげが が代りに ぉい として使用されます。
外部 ぃここ ファイルを登録するのには、 ひづでどびぴづひぃびびうどぬづ〨〩 を使わずに、
アセット・バンドル を使うことが強く推奨されます。アセット・バンド
ルを使えば、複数の ぃここ ファイルを結合して圧縮すること 〨アクセスの多いウェブ・サイトではそうすることが望まれます〩 が可能になります。
また、アプリケーションの全てのアセットの依存関係を一ヶ所で構成することが出来るため、より大きな柔軟性を得ることが出来ます。

8.6.3

アセット・バンドルを登録する

既に述べたように、ぃここ ファイルと おちぶちこっひどばぴ ファイルを直接に登録す
る代りにアセット・バンドルを使うことが推奨されます。 アセット・バ
ンドルを定義する方法の詳細は、ガイドの アセット のセクションで知ることが出来ます。 既に定義されているアセット・バンドルの使い方は、次のように非常に単純明快です。
\frontend\assets\AppAsset::register($this);

上記のコードでは、ビュー・ファイルのコンテキストにおいて、AppAsset
バンドルが 〨$this で表される〩 現在のビューに対して登録されています。 ウィジェットの中からアセット・バンドルを登録するときは、ウィジェットの 〤ぶどづぷ を代りに渡します 〨$this->view〩。

〴〴〸

8.6.4

ぃえぁぐごぅげ 〸〮 データの表示

動的な Javascript を生成する

ビュー・ファイルでは、えごきが コードが直接に書き出されのではなく、ビューの変数に依存して、ぐえぐ のコードによって生成されることがよくあります。 生成された えごきが を おちぶちびっひどばぴ によって操作するためには、おこ コードも同様に動的な部分を含まなければなりません。 例え
ば、なけふづひべ セレクタの ぉい などがそうです。
ぐえぐ の変数を おこ コードに挿入するためには、変数の値を適切にエスケープする必要があります。 おこ コードを専用の おこ ファイルの中に置くのではなく、えごきが に挿入する場合は特にそうです。 すどど は、この目的のために、おびはの ヘルパの とぴねぬぅのっはつづ〨〩 メソッドを提供しています。 その使用方法は、以下の例の中で示されています。
グローバルな おちぶちこっひどばぴ の構成情報を登録する
この例では、配列を使って、グローバルな構成情報のパラメータをアプ
リケーションの ぐえぐ のパートから おこ のフロントエンド・コードに渡します。
$options = ['appName' => Yii::$app->name,'baseUrl' => Yii::$app->request->baseUrl,'language' => Yii::$app->language,// ...
];$this->registerJs("var yiiOptions = ".\yii\helpers\Json::htmlEncode($options).";",
View::POS_HEAD,'yiiOptions');

上記のコードは、次のような おちぶちこっひどばぴ の変数定義を含む <script> タグ
を登録します。 例えば、
var yiiOptions = {"appName":"My Yii
Application","baseUrl":"/basic/web","language":"en"};

このようにすれば、あなたの おちぶちびっひどばぴ コードで、これらの構成情報に
yiiOptions.baseUrl や yiiOptions.language のようにしてアクセスすることが出来るようになります。〮
翻訳されたメッセージを渡す
あなたの おちぶちこっひどばぴ が何らかのイベントに反応してメッセージを表示する必要がある、という状況に遭遇するかも知れません。 複数の言語で動作するアプリケーションでは、この文字列は、現在のアプリケーシの言語に翻訳されなければなりません。 これを達成する一つの方法は、すどど によって提供されている せメッセージ翻訳機能そ 〨ぴふぴはひどちぬ〭ど〱〸の〮ねつ〣ねづびびちでづ〭
ぴひちのびぬちぴどはの〩 を使って、その結果を おちぶちこっひどばぴ コードに渡すことです。

〸〮〷〮 テーマ〴〴〹

$message = \yii\helpers\Json::htmlEncode(\Yii::t('app', 'Button clicked!'));$this->registerJs(<<<JS$('#myButton').on('click', function() { alert( $message ); });JS);

上記のサンプル・コードは、可読性を高めるために、ぐえぐ の ヒアドキュ
メント構文11 を使っています。 また、ヒアドキュメントは、たいていの ぉいぅ で、より良い構文ハイライトが可能になるので、 インライン
おちぶちこっひどばぴ、特に一行に収まらないものを書くときに推奨される方法です。 変数 $message は ぐえぐ で生成され、おびはの〺〺とぴねぬぅのっはつづ のおかげで、
適切な おこ 構文の文字列を含むものになります。 それを おちぶちこっひどばぴ コードに挿入して、alert() の関数呼び出しに動的な文字列を渡すことが出来ます。
補足〺 ヒアドキュメントを使う場合は、おこ コード中の変数名に注意してください。 $ で始まる変数は、ぐえぐ の変数として解釈され、 その値によって置き換えられる可能性があります。 ただし、$( または $. という形式の なけふづひべ 関数は ぐえぐ
変数として解釈される心配は無く、安全に使うことが出来ま
す。

8.6.5

スクリプト

補足〺 このセクションはまだ書かれていません。このセクショ
ンは、yii.js によって提供される以下の機能についての説明を含むはずのものです。
• すどど おちぶちこっひどばぴ モジュール• ぃこげう パラメータの処理• data-confirm ハンドラ
• data-method ハンドラ
• スクリプトのフィルタリング• リダイレクトの処理

8.7

テーマ

テーマは、元のビュー・レンダリングのコードに触れる必要なしに、ビューのセットを別のセットに置き換えるための方法です。 テーマを使うとアプリケーションのルック・アンド・フィールを体系的に変更することが出来ます。
11
https://www.php.net/manual/ja/language.types.string.php#language.types.
string.syntax.heredoc〴〵〰

ぃえぁぐごぅげ 〸〮 データの表示

テーマを使うためには、view アプリケーション・コンポーネントのぴとづねづ プロパティを構成しなければなりません。 このプロパティが、
ビュー・ファイルが置換される方法を管理する べどどぜぢちびづぜごとづねづ オブジェ
クトを構成します。 指定しなければならない べどどぜぢちびづぜごとづねづ のプロパ
ティは主として以下のものです。
• べどどぜぢちびづぜごとづねづ〺〺〤ぢちびづぐちぴと〺 テーマのリソース 〨ぃここ、おこ、画像など〩 を含むベース・ディレクトリを指定します。
• べどどぜぢちびづぜごとづねづ〺〺〤ぢちびづさひぬ〺 テーマのリソースのベース さげが を指定します。
• べどどぜぢちびづぜごとづねづ〺〺〤ばちぴときちば〺 ビュー・ファイルの置換の規則を指定します。 詳細は後述する項で説明します。
例えば、SiteController で $this->render('about') を呼び出すと、ビュー・
ファイル @app/views/site/about.php をレンダリングすることになります。
しかし、下記のようにアプリケーション構成情報でテーマを有効にすると、 代りに、ビュー・ファイル @app/themes/basic/site/about.php がレンダリングされます。
return ['components' => ['view' => ['theme' => ['basePath' => '@app/themes/basic','baseUrl' => '@web/themes/basic','pathMap' => ['@app/views' => '@app/themes/basic',
],
],
],
],
];

情報〺 テーマではパス・エイリアスがサポートされています。
ビューの置換を行う際に、パス・エイリアスは実際のファイ
ル・パスまたは さげが に変換されます。
べどどぜぢちびづぜざどづぷ〺〺〤ぴとづねづ プロパティを通じて べどどぜぢちびづぜごとづねづ オブジェ
クトにアクセスすることが出来ます。 例えば、ビュー・ファイルの中では $this がビュー・オブジェクトを指すので、次のようなコードを書くことが出来ます。
$theme = $this->theme;// $theme->baseUrl . '/img/logo.gif' を返す$url = $theme->getUrl('img/logo.gif');// $theme->basePath . '/img/logo.gif' を返す$file = $theme->getPath('img/logo.gif');〸〮〷〮 テーマ〴〵〱

べどどぜぢちびづぜごとづねづ〺〺〤ばちぴときちば プロパティが、ビュー・ファイルがどのように置換されるべきかを制御します。 このプロパティは「キー・値」ペアの配列を取ります。 キーは置き換えられる元のビューのパスであり、値は対応するテーマのビューのパスです。 置換は部分一致に基づいて行われます。 あるビューのパスが ばちぴときちば 配列のキーのどれかで始っていると、その一致している部分が対応する配列の値によって置き換えられます。 上記の構成例を使う場合、@app/views/site/about.php は @app/views というキーに部分一致するため、@app/themes/basic/site/about.php に置き換
えられることになります。
モジュールにテーマを適用するモジュールにテーマを適用するためには、べどどぜぢちびづぜごとづねづ〺〺〤ばちぴときちば を
次のように構成します。
'pathMap' => ['@app/views' => '@app/themes/basic','@app/modules' => '@app/themes/basic/modules', // <-- !!!
],これによって、@app/modules/blog/views/comment/index.php に @app/themes/basic/modules/blog/views/comment/iというテーマを適用することが出来ます。
ウィジェットにテーマを適用する
ウィジェットにテーマを適用するためには、べどどぜぢちびづぜごとづねづ〺〺〤ばちぴときちば
を次のように構成します。
'pathMap' => ['@app/views' => '@app/themes/basic','@app/widgets' => '@app/themes/basic/widgets', // <-- !!!
],これによって、@app/widgets/currency/views/index.php に @app/themes/basic/widgets/currency/views/index.phpというテーマを適用することが出来ます。

8.7.1

テーマの継承場合によっては、基本的なルック・アンド・フィールを含むアプリケー
ションの基本テーマを定義しておいて、 現在の祝日に基づいてルック・アンド・フィールを少し変更したい、ということがあるかもしれません。 テーマの継承を使ってこの目的を達することが出来ます。テーマの継承は、一つのビュー・パスを複数のターゲットに割り付けることによって設定することが出来ます。例えば、'pathMap' => ['@app/views' => ['@app/themes/christmas',

〴〵〲

]

ぃえぁぐごぅげ 〸〮 データの表示],'@app/themes/basic',

こ の 場 合 、 ビ ュ ー @app/views/site/index.php に は 、 ど ち ら の テ ー マ ・ファイルが存在するかに従って、 @app/themes/christmas/site/index.php か@app/themes/basic/site/index.php か、どちらかのテーマが適用されます。
テーマ ・ファイル が両方とも存在する場合は、最初のもの が優先されます。 実際の場面では、ほとんどのテーマ・ビュー・ファイルを@app/themes/basic に保管し、その中のいくつかを @app/themes/christmas でカスタマイズすることになるでしょう。

Chapter 9

セキュリティ
9.1

セキュリティ

十分なセキュリティは、すべてのアプリケーションの健全さと成功のために欠くことが出来ないものです。 不幸なことに、理解が不足している
ためか、実装の難易度が高すぎるためか、セキュリティのことになると手を抜く開発者がたくさんいます。 すどど によって駆動されるあなたのア
プリケーションを可能な限り安全にするために、すどど はいくつかの優秀な使いやすいセキュリティ機能を内蔵しています。
• 認証• 権限付与• パスワードを扱う• 暗号化• ビューのセキュリティ• 認証クライアント1• ベスト・プラクティス• 信頼できるプロキシとヘッダ

9.2

認証

認証は、ユーザが誰であるかを確認するプロセスです。 通常は、識別子〨ユーザ名やメール・アドレスなど〩 と秘密のトークン 〨パスワードやア
クセス・トークンなど〩 を使って、ユーザがそうであると主張する通りのユーザであるか否かを判断します。 認証がログイン機能の基礎となります。
すどど はさまざまなコンポーネントを結び付けてログインをサポートする認証フレームワークを提供しています。 このフレームワークを使用するために、あなたは主として次の仕事をする必要があります。
• ふびづひ アプリケーション・コンポーネントを構成する。
1
https://github.com/yiisoft/yii2-authclient/blob/master/docs/guide-ja/
README.md

〴〵〳

〴〵〴

ぃえぁぐごぅげ 〹〮 セキュリティ• べどどぜぷづぢぜぉつづのぴどぴべぉのぴづひてちっづ インタフェイスを実装するクラスを作
成する。

9.2.1

yii\web\User を構成する

ふびづひ アプリケーション・コンポーネントがユーザの認証状態を管理します。 実際の認証ロジックを含む ユーザ識別情報クラス は、あなたが指定しなければなりません。 下記のアプリケーション構成情報においては、ふびづひ の ユーザ識別情報クラス は app\models\User であると構成されています。 app\models\User の実装については、次の項で説明します。
return ['components' => ['user' => ['identityClass' => 'app\models\User',
],
],
];

9.2.2

yii\web\IdentityInterface を実装する

ユーザ識別情報クラス が実装しなければならない べどどぜぷづぢぜぉつづのぴどぴべぉのぴづひてちっづ
は次のメソッドを含んでいます。
• てどのつぉつづのぴどぴべ〨〩〺 指定されたユーザ ぉい を使ってユーザ識別情報クラスのインスタンスを探します。 セッションを通じてログイン状態を保持する必要がある場合に、このメソッドが使用されます。
• てどのつぉつづのぴどぴべあべぁっっづびびごはにづの〨〩〺 指定されたアクセス・トークンを使ってユーザ識別情報クラスのインスタンスを探します。 単一の秘密のトークンでユーザを認証する必要がある場合 〨ステートレスなげぅこごてふぬ アプリケーションなどの場合〩 に、このメソッドが使用されます。
• でづぴぉつ〨〩〺 ユーザ識別情報クラスのインスタンスによって表されるユーザの ぉい を返します。
• でづぴぁふぴとかづべ〨〩〺 自動ログインが有効にされている場合に、 セッショ
ンと自動ログインを検証するキーを返します。
• ぶちぬどつちぴづぁふぴとかづべ〨〩〺 クッキー・ベースのログイン・キーを検証するロジックを実装します。
特定のメソッドが必要でない場合は、中身を空にして実装しても構いません 。例えば、 あなたのア プリケーシ ョンが純粋なステ ート・レ
ス げぅこごてふぬ アプリケーションであるなら、 実装する必要があるのはてどのつぉつづのぴどぴべあべぁっっづびびごはにづの〨〩 と でづぴぉつ〨〩 だけであり、他のメソッドは全て中身を空にしておくことが出来ます。 逆にあなたのアプリケーショ
ンがセッションのみの認証を使用する場合は、 てどのつぉつづのぴどぴべあべぁっっづびびごはにづの〨〩以外の全てのメソッドを実装する必要があります。
次の例では、ユーザ識別情報クラス は、user データベース・テーブ
ルと関連付けられた アクティブ・レコード クラスとして実装されていま〹〮〲〮 認証

〴〵〵

す。
<?php
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;class User extends ActiveRecord implements IdentityInterface{
public static function tableName(){
return 'user';}/*** 与えられた ID によってユーザ識別情報を探す** @param string|int $id 探すための ID* @return IdentityInterface|null 与えられた ID に合致する Identity オブ
ジェクト*/
public static function findIdentity($id){
return static::findOne($id);}/*** 与えられたトークンによってユーザ識別情報を探す** @param string $token 探すためのトークン* @return IdentityInterface|null 与えられたトークンに合致する Identity
オブジェクト*/public static function findIdentityByAccessToken($token, $type = null){
return static::findOne(['access_token' => $token]);}/*** @return int|string 現在のユーザの ID*/
public function getId(){
return $this->id;}/*** @return string|null 現在のユーザの認証キー*/
public function getAuthKey(){
return $this->auth_key;
}

〴〵〶

}

ぃえぁぐごぅげ 〹〮 セキュリティ/*** @param string $authKey* @return bool|null 認証キーが現在のユーザに対して有効か否か*/
public function validateAuthKey($authKey){
return $this->getAuthKey() === $authKey;}

次のコードを使って、各ユーザに対して認証キーを生成して、 user テー
ブルに保存しておくことが出来ます。
class User extends ActiveRecord implements IdentityInterface{......

}

public function beforeSave($insert){
if (parent::beforeSave($insert)) {if ($this->isNewRecord) {$this->auth_key =\Yii::$app->security->generateRandomString();}
return true;}
return false;}補足〺 ユーザ識別情報クラスである User と べどどぜぷづぢぜさびづひ を混同してはいけません。 前者は認証のロジックを実装するクラスであり、普通は、ユーザの認証情報を保存する何らかの
持続的ストレージと関連付けられた アクティブ・レコード ク
ラスとして実装されます。 後者はユーザの認証状態の管理に責任を持つアプリケーション・コンポーネントです。

9.2.3

yii\web\User を使う

べどどぜぷづぢぜさびづひ は、主として、user アプリケーション・コンポーネントの形で使います。
現在のユーザの識別情報は、Yii::$app->user->identity という式を使って取得することが出来ます。 これは、現在ログインしているユーザのユーザ識別情報クラス のインスタンスを返すか、現在のユーザが認証されていない 〨つまりゲストである〩 場合は のふぬぬ を返します。 次のコード
は、べどどぜぷづぢぜさびづひ からその他の認証関連の情報を取得する方法を示すものです。
// 現在のユーザの識別情報。ユーザが認証されていない場合は null
$identity = Yii::$app->user->identity;〹〮〲〮 認証〴〵〷// 現在のユーザの ID。ユーザが認証されていない場合は null
$id = Yii::$app->user->id;// 現在のユーザがゲストである (認証されていない) かどうか
$isGuest = Yii::$app->user->isGuest;

ユーザをログインさせるためには、次のコードを使うことが出来ます。
// 指定された username を持つユーザ識別情報を探す// 必要ならパスワードをチェックしてもよいことに注意$identity = User::findOne(['username' => $username]);// ユーザをログインさせる
Yii::$app->user->login($identity);

べどどぜぷづぢぜさびづひ〺〺ぬはでどの〨〩 メソッドは現在のユーザの識別情報を べどどぜぷづぢ
ぜさびづひ にセットします。 セッションが 有効 にされている場合は、 ユー
ザの認証状態がセッション全体を通じて保持されるように、ユーザ識別
情報がセッションに保管されます。 クッキー・ベースのログイン 〨つまり 【ひづねづねぢづひ ねづ】、「次回は自動ログイン」〩 が 有効 にされている場合
は、 ユーザ識別情報をクッキーにも保存して、クッキーが有効である
限りは、ユーザの認証状態をクッキーから復元することが可能になります。
クッキー・ベースのログインを有効にするためには、アプリケーショ
ンの構成情報で べどどぜぷづぢぜさびづひ〺〺〤づのちぢぬづぁふぴはがはでどの を true に構成する必要があります。 また、べどどぜぷづぢぜさびづひ〺〺ぬはでどの〨〩 メソッドを呼ぶときには、有効期間のパラメータを与える必要があります。
ユーザをログアウトさせるためには、単に次のように logout() を呼びます。
Yii::$app->user->logout();

ユーザのログアウトはセッションが有効にされている場合にだけ意味があることに注意してください。 logout() メソッドは、ユーザ認証状態をメモリとセッションの両方から消去します。そして、デフォルトでは、ユーザのセッションデータの 全て を破壊します。 セッション・データを保持したい場合は、代りに、Yii::$app->user->logout(false) を呼ばなけ
ればなりません。

9.2.4

認証のイベント

べどどぜぷづぢぜさびづひ クラスは、ログインとログアウトのプロセスで、いくつかのイベントを発生させます。
• ぅざぅぎごたあぅうくげぅたがくぇぉぎ〺 べどどぜぷづぢぜさびづひ〺〺ぬはでどの〨〩 の開始時に発生します。 イベント・ハンドラがイベントの どびざちぬどつ プロパティを falseにセットした場合は、 ログインのプロセスがキャンセルされます。

〴〵〸

ぃえぁぐごぅげ 〹〮 セキュリティ• ぅざぅぎごたぁうごぅげたがくぇぉぎ〺 ログインが成功した時に発生します。
• ぅざぅぎごたあぅうくげぅたがくぇくさご〺 べどどぜぷづぢぜさびづひ〺〺ぬはではふぴ〨〩 の開始時に発生します。 イベント・ハンドラがイベントの どびざちぬどつ プロパティを
false にセットした場合は、 ログアウトのプロセスがキャンセルされます。
• ぅざぅぎごたぁうごぅげたがくぇくさご〺 ログアウトが成功した時に発生します。
これらのイベントに反応して、ログイン監査、オンライン・ユーザ統計などの機能を実装することが出来ます。 例えば、ぅざぅぎごたぁうごぅげたがくぇぉぎ の
ハンドラの中で、 user テーブルにログインの日時と ぉぐ アドレスを記録することが出来ます。

9.3

権限付与

権限付与は、ユーザが何かをするのに十分な許可を有しているか否かを確認するプロセスです。 すどど は二つの権限付与の方法を提供しています。
すなわち、アクセス制御フィルタ 〨ぁぃう〩 と、ロール・ベース・アクセス制御 〨げあぁぃ〩 です。

9.3.1

アクセス制御フィルタ (ACF)

アクセス制御フィルタ 〨ぁぃう〩 は、べどどぜてどぬぴづひびぜぁっっづびびぃはのぴひはぬ として実装される単純な権限付与の方法であり、 何らかの単純なアクセス制御だけを必要とするアプリケーションで使うのに最も適したものです。 その名前が示すように、ぁぃう は、コントローラまたはモジュールで使用することが出来るアクション フィルタ です。 ぁぃう は、ユーザがアクションの実行をリクエストしたときに、一連の アクセス規則 をチェックして、現在のユーザがそのアクションにアクセスする許可を持つかどうかを決定します。
下記のコードは、site コントローラで ぁぃう を使う方法を示すものです。
use yii\web\Controller;
use yii\filters\AccessControl;
class SiteController extends Controller{
public function behaviors(){
return ['access' => ['class' => AccessControl::class,'only' => ['login', 'logout', 'signup'],'rules' => [['allow' => true,'actions' => ['login', 'signup'],'roles' => ['?'],

〹〮〳〮 権限付与

〴〵〹
],
[

];

}

],

],

],

'allow' => true,'actions' => ['logout'],'roles' => ['@'],}// ...

上記のコードにおいて、ぁぃう は site コントローラにビヘイビアとしてアタッチされています。これがアクション・フィルタを使用する典型的な方法です。 only オプションは、ぁぃう が login、logout、signup のアクショ
ンにのみ適用されるべきであることを指定しています。 site コントロー
ラの他の全てのアクションには ぁぃう の影響は及びません。 rules オプ
ションは アクセス規則 を指定するものであり、以下のように読むことが出来ます。
• 全てのゲスト・ユーザ 〨まだ認証されていないユーザ〩 に、login とsingup のアクションにアクセスすることを許可します。 roles オプ
ションに疑問符 ? が含まれていますが、これは「ゲスト」を表す特
殊なトークンです。
• 認証されたユーザに、logout アクションにアクセスすることを許可します。 @ という文字はもう一つの特殊なトークンで、「認証されたユーザ」を表すものです。
ぁぃう による権限付与のプロセスにおいては、現在の実行コンテキストに合致する規則が見つかるまで、 アクセス規則が上から下へと一つずつ調べられます。 そして、合致したアクセス規則の allow の値が、ユーザが権限を有するか否かを決定するのに使われます。 合致する規則が一つもなかった場合は、ユーザが権限をもたないことを意味し、ぁぃう はアクションの継続を中止します。
ユーザが現在のアクションにアクセスする権限を持っていないと判定した場合は、デフォルトでは、ぁぃう は以下の手段を取ります。
• ユーザがゲストである場合は、べどどぜぷづぢぜさびづひ〺〺ぬはでどのげづぱふどひづつ〨〩 を呼び出して、ユーザのブラウザをログイン・ページにリダイレクトします。
• ユーザが既に認証されている場合は、べどどぜぷづぢぜうはひぢどつつづのえぴぴばぅへっづばぴどはのを投げます。
この動作は、次のように、べどどぜてどぬぴづひびぜぁっっづびびぃはのぴひはぬ〺〺〤つづのべぃちぬぬぢちっに
プロパティを構成することによって、カスタマイズすることが出来ます。
['class' => AccessControl::class,
...

〴〶〰

]

ぃえぁぐごぅげ 〹〮 セキュリティ'denyCallback' => function ($rule, $action) {throw new \Exception('このページにアクセスする権限がありません。');}

アクセス規則 は多くのオプションをサポートしています。以下はサポー
トされているオプションの要約です。 べどどぜてどぬぴづひびぜぁっっづびびげふぬづ を拡張して、あなた自身のカスタマイズしたアクセス規則のクラスを作ることも出来ます。
• ちぬぬはぷ〺 これが「許可」の規則であるか、「禁止」の規則であるかを指定します。
• ちっぴどはのび〺 どのアクションにこの規則が適用されるかを指定します。
これはアクション ぉい の配列でなければなりません。比較は大文字と小文字を区別します。 このオプションが空であるか指定されていない場合は、規則が全てのアクションに適用されることを意味します。
• っはのぴひはぬぬづひび〺 どのコントローラにこの規則が適用されるかを指定します。これはコントローラ ぉい の配列でなければなりません。 コントローラがモジュールに属する場合は、モジュール ぉい をコント
ローラ ぉい の前に付けます。比較は大文字と小文字を区別します。
このオプションが空であるか指定されていない場合は、規則が全てのコントローラに適用されることを意味します。
• ひはぬづび〺 どのユーザ・ロールにこの規則が適用されるかを指定します。 二つの特別なロールが認識されます。これらは、べどどぜぷづぢ
ぜさびづひ〺〺〤どびぇふづびぴ によって判断されます。
〕 ?〺 ゲスト・ユーザ 〨まだ認証されていないユーザ〩 を意味します。
〕 @〺 認証されたユーザを意味します。
その他のロール名を使うと、べどどぜぷづぢぜさびづひ〺〺っちの〨〩 の呼び出しが惹起されますが、そのためには、げあぁぃ 〨次のセクションで説明します〩 を有効にする必要があります。 このオプションが空であるか指定されていない場合は、規則が全てのロールに適用されることを意味します。
• ひはぬづぐちひちねび〺 べどどぜぷづぢぜさびづひ〺〺っちの〨〩 に渡されるパラメータを指定します。 パラメータがどのように使われるかは、げあぁぃ 規則を説明する後のセクションを参照して下さい。このオプションが空であるか設定されていない場合は、パラメータは渡されません。
• どばび〺 どの クライアントの ぉぐ アドレス にこの規則が適用されるかを指定します。 ぉぐ アドレスは、最後にワイルドカード * を含むことが出来て、同じプレフィクスを持つ ぉぐ アドレスに合致させることが出来ます。 例えば、〧〱〹〲〮〱〶〸〪〮だ は、〧〱〹〲〮〱〶〸〮〧 のセグメントに属する全ての ぉぐ アドレスに合致します。 このオプションが空であるか指定されていない場合は、規則が全ての ぉぐ アドレスに適用されることを意味します。
• ぶづひぢび〺 どのリクエスト・メソッド 〨えごごぐ 動詞、例えば GET や POST〩〹〮〳〮 権限付与〴〶〱にこの規則が適用されるかを指定します。 比較は大文字と小文字を区別しません。
• ねちぴっとぃちぬぬぢちっに〺 この規則が適用されるべきか否かを決定するために呼び出されるべき ぐえぐ コーラブルを指定します。
• つづのべぃちぬぬぢちっに〺 この規則がアクセスを禁止する場合に呼び出されるべき ぐえぐ コーラブルを指定します。
下記は、matchCallback オプションを利用する方法を示す例です。 このオ
プションによって、任意のアクセス制御ロジックを書くことが可能になります。
use yii\filters\AccessControl;
class SiteController extends Controller{
public function behaviors(){
return ['access' => ['class' => AccessControl::class,'only' => ['special-callback'],'rules' => [['actions' => ['special-callback'],'allow' => true,'matchCallback' => function ($rule, $action) {return date('d-m') === '31-10';
}
],
],
],
];
}

}

// matchCallback が呼ばれる。このページは毎年10月31日だけアクセス出来ます。
public function actionSpecialCallback(){
return $this->render('happy-halloween');
}

9.3.2

ロール・ベース・アクセス制御 (RBAC)

ロール・ベース・アクセス制御 〨げあぁぃ〩 は、単純でありながら強力な集中型のアクセス制御を提供します。 げあぁぃ と他のもっと伝統的なアクセ
ス制御スキーマとの比較に関する詳細については、 しどにど 記事2 を参照してください。
2
https://ja.wikipedia.org/wiki/%E3%83%AD%E3%83%BC%E3%83%AB%E3%83%99%E3%
83%BC%E3%82%B9%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E5%88%B6%E5%BE%A1

〴〶〲

ぃえぁぐごぅげ 〹〮 セキュリティ

すどど は、ぎぉこご げあぁぃ モデル3 に従って、一般的階層型 げあぁぃ を実装しています。 げあぁぃ の機能は、ちふぴときちのちでづひ アプリケーション・コン
ポーネント を通じて提供されます。
げあぁぃ を使用することには、二つの作業が含まれます。 最初の作業
は、げあぁぃ 権限付与データを作り上げることであり、第二の作業は、権限付与データを使って必要とされる場所でアクセス・チェックを実行することです。
説明を容易にするために、まず、いくつかの基本的な げあぁぃ の概念を導入します。
基本的な概念ロール 〨役割〩 は、許可 〨例えば、記事を作成する、記事を更新するなど〩のコレクションです。 一つのロールを一人または複数のユーザに割り当てることが出来ます。 ユーザが特定の許可を有しているか否かをチェックするためには、その許可を含むロールがユーザに割り当てられているか否かをチェックすればよいのです。
各ロールまたは許可に関連付けられた 規則 が存在し得ます。 規則とは、アクセス・チェックの際に、対応するロールや許可が現在のユーザに適用されるか否かを決定するために実行されるコード断片のことです。 例えば、「記事更新」の許可は、現在のユーザが記事の作成者であるかどうかをチェックする規則を持つことが出来ます。 そして、アクセ
ス・チェックのときに、ユーザが記事の作成者でない場合は、彼〯彼女は「記事更新」の許可を持っていないと見なすことが出来ます。
ロールおよび許可は、ともに、階層的に構成することが出来ます。具
体的に言えば、一つのロールは他のロールと許可を含むことが出来、 許可は他の許可を含むことが出来ます。すどど は、一般的な 半順序 階層を実装していますが、これはその特殊形として 木 階層を含むものです。 ロールは許可を含むことが出来ますが、許可はロールを含むことが出来ません。
げあぁぃ を構成する
権限付与データを定義してアクセス・チェックを実行する前に、 ちふぴときちのちでづひ
アプリケーション・コンポーネントを構成する必要があります。 すどど は二種類の権限付与マネージャを提供しています。すなわち、べどどぜひぢちっ
ぜぐとばきちのちでづひ と べどどぜひぢちっぜいぢきちのちでづひ です。 前者は権限付与データを保存するのに ぐえぐ スクリプト・ファイルを使いますが、後者は権限付与
データをデータベースに保存します。 あなたのアプリケーションが非常に動的なロールと許可の管理を必要とするのでなければ、前者を使うことを考慮するのが良いでしょう。
3https://csrc.nist.gov/CSRC/media/Publications/conference-paper/1992/10/
13/role-based-access-controls/documents/ferraiolo-kuhn-92.pdf

〹〮〳〮 権限付与〴〶〳を使用する 次のコードは、アプリケーションの構成情報で べどどぜひぢちっ
ぜぐとばきちのちでづひ クラスを使って authManager を構成する方法を示すものです。
return [// ...
'components' => ['authManager' => ['class' => 'yii\rbac\PhpManager',],// ...
],];

これで authManager は \Yii::$app->authManager によってアクセスすることが出来るようになります。
デフォルトでは、べどどぜひぢちっぜぐとばきちのちでづひ は げあぁぃ データを @app/rbac/
ディレクトリの下のファイルに保存します。 権限の階層をオンラインで変更する必要がある場合は、必ず、ウェブ・サーバのプロセスがこのディレクトリとその中の全てのファイルに対する書き込み権限を有するようにしてください。
を使用する 次のコードは、アプリケーションの構成情報で べどどぜひぢちっ
ぜいぢきちのちでづひ クラスを使って authManager を構成する方法を示すものです。
return [// ...
'components' => ['authManager' => ['class' => 'yii\rbac\DbManager',// RBAC アイテムの階層をキャッシュしたい場合はコメントを外す// 'cache' => 'cache',],// ...
],];

補足〺 べどど〲〭ぢちびどっ〭ちばば テンプレートを使おうとする場合は、config/web.phpに加えて、 config/console.php 構成ファイルにおいても authManagerを宣言する必要があります。 べどど〲〭ちつぶちのっづつ〭ちばば の場合は、authManager
は common/config/main.php で一度だけ宣言されなければなりま
せん。
DbManager は四つのデータベース・テーブルを使ってデータを保存します。
• どぴづねごちぢぬづ〺 権限アイテムを保存するためのテーブル。デフォルトは【ちふぴとたどぴづね】。
• どぴづねぃとどぬつごちぢぬづ〺 権限アイテムの階層を保存するためのテーブル。
デフォルトは 【ちふぴとたどぴづねたっとどぬつ】。

〴〶〴ぃえぁぐごぅげ 〹〮 セキュリティ• ちびびどでのねづのぴごちぢぬづ〺 権限アイテムの割り当てを保存するためのテーブル。デフォルトは 【ちふぴとたちびびどでのねづのぴ】。
• ひふぬづごちぢぬづ〺 規則を保存するためのテーブル。デフォルトは 【ちふぴとたひふぬづ】。

先に進む前にこれらのテーブルをデータベースに作成する必要があります。そのためには、@yii/rbac/migrations に保存されているマイグレー
ションを使うことが出来ます。
yii migrate --migrationPath=@yii/rbac/migrations

異なる名前空間のマイグレーションを扱う方法の詳細については 分離されたマイグレーション のセクションを参照して下さい。
これで authManager は \Yii::$app->authManager によってアクセスすることが出来るようになります。

権限付与データを構築する

権限付与データを構築する作業は、つまるところ、以下のタスクに他なりません。
• ロールと許可を定義する• ロールと許可の関係を定義する• 規則を定義する• 規則をロールと許可に結び付ける• ロールをユーザに割り当てる
権限付与に要求される柔軟性の程度によって、上記のタスクのやりかたも異なってきます。 許可の階層構造が開発者によってのみ変更されることを意図する場合は、 マイグレーションまたはコンソールコマンドを使うことが出来ます。 マイグレーションを使う場合の利点は、他のマイグ
レーションと一緒に実行できることです。 コンソール・コマンドを使う場合の利点は、階層構造の全体が、複数のマイグレーションに分散することなく、コード中に見やすい形で保たれることです。
どちらの方法でも、結局は次のような げあぁぃ 階層を得ることになります。

〹〮〳〮 権限付与〴〶〵

許可の階層構造が動的に形成される必要がある場合は、さぉ またはコンソール・コマンドが必要になります。 階層構造そのものを構築するた〴〶〶

ぃえぁぐごぅげ 〹〮 セキュリティ

めに使用される ぁぐぉ には違いはありません。
マイグレーションを使う マイグレーション を使って、 authManager が提供する ぁぐぉ によって階層を初期化したり変更したりすることが出来ます。
./yii migrate/create init_rbac を使って新しいマイグレーションを作成
し、階層の作成を実装します。
<?php
use yii\db\Migration;
class m170124_084304_init_rbac extends Migration{
public function up(){$auth = Yii::$app->authManager;// "createPost" という許可を追加する$createPost = $auth->createPermission('createPost');$createPost->description = '記事を投稿';$auth->add($createPost);// "updatePost" という許可を追加する$updatePost = $auth->createPermission('updatePost');$updatePost->description = '記事を更新';$auth->add($updatePost);// "author" ロールを追加し、このロールに "createPost" の許可を付与する$author = $auth->createRole('author');$auth->add($author);$auth->addChild($author, $createPost);// "admin" ロールを追加し、このロールに "updatePost" の許可を付与する// 同時に、"author" ロールが持つ許可も付与する$admin = $auth->createRole('admin');$auth->add($admin);$auth->addChild($admin, $updatePost);$auth->addChild($admin, $author);}// ロールをユーザに割り当てる。1 と 2 は IdentityInterface::getId()
によって返される ID// IdentityInterface::getId() は、通常は User モデルの中で実装される$auth->assign($author, 2);$auth->assign($admin, 1);

public function down(){$auth = Yii::$app->authManager;$auth->removeAll();〹〮〳〮 権限付与

}

〴〶〷

}

どのユーザにどのロールを割り当てるかをハードコードした
くない場合は、マイグレーションに ->assign() の呼び出しを書かないで下さい。 その代りに、ロールの割り当てを管理す
る さぉ またはコンソール・コマンドを作成して下さい。
マイグレーションは yii migrate を使って適用することが出来ます。
コンソール・コマンドを使う
許可の階層が全く変化せず、決った数のユーザしか存在しない場合は、
authManager が提供する ぁぐぉ によって権限付与データを一回だけ初期設定
する コンソール・コマンド を作ることが出来ます。
<?php
namespace app\commands;
use Yii;
use yii\console\Controller;class RbacController extends Controller{
public function actionInit(){$auth = Yii::$app->authManager;$auth->removeAll();// "createPost" という許可を追加する$createPost = $auth->createPermission('createPost');$createPost->description = '記事を投稿';$auth->add($createPost);// "updatePost" という許可を追加$updatePost = $auth->createPermission('updatePost');$updatePost->description = '記事を更新';$auth->add($updatePost);// "author" というロールを追加し、このロールに "createPost" の許可を付与する$author = $auth->createRole('author');$auth->add($author);$auth->addChild($author, $createPost);// "admin" というロールを追加し、このロールに "updatePost" 許可を付与する// 同時に、"author" ロールが持つ許可も付与する$admin = $auth->createRole('admin');$auth->add($admin);$auth->addChild($admin, $updatePost);〴〶〸ぃえぁぐごぅげ 〹〮 セキュリティ$auth->addChild($admin, $author);}// ロールをユーザに割り当てる。1 と 2 は IdentityInterface::getId()
によって返される ID// IdentityInterface::getId() は、通常は User モデルの中で実装される$auth->assign($author, 2);$auth->assign($admin, 1);}

補 足〺 ア ド バ ン ス ト ・ テ ン プ レ ー ト を 使 お う と す る と き
は、RbacController を console/controllers ディレクトリの中に置いて、名前空間を console\controllers に変更する必要があります。
上記のコマンドは、コンソールから次のようにして実行することが出来ます。
yii rbac/init

どのユーザにどのロールを割り当てるかをハードコードした
くない場合は、 コマンドに ->assign() の呼び出しを書かないで下さい。 その代りに、ロールの割り当てを管理する さぉ ま
たはコンソール・コマンドを作成して下さい。

9.3.3

ロールをユーザに割り当てる

投稿者 〨ちふぴとはひ〩 は記事を投稿することが出来、管理者 〨ちつねどの〩 は記事を更新することに加えて投稿者が出来る全てのことが出来ます。
あなたのアプリケーションがユーザ自身によるユーザ登録を許している場合は、新しく登録されたユーザに一度はロールを割り当てる必要があります。 例えば、アドバンスト・プロジェクト・テンプレー
トにお いては、登録したユ ーザの全てを「投稿者」にす るために、
frontend\models\SignupForm::signup() を次のように修正しなければなりません。
public function signup(){if ($this->validate()) {$user = new User();$user->username = $this->username;$user->email = $this->email;$user->setPassword($this->password);$user->generateAuthKey();$user->save(false);// 次の三行が追加されたものです$auth = Yii::$app->authManager;$authorRole = $auth->getRole('author');〹〮〳〮 権限付与〴〶〹

$auth->assign($authorRole, $user->getId());}}

return $user;

return null;

動的に更新される権限付与データを持つ複雑なアクセス制御を必要とするアプリケーションについては、 authManager が提供する ぁぐぉ を使って、特別なユーザ・インタフェイス 〨つまり、管理パネル〩 を開発する必要があるでしょう。
規則を使う
既に述べたように、規則がロールと許可に制約を追加します。規則は べどど
ぜひぢちっぜげふぬづ を拡張したクラスであり、 づへづっふぴづ〨〩 メソッドを実装しなけ
ればなりません。前に作った権限階層においては、投稿者は自分自身の記事を編集することが出来ませんでした。 これを修正しましょう。最初に、ユーザが記事の投稿者であることを確認する規則が必要です。
namespace app\rbac;
use yii\rbac\Rule;use app\models\Post;/*** authorID がパラメータで渡されたユーザと一致するかチェックする*/
class AuthorRule extends Rule{
public $name = 'isAuthor';/*** @param string|int $user ユーザ ID* @param Item $item この規則が関連付けられているロールまたは許可* @param array $params ManagerInterface::checkAccess() に渡されたパラ
メータ* @return bool 関連付けられたロールまたは許可を認めるか否かを示す値*/
public function execute($user, $item, $params){
return isset($params['post']) ? $params['post']->createdBy == $user: false;}}

上の規則は、post が $user によって作成されたかどうかをチェックします。 次に、前に使ったコマンドの中で、updateOwnPost という特別な許可を作成します。

〴〷〰

ぃえぁぐごぅげ 〹〮 セキュリティ$auth = Yii::$app->authManager;// 規則を追加する$rule = new \app\rbac\AuthorRule;$auth->add($rule);// "updateOwnPost" という許可を作成し、それに規則を関連付ける$updateOwnPost = $auth->createPermission('updateOwnPost');$updateOwnPost->description = '自分の記事を更新';$updateOwnPost->ruleName = $rule->name;$auth->add($updateOwnPost);// "updateOwnPost" は "updatePost" から使われる$auth->addChild($updateOwnPost, $updatePost);// "author" に自分の記事を更新することを許可する$auth->addChild($author, $updateOwnPost);

これで、次のような権限階層になります。

〹〮〳〮 権限付与〴〷〱

アクセス・チェック
権限付与データが準備できてしまえば、アクセス・チェックは べどどぜひぢちっ
ぜきちのちでづひぉのぴづひてちっづ〺〺っとづっにぁっっづびび〨〩 メソッドを呼ぶだけの簡単な仕事です。 たいていのアクセス・チェックは現在のユーザに関するものですから、すどど は、便利なように、べどどぜぷづぢぜさびづひ〺〺っちの〨〩 というショートカッ
ト・メソッドを提供しています。 これは、次のようにして使うことが出来ます。
if (\Yii::$app->user->can('createPost')) {// 記事を作成する}

現在のユーザが ID=1 である おちのづ であるとすると、createPost からスター
トして Jane まで到達しようと試みます。

ユーザが記事を更新することが出来るかどうかをチェックするためには、前に説明した AuthorRule によって要求される追加のパラメータを渡す必要があります。

〴〷〲

ぃえぁぐごぅげ 〹〮 セキュリティ

if (\Yii::$app->user->can('updatePost', ['post' => $post])) {// 記事を更新する}

現在のユーザが おはとの であるとすると、次の経路をたどります。

updatePost からスタートして、updateOwnPost を通過します。通過する
ためには、AuthorRule が execute メソッドで true を返さなければなりません。 execute メソッドは can メソッドの呼び出しから $params を受け取りますので、その値は ['post' => $post] です。 すべて くか であれば、おはとのに割り当てられている author に到達します。

おちのづ の場合は、彼女が管理者であるため、少し簡単になります。

〹〮〳〮 権限付与〴〷〳

コントローラ内で権限付与を実装するのには、いくつかの方法があります。 追加と削除に対するアクセス権を分離する細分化された許可が必要な場合は、それぞれのアクションに対してアクセス権をチェックする
必要があります。 各アクション・メソッドの中で上記の条件を使用する
か、または べどどぜてどぬぴづひびぜぁっっづびびぃはのぴひはぬ を使います。
public function behaviors(){
return ['access' => ['class' => AccessControl::class,'rules' => [['allow' => true,'actions' => ['index'],'roles' => ['managePost'],],['allow' => true,'actions' => ['view'],〴〷〴

ぃえぁぐごぅげ 〹〮 セキュリティ

],
[

],
[

],
[

}

];

],

],

],

'roles' => ['viewPost'],'allow' => true,'actions' => ['create'],'roles' => ['createPost'],'allow' => true,'actions' => ['update'],'roles' => ['updatePost'],'allow' => true,'actions' => ['delete'],'roles' => ['deletePost'],

全ての ぃげさい 操作がまとめて管理される場合は、managePost のような単一の許可を使い、 べどどぜぷづぢぜぃはのぴひはぬぬづひ〺〺ぢづてはひづぁっぴどはの〨〩 の中でそれをチェックするのが良いアイデアです。
上記の例では、アクションにアクセスするために必要と指定された
ロールについて、パラメータは渡されていません。 しかし、updatePost
許可の場合は、それが正しく動作するためには post パラメータを渡す必
要があります。 アクセス規則の中で ひはぬづぐちひちねび を指定することによって、 べどどぜぷづぢぜさびづひ〺〺っちの〨〩 にパラメータを渡すことが出来ます。
[],'allow' => true,'actions' => ['update'],'roles' => ['updatePost'],'roleParams' => function() {return ['post' => Post::findOne(['id' =>Yii::$app->request->get('id')])];},

上記の例では、ひはぬづぐちひちねび はアクセス規則がチェックされるときに評価されるクロージャになっています。 従って、モデルは必要になったとき
だけロードされます。 ロール・パラメータの作成が簡単な操作である場
合は、次のように、単に配列を指定しても構いません。
[],'allow' => true,'actions' => ['update'],'roles' => ['updatePost'],'roleParams' => ['postId' => Yii::$app->request->get('id')],〹〮〳〮 権限付与〴〷〵

デフォルト・ロールを使う
デフォルト・ロールというのは、全て のユーザに 黙示的 に割り当てられるロールです。 べどどぜひぢちっぜきちのちでづひぉのぴづひてちっづ〺〺ちびびどでの〨〩 を呼び出す必要はなく、権限付与データはその割り当て情報を含みません。
デフォルト・ロールは、通常、そのロールが当該ユーザに適用されるかどうかを決定する規則と関連付けられます。
デフォルト・ロールは、たいていは、何らかのロールの割り当てを既に持っているアプリケーションにおいて使われます。 例えば、アプ
リケーションによっては、ユーザのテーブルに 【でひはふば】 というカラムを持って、個々のユーザが属する特権グループを表している場合があります。 それぞれの特権グループを げあぁぃ ロールに対応付けることが出来るのであれば、デフォルト・ロールの機能を使って、それぞれのユーザにげあぁぃ ロールを自動的に割り当てることが出来ます。 どのようにすればこれが出来るのか、例を使って説明しましょう。
ユーザのテーブルに group というカラムがあって、〱 は管理者グループ、〲 は投稿者グループを示していると仮定しましょう。 これら二つのグループの権限を表すために、それぞれ、admin と author という げあぁぃ
ロールを作ることにします。 このとき、次のように げあぁぃ データをセッ
トアップすることが出来ます。
namespace app\rbac;
use Yii;
use yii\rbac\Rule;/*** ユーザのグループが合致するかどうかをチェックする*/
class UserGroupRule extends Rule{
public $name = 'userGroup';}

public function execute($user, $item, $params){
if (!Yii::$app->user->isGuest) {$group = Yii::$app->user->identity->group;
if ($item->name === 'admin') {return $group == 1;} elseif ($item->name === 'author') {return $group == 1 || $group == 2;}}
return false;}

次に、前のセクション で説明したように、あなた独自のコマンド〯マイグ
レーションを作成します。

〴〷〶

ぃえぁぐごぅげ 〹〮 セキュリティ$auth = Yii::$app->authManager;$rule = new \app\rbac\UserGroupRule;$auth->add($rule);$author = $auth->createRole('author');$author->ruleName = $rule->name;$auth->add($author);// ... $author の子として許可を追加 ...
$admin = $auth->createRole('admin');$admin->ruleName = $rule->name;$auth->add($admin);$auth->addChild($admin, $author);// ... $admin の子として許可を追加 ...

上記において、〢ちふぴとはひ】 が 【ちつねどの】 の子として追加されているため、規則クラスの execute() メソッドを実装する時には、 この階層関係にも配慮しなければならないことに注意してください。 このために、ロール名が【ちふぴとはひ】 である場合には、execute() メソッドは、ユーザのグループが 〱または 〲 である 〨ユーザが 【ちつねどの】 グループまたは 【ちふぴとはひ】 グループに属している〩 ときに ぴひふづ を返しています。
次に、authManager の構成情報で、この二つのロールを べどどぜひぢちっぜあちびづきちのちでづひ〺〺〤つづてちふぬぴげはぬづび としてリストします。
return [// ...
'components' => ['authManager' => ['class' => 'yii\rbac\PhpManager','defaultRoles' => ['admin', 'author'],],// ...
],];

このようにすると、アクセス・チェックを実行すると、admin と author の両方のロールは、それらと関連付けられた規則を評価することによってチェックされるようになります。 規則が ぴひふづ を返せば、そのロールが現在のユーザに適用されることになります。 上述の規則の実装に基づいて言えば、ユーザの group の値が 〱 であれば admin ロールがユーザに適用され、 group の値が 〲 であれば author ロールが適用されるということを意
味します。

9.4

パスワードを扱う

ほとんどの開発者はパスワードを平文テキストで保存してはいけないということを知っていますが、パスワードを md5 や sha1 でハッシュしてもまだ安全だと思っている開発者がたくさんいます。かつては、前述の〹〮〵〮 暗号化〴〷〷

ハッシュ・アルゴリズムを使えば十分であった時もありましたが、 それらのハッシュや更に強力なハッシュでも、現代のハードウェアをもってすればブルート・フォース・アタックを使って非常に簡単にクラックすることが可能です。
最悪のシナリオ 〨アプリケーションに侵入された場合〩 であっても、ユーザのパスワードについて強化されたセキュリティを提供することが出来るように、 ブルート・フォース・アタックに対する耐性が強いハッシュ・アルゴリズムを使う必要があります。現在、最善の選択は bcryptです。 ぐえぐ では、っひべばぴ 関数4 を使って bcrypt ハッシュを生成することが出来ます。 すどど は crypt を使ってハッシュを安全に生成し検証することを容易にするために、二つのヘルパ関数を提供しています。
ユーザが初めてパスワードを提供するとき 〨例えば、ユーザ登録の時〩には、パスワードをハッシュする必要があります。
$hash = Yii::$app->getSecurity()->generatePasswordHash($password);

そして、ハッシュを対応するモデル属性と関連付けて、後で使用するためにデータベースに保存します。
ユーザがログインを試みたときは、送信されたパスワードは、前にハッシュされて保存されたパスワードと照合して検証されなければなりません。
if (Yii::$app->getSecurity()->validatePassword($password, $hash)) {// よろしい、ユーザをログインさせる} else {// パスワードが違う
}

9.5

暗号化

このセクションでは、セキュリティの以下の側面について見ていきます。
• 乱数データの生成• 暗号化と復号化• データの完全性の確認

9.5.1

擬似乱数データを生成する

擬似乱数データはさまざまな状況で役に立ちます。 例えば、メール経由
でパスワードをリセットするときは、トークンを生成してデータベースに保存し、それをユーザにメールで送信します。 そして、ユーザはこのトークンを自分がアカウントの所有者であることの証拠として使用します。このトークンがユニークかつ推測困難なものであることは非常に重4https://www.php.net/manual/ja/function.crypt.php〴〷〸ぃえぁぐごぅげ 〹〮 セキュリティ

要なことです。 さもなくば、攻撃者がトークンの値を推測してユーザのパスワードをリセットする可能性があります。
すどど のセキュリティヘルパは擬似乱数データの生成を単純な作業にしてくれます。
$key = Yii::$app->getSecurity()->generateRandomString();

9.5.2

暗号化と復号化

すどど は秘密鍵を使ってデータを暗号化〯復号化することを可能にする便利なヘルパ関数を提供しています。データを暗号化関数に渡して、秘密鍵を持つ者だけが復号化することが出来るようにすることが出来ます。 例
えば、何らかの情報をデータベースに保存する必要があるけれども、〨たとえアプリケーションのデータベースが第三者に漏洩した場合でも〩 秘密
鍵を持つユーザだけがそれを見ることが出来るようにする必要がある、という場合には次のようにします。
// $data と $secretKey はフォームから取得する$encryptedData = Yii::$app->getSecurity()->encryptByPassword($data,$secretKey);// $encryptedData をデータベースに保存する

そして、後でユーザがデータを読みたいときは、次のようにします。
// $secretKey はユーザ入力から取得、$encryptedData はデータベースから取得$data = Yii::$app->getSecurity()->decryptByPassword($encryptedData,$secretKey);

べどどぜぢちびづぜこづっふひどぴべ〺〺づのっひべばぴあべかづべ〨〩 と べどどぜぢちびづぜこづっふひどぴべ〺〺つづっひべばぴあべかづべ〨〩によって、 パスワードの代わりにキーを使うことも可能です。

9.5.3

データの完全性を確認する

データが第三者によって改竄されたり、更には何らかの形で毀損された
りしていないことを確認する必要がある、という場合があります。すどど は二つのヘルパ関数の形で、データの完全性を確認するための簡単な方法を提供しています。
秘密鍵とデータから生成されたハッシュをデータにプレフィクスします。
// $secretKey はアプリケーションまたはユーザの秘密、$genuineData は信頼できるソースから取得$data = Yii::$app->getSecurity()->hashData($genuineData, $secretKey);

データの完全性が毀損されていないかチェックします。
// $secretKey はアプリケーションまたはユーザの秘密、$data は信頼できないソース
から取得$data = Yii::$app->getSecurity()->validateData($data, $secretKey);〹〮〶〮 セキュリティのベスト・プラクティス

9.6

〴〷〹

セキュリティのベスト・プラクティス

下記において、一般的なセキュリティの指針を復習し、すどど を使ってアプ
リケーションを開発するときに脅威を回避する方法を説明します。 これらの原則のほとんどのものは すどど に固有のものではなく、ウェブ・サイ
トまたはソフトウェアの開発一般に適用されるものです。 従って、これ
らの原則の背後にある一般的な考え方について、さらに参照すべき文書へのリンクが追加されています。

9.6.1

基本的な指針どのようなアプリケーションが開発されているかに関わらず、セキュリ
ティに関しては二つの大きな指針が存在します。
〱〮 入力をフィルタする。
〲〮 出力をエスケープする。
入力をフィルタする
入力をフィルタするとは、入力値は決して安全なものであると見なさず、取得した値が実際に許容されるものであるかどうかを、 常にチェッ
クしなければならない、ということを意味します。例えば、並べ替えが三つのフィールド title、created_at および status によって実行され、フィールドの名前がユーザの入力によって提供されるものであることが判っている場合、取得した値を受信するその場でチェックする方が良い、ということです。 基本的な ぐえぐ の形式では、次のようなコードになります。
$sortBy = $_GET['sort'];if (!in_array($sortBy, ['title', 'created_at', 'status'])) {throw new Exception('sort の値が不正です。');}

すどど においては、たいていの場合、同様のチェックを行うために フォー
ムの検証 を使うことになるでしょう。
このトピックについて更に読むべき文書〺• とぴぴばび〺〯〯はぷちびば〮はひで〯ぷぷぷ〭っはねねふのどぴべ〯ぶふぬのづひちぢどぬどぴどづび〯ぉねばひはばづひたいちぴちた
ざちぬどつちぴどはの• とぴぴばび〺〯〯ぷぷぷ〮はぷちびば〮はひで〯どのつづへ〮ばとば〯ぉのばふぴたざちぬどつちぴどはのたぃとづちぴたことづづぴ
出力をエスケープする
データを使用するコンテキストに応じて、出力をエスケープしなければなりません。 つまり、えごきが のコンテキストでは、< や > などの特殊な文字をエスケープしなければなりません。 おちぶちこっひどばぴ や こけが のコンテキ〴〸〰

ぃえぁぐごぅげ 〹〮 セキュリティ

ストでは、対象となる文字は別のセットになります。 全てを手動でエスケープするのは間違いを生じやすいことですから、すどど は異なるコンテキ
ストに応じたエスケープを実行するためのさまざまなツールを提供しています。
このトピックについて更に読むべき文書〺• とぴぴばび〺〯〯はぷちびば〮はひで〯ぷぷぷ〭っはねねふのどぴべ〯ちぴぴちっにび〯ぃはねねちのつたぉのなづっぴどはの• とぴぴばび〺〯〯はぷちびば〮はひで〯ぷぷぷ〭っはねねふのどぴべ〯ちぴぴちっにび〯ぃはつづたぉのなづっぴどはの• とぴぴばび〺〯〯はぷちびば〮はひで〯ぷぷぷ〭っはねねふのどぴべ〯ちぴぴちっにび〯へびび〯

9.6.2

SQL インジェクションを回避する

こけが インジェクションは、次のように、エスケープされていない文字列を連結してクエリ・テキストを構築する場合に発生します。
$username = $_GET['username'];$sql = "SELECT * FROM user WHERE username = '$username'";

正しいユーザ名を提供する代りに、攻撃者は '; DROP TABLE user; -- のような文字列をあなたのアプリケーションに与えることが出来ます。 結果として構築される こけが は次のようになります。
SELECT * FROM user WHERE username = ''; DROP TABLE user; --'これは有効なクエリで、空のユーザ名を持つユーザを探してから、user
テーブルを削除します。 おそらく、ウェブ・サイトは破壊されて、データは失われることになります 〨定期的なバックアップは設定済みですよね、ね〿 〩。
すどど においては、ほとんどのデータベース・クエリは、ぐいく のプリペ
アド・ステートメントを適切に使用する アクティブ・レコード を経由して実行されます。 プリペアド・ステートメントの場合は、上で説明したようなクエリの改竄は不可能です。
それでも、生のクエリ や クエリ・ビルダ を必要とする場合はあります。 その場合には、データを渡すための安全な方法を使わなければなりません。データをカラムの値として使う場合は、プリペアド・ステート
メントを使うことが望まれます。
// クエリ・ビルダ$userIDs = (new Query())->select('id')->from('user')->where('status=:status', [':status' => $status])->all();// DAO$userIDs = $connection->createCommand('SELECT id FROM user where status=:status')->bindValues([':status' => $status])->queryColumn();〹〮〶〮 セキュリティのベスト・プラクティス〴〸〱

データがカラム名やテーブル名を指定するために使われる場合は、事前定義された一連の値だけを許可するのが最善の方法です。
function actionList($orderBy = null){if (!in_array($orderBy, ['name', 'status'])) {throw new BadRequestHttpException('name と status だけを並べ替えに使うことが出来ます。')}}// ...

それが不可能な場合は、テーブル名とカラム名をエスケープしなければなりません。 すどど はそういうエスケープのための特別な文法を持っており、それを使うと、サポートされている全てのデータベースに対して同じ方法でエスケープすることが出来ます。
$sql = "SELECT COUNT([[$column]]) FROM {{table}}";$rowCount = $connection->createCommand($sql)->queryScalar();

この文法の詳細は、テーブルとカラムの名前を引用符で囲む で読むことが出来ます。
このトピックについて更に読むべき文書〺• とぴぴばび〺〯〯はぷちびば〮はひで〯ぷぷぷ〭っはねねふのどぴべ〯ちぴぴちっにび〯こけがたぉのなづっぴどはの

9.6.3

XSS を回避する

じここ すなわちクロス・サイト・スクリプティングは、ブラウザに えごきがを出力する際に、出力が適切にエス ケープされ ていないと発生します 。 例 え ば 、 ユ ー ザ 名 を 入 力 で き る フ ォ ー ム で Alexander の 代 り に<script>alert('Hello!');</script> と入力した場合、 ユーザ名をエスケー
プせずに出力している全てのページでは、おちぶちこっひどばぴ alert('Hello!'); が実行されて、ブラウザにアラート・ボックスがポップアップ表示されます。 ウェブ・サイト次第では、そのようなスクリプトを使って、無害なアラートではなく、あなたの名前を使ってメッセージを送信したり、 さらには銀行取引を実行したりすることが可能です。
じここ の回避は、すどど においてはとても簡単です。一般に、二つのケースがあります。
〱〮 データをプレーン・テキストとして出力したい。
〲〮 データを えごきが として出力したい。
プレーン・テキストしか必要でない場合は、エスケープは次のようにとても簡単です。
<?= \yii\helpers\Html::encode($username) ?>〴〸〲ぃえぁぐごぅげ 〹〮 セキュリティ

えごきが である場合は、えぴねぬぐふひど〜づひ から助けを得ることが出来ます。
<?= \yii\helpers\HtmlPurifier::process($description) ?>えぴねぬぐふひど〜づひ の処理は非常に重いので、キャッシュを追加することを検討してください。
このトピックについて更に読むべき文書〺• とぴぴばび〺〯〯はぷちびば〮はひで〯ぷぷぷ〭っはねねふのどぴべ〯ちぴぴちっにび〯へびび〯

9.6.4

CSRF を回避する

ぃこげう は、クロス・サイト・リクエスト・フォージェリ 〨っひはびび〭びどぴづ ひづぱふづびぴてはひでづひべ〩 の略称です。 多くのアプリケーションは、ユーザのブラウザから来るリクエストはユーザ自身によって発せられたものだと仮定しているけれども、その仮定は間違っているかもしれない 〮 〮 〮 というのがぃこげう の考え方です。
例えば、an.example.com というウェブ・サイトが /logout という さげが を持っており、 この さげが を単純な ぇぅご でアクセスするとユーザをログアウトさせるようになっているとします。 ユーザ自身によってこの さげが がリクエストされる限りは何も問題はありませんが、ある日、悪い奴が、ユーザが頻繁に訪れるフォーラムに <img src="https://an.example.com/logout">というリンクを含むコンテントを何らかの方法で投稿します。 ブラウザ
は画像のリクエストとページのリクエストの間に何ら区別を付けませんので、ユーザがそのような img タグを含むページを開くとブラウザは
その さげが に対して ぇぅご リクエストを送信します。 そして、ユーザがan.example.com からログアウトされてしまうことになる訳です。
これは ぃこげう 攻撃がどのように動作するかという基本的な考え方です。ユーザがログアウトされるぐらいは大したことではない、と言うことも出来るでしょう。 しかしこれは例に過ぎません。この考え方を使って、支払いを開始させたり、データを変更したりというような、もっとひどいことをすることも出来ます。 https://an.example.com/purse/transfer?to=anotherUser&amountという さげが を持つウェブ・サイトがあると考えて見てください。このさげが に ぇぅご リクエストを使ってアクセスすると、権限を持つユーザ・アカウントから anotherUser に 〤〲〰〰〰 が送金されるのです。 私たちは、ブラウザは画像をロードするのに常に ぇぅご リクエストを使う、ということを知っていますから、 この さげが が ぐくこご リクエストだけを受け入れる
ようにコードを修正することは出来ます。 しかし残念なことに、それで問題が解決する訳ではありません。攻撃者は <img> タグの代りに何らかの
おちぶちこっひどばぴ コードを書いて、 その さげが に対する ぐくこご リクエストの送信を可能にすることが出来ます。
これを理由として、すどど は ぃこげう 攻撃を防御するための追加のメカニ
ズムを適用します。
ぃこげう を回避するためには、常に次のことを守らなければなりません。

〹〮〶〮 セキュリティのベスト・プラクティス〴〸〳〱〮 えごごぐ の規格、すなわち、ぇぅご はアプリケーションの状態を変更すべきではない、という規則に従うこと。 詳細は げうぃ〲〶〱〶5 を参照
して下さい。
〲〮 すどど の ぃこげう 保護を有効にしておくこと。
場合によっては、コントローラやアクションの単位で ぃこげう 検証を無効化する必要があることがあるでしょう。これは、そのプロパティを設定することによって達成することが出来ます。
namespace app\controllers;
use yii\web\Controller;class SiteController extends Controller{
public $enableCsrfValidation = false;
public function actionIndex(){// CSRF 検証はこのアクションおよびその他のアクションに対して適用されない}}

特定のアクションに対して ぃこげう 検証を無効化したいときは、次のようにすることが出来ます。
namespace app\controllers;
use yii\web\Controller;class SiteController extends Controller{
public function beforeAction($action){// ... ここで何らかの条件に従って `$this->enableCsrfValidation` を設定する ...
// 親のメソッドを呼ぶ。プロパティが true であれば、その中で CSRF がチェックされる。
return parent::beforeAction($action);}}

スタンドアロン・アクション における ぃこげう 検証の無効化は init() メ
ソッドの中で行わなければなりません。 このコードは beforeRun() メソッドに置いてはいけません。そこでは効果がありません。
5https://www.rfc-editor.org/rfc/rfc9110.html#name-method-definitions〴〸〴ぃえぁぐごぅげ 〹〮 セキュリティ<?php
namespace app\components;
use yii\base\Action;
class ContactAction extends Action{
public function init(){
parent::init();$this->controller->enableCsrfValidation = false;}}

public function run(){$model = new ContactForm();$request = Yii::$app->request;
if ($request->referrer === 'yiipowered.com'&& $model->load($request->post())&& $model->validate()) {$model->sendEmail();}}警告〺 ぃこげう を無効化すると、あらゆるサイトから ぐくこご リク
エストをあなたのサイトに送信することが出来るようになります。その場合には、ぉぐ アドレスや秘密のトークンをチェックするなど、追加の検証を実装することが重要です。
補足〺 バージョン 〲〮〰〮〲〱 以降、すどど は sameSite クッキー設定〨ぐえぐ バージョン 〷〮〳〮〰 以上が必要〩 をサポートしています。
ただし、sameSite クッキー設定を行えば、上記の ぃこげう 対策が不要になるということではありません。何故なら、今はまだ全てのブラウザがこの設定をサポートしている訳ではないからです。 詳細については セッションとクッキー 〭 びちねづこどぴづ
オプション を参照して下さい。
このトピックについて更に読むべき文書〺• とぴぴばび〺〯〯はぷちびば〮はひで〯ぷぷぷ〭っはねねふのどぴべ〯ちぴぴちっにび〯っびひて• とぴぴばび〺〯〯はぷちびば〮はひで〯ぷぷぷ〭っはねねふのどぴべ〯こちねづこどぴづ

9.6.5

ファイルの曝露を回避する

デフォルトでは、サーバのウェブ・ルートは、index.php がある web ディ
レクトリを指すように意図されています。 共有ホスティング環境の場
合、それをすることが出来ずに、全てのコード、構成情報、ログをサー
バのウェブ・ルートの下に置かなくてはならないことがあり得ます。

〹〮〶〮 セキュリティのベスト・プラクティス〴〸〵

そういう場合には、web 以外の全てに対してアクセスを拒否することを忘れないでください。 それも出来ない場合は、アプリケーションを別の場所でホストすることを検討してください。

9.6.6

本番環境ではデバッグ情報とデバッグ・ツールを無効にする

デバッグ・モードでは、すどど は極めて多くのエラー情報を出力します。
これは確かに開発には役立つものです。 しかし、実際の所、これらの饒
舌なエラー情報は、攻撃者にとっても、データベース構造、構成情報の値、コードの断片などを曝露してくれる重宝なものです。 本番でのアプ
リケーションにおいては、決して index.php の YII_DEBUG を true にして走らせてはいけません。
本番環境では ぇどど やデバッグ・ツール・バーを決して有効にしてはいけません。 これらを有効にすると、データベース構造とコードに関する情報を得ることが出来るだけでなく、コードを ぇどど によって生成したもので書き換えることすら出来てしまいます。
デバッグ・ツール・バーは本当に必要でない限り本番環境では使用を避けるべきです。これはアプリケーションと構成情報の全ての詳細を曝露することが出来ます。 どうしても必要な場合は、あなたの ぉぐ だけに
適切にアクセス制限されていることを再度チェックしてください。
このトピックについて更に読むべき文書〺• とぴぴばび〺〯〯はぷちびば〮はひで〯ぷぷぷ〭ばひはなづっぴ〭〮のづぴ〯ちひぴどっぬづび〯ぅへっづばぴどはのたえちのつぬどので〮ねつ• とぴぴばび〺〯〯はぷちびば〮はひで〯ぷぷぷ〭ばつて〭ちひっとどぶづ〯くしぁこぐたごはばた〱〰た〲〰〰〷〮ばつて 〨ぁ〶〭 ぉのてはひねちぴどはの がづちにちでづ ちのつ ぉねばひはばづひ ぅひひはひ えちのつぬどので〩

9.6.7

TLS によるセキュアな接続を使う

すどど が提供する機能には、クッキーや ぐえぐ セッションに依存するものがあります。これらのものは、接続が侵害された場合には、脆弱性となり得ます。 アプリケーションが ごがこ 〨しばしば ここが6 と呼ばれます〩 による
セキュアな接続を使用している場合は、この危険性を減少させることが出来ます。
その設定の仕方については、あなたのウェブ・サーバのドキュメントの指示を参照してください。 え〵あぐ プロジェクトが提供する構成例を参考にすることも出来ます。
• ぎでどのへ7• ぁばちっとづ8 〮• ぉぉこ9 〮https://ja.wikipedia.org/wiki/Transport_Layer_Security
https://github.com/h5bp/server-configs-nginx
8
https://github.com/h5bp/server-configs-apache9
https://github.com/h5bp/server-configs-iis
6
7

〴〸〶

ぃえぁぐごぅげ 〹〮 セキュリティ• がどでとぴぴばつ10 〮補足〺 ごがこ が構成されているときは、〨セッションの〩クッキー
を ごがこ のみで送信することが推奨されます。 これは、セッション および〯または クッキーのの secure フラグを設定する
ことで達成されます。 詳細は セッションとクッキー 〭 びづっふひづ
フラグ を参照して下さい。

9.6.8

サーバの構成をセキュアにする

このセクションの目的は、すどど ベースのウェブ・サイトをホストするサーバの構成を作成するときに、 考慮に入れなければならないリスクに照明を当てることにあります。 ここで触れられる問題点以外にも、セキュリ
ティに関連して考慮すべき構成オプションがあるかもしれません。 このセクションの説明が完全であるとは考えないで下さい。
ヘッダ攻撃を避ける
べどどぜぷづぢぜさひぬきちのちでづひ や べどどぜとづぬばづひびぜさひぬ のクラスは、リンクを生成するために 現在リクエストされているホスト名 を使うことがあります。 ウェ
ブ・サーバが Host ヘッダの値とは無関係に同じサイトとして応答する
ように構成されている場合は、 この情報は信頼できないものになっており、えごごぐ リクエストを送信するユーザによって偽装されている11 可能性があります。 そのような状況においては、ウェブ・サーバの構成を改修して、指定されたホスト名に対してのみ応答するようにするか、 または、request アプリケーション・コンポーネントの とはびぴぉのては プロパティを設定して、 ホスト名の値を明示的に設定ないしフィルタするか、どちらかの対策を取るべきです。
サーバの構成についての詳細な情報は、ウェブ・サーバのドキュメン
トを参照して下さい。
• ぁばちっとづ 〲〺 とぴぴばび〺〯〯とぴぴばつ〮ちばちっとづ〮はひで〯つはっび〯ぴひふのに〯ぶとはびぴび〯づへちねばぬづび〮とぴねぬ〣つづてちふぬぴちぬぬばはひぴび• ぎでどのへ〺 とぴぴばび〺〯〯ぷぷぷ〮のでどのへ〮っはね〯ひづびはふひっづび〯ぷどにど〯びぴちひぴ〯ぴはばどっび〯づへちねばぬづび〯
びづひぶづひたぢぬはっにび〯
サーバの構成にアクセスする権限がない場合は、このような攻撃に対して防御するために、べどどぜてどぬぴづひびぜえはびぴぃはのぴひはぬ フィルタを設定することが出来ます。
// ウェブ・アプリケーション構成ファイル
return ['as hostControl' => ['class' => 'yii\filters\HostControl','allowedHosts' => [1011https://github.com/h5bp/server-configs-lighttpdhttps://www.acunetix.com/vulnerabilities/web/host-header-attack〹〮〶〮 セキュリティのベスト・プラクティス〴〸〷'example.com','*.example.com',],'fallbackHostInfo' => 'https://example.com',],// ...

];

補足〺 「ホスト・ヘッダ攻撃」に対する保護のためには、常に、フィルタの使用よりもウェブ・サーバの構成を優先すべきです。 べどどぜてどぬぴづひびぜえはびぴぃはのぴひはぬ は、サーバの構成が出来ない場合にだけ使うべきものです。
ここが ピア検証を構成する
ここが 証明書検証の問題、例えば 〺cURL error 60: SSL certificate problem: unable to get local issuer
certificate

またはstream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL
Error messages: error:1416F086:SSL
routines:tls_process_server_certificate:certificate verify failedを解決する方法については、典型的な誤解があります。ここが ピア検証を無効化するよう示唆する間違った情報が数多くありますが、決して従ってはいけません。 そんなことをすれば、マン・イン・ザ・ミドル型の攻撃を可能にします。そうするのではなく、ぐえぐ を適切に構成すべきです。
〱〮 とぴぴばび〺〯〯っふひぬ〮とちへへ〮びづ〯っち〯っちっづひぴ〮ばづね12 をダウンロードする。
〲〮 ばとば〮どのど に 以 下 を 追 加 す る 。

openssl.cafile="/path/to/cacert.pem"

curl.cainfo="/path/to/cacert.pem".
cacert.pem ファイルを最新に保つ必要があることに注意して下さい。

12https://curl.haxx.se/ca/cacert.pem〴〸〸

ぃえぁぐごぅげ 〹〮 セキュリティ

Chapter 10

キャッシュ
10.1

キャッシュ

キャッシュはウェブ・アプリケーションのパフォーマンスを向上させるための安価で効果的な方法です。 比較的静的なデータをキャッシュに格納し、要求に応じてキャッシュからそれを取得します。 これによって、アプリケーションは、毎回一からデータを生成した場合に必要になるであろう時間を節約することができます。
キャッシュはアプリケーション内のさまざまなレベルと場所で使用することができます。 例えばサーバ・サイドでの低いレベルでは、デー
タベースから取得した最新の記事情報リストのような 基本的なデータを格納するためにキャッシュを使用することが出来ます。 より高いレベル
では、ウェブ・ページの断片または全体、例えば、最新の記事のレンダ
リング結果を格納するためにキャッシュを使用することが出来ます。 ク
ライアント・サイドでは、最近訪れたページの内容をブラウザのキャッシュに格納するために、えごごぐ キャッシュを使用することができます。
すどど はこれら全てのキャッシュ機構をサポートしています〺• データ・キャッシュ• フラグメント・キャッシュ• ページ・キャッシュ• えごごぐ キャッシュ10.2

データ・キャッシュ

データ・キャッシュは ぐえぐ の変数をキャッシュに格納し、あとでキャッシュからそれらを読み込みます。 これは、クエリ・キャッシュ や ペー
ジ・キャッシュ など、 より高度なキャッシュ機能の基礎でもあります。
以下のコードが、データ・キャッシュの典型的な利用パターンです。
ここで、$cache は キャッシュ・コンポーネント を指しています。
// キャッシュから $data を取得しようと試みる$data = $cache->get($key);

〴〸〹

〴〹〰

ぃえぁぐごぅげ 〱〰〮 キャッシュ

if ($data === false) {// キャッシュの中に $data が見つからない場合は一から作る$data = $this->calculateSomething();// $data をキャッシュに格納して、次回はそれを取得できるようにする$cache->set($key, $data);}// この時点で $data は利用可能になっているバージョン 〲〮〰〮〱〱 以降は、キャッシュ・コンポーネント が提供する
でづぴくひこづぴ〨〩 メソッドを使って、 データを取得、計算、保存するためのコードを単純化することが出来ます。 次に示すコードは、上述の例と全く同じことをするものです。
$data = $cache->getOrSet($key, function () {return $this->calculateSomething();});

キャッシュが $key と関連づけられたデータを保持している場合は、キャッシュされている値が返されます。 そうでない場合は、渡された無名関数が実行されて値が計算され、その値がキャッシュされるとともに返されます。
無名関数が外部のスコープの何らかのデータを必要とする場合は、それを use 文を使って渡すことが出来ます。 例えば、
$user_id = 42;$data = $cache->getOrSet($key, function () use ($user_id) {return $this->calculateSomething($user_id);});

補足〺 でづぴくひこづぴ〨〩 メソッドは、有効期限と依存もサポートしています。 詳しくは キャッシュの有効期限 と キャッシュの依存 を参照してください。

10.2.1キャッシュ・コンポーネント

データ・キャッシュはメモリ、ファイル、データベースなどさまざまな
キャッシュ・ストレージを表す、 いわゆる キャッシュ・コンポーネントに依存しています。
キャッシュ・コンポーネントは通常グローバルに設定しアクセスできるように アプリケーション・コンポーネント として登録されます。 以
下のコードは、二台のキャッシュ・サーバを用いる きづねっちっとづつ1 を使う
ように cache アプリケーション・コンポーネントを構成する方法を示すものです。
1

https://memcached.org/

〱〰〮〲〮 データ・キャッシュ〴〹〱'components' => ['cache' => ['class' => 'yii\caching\MemCache','servers' => [['host' => 'server1','port' => 11211,'weight' => 100,],['host' => 'server2','port' => 11211,'weight' => 50,
],
],
],
],

こうすると、上記のキャッシュ・コンポーネントに Yii::$app->cache という式でアクセスできるようになります。
すべてのキャッシュ・コンポーネントは同じ ぁぐぉ をサポートしているので、アプリケーションの構成情報で設定しなおせば、 キャッシュを使っているコードに変更を加えることなく、異なるキャッシュ・コ
ンポーネントに入れ替えることができます。 例えば上記の構成を ぁぐぃ
キャッシュ を使うように変更する場合は以下のようにします〺'components' => ['cache' => ['class' => 'yii\caching\ApcCache',],],ヒント〺 キャッシュ・コンポーネントは複数登録することができます。cache という名前のコンポーネントが、 キャッシュに依存する多数のクラスによってデフォルトで使用されます 〨例
えば べどどぜぷづぢぜさひぬきちのちでづひ など〩 。
サポートされているキャッシュ・ストレージ
すどど はさまざまなキャッシュ・ストレージをサポートしています。以下がその概要です〺• べどどぜっちっとどのでぜぁばっぃちっとづ〺 ぐえぐ の ぁぐぃ2 拡張モジュールを使用します。 集中型の重厚なアプリケーションのキャッシュを扱うときには最速の一つとして考えることができます 〨例えば、サーバが一台で、専用のロード・バランサを持っていない、などの場合〩。
• べどどぜっちっとどのでぜいぢぃちっとづ〺 キャッシュされたデータを格納するためにデータベースのテーブルを使用します。 このキャッシュを使用する
2

https://www.php.net/manual/ja/book.apc.php〴〹〲

ぃえぁぐごぅげ 〱〰〮 キャッシュには べどどぜっちっとどのでぜいぢぃちっとづ〺〺〤っちっとづごちぢぬづ で指定したテーブルを作成する必要があります。
• べどどぜっちっとどのでぜぁひひちべぃちっとづ〺 配列に値を保存することによって、現在のリクエストのためだけのキャッシュを提供します。 ぁひひちべ〭
ぃちっとづ のパフォーマンスを高めるために、べどどぜっちっとどのでぜぁひひちべぃちっとづ〺〺〤びづひどちぬどぺづひ を false に設定して、 保存するデータのシリアライ
ズを無効にすることが出来ます。 〮• べどどぜっちっとどのでぜいふねねべぃちっとづ〺 実際にはキャッシュを行わない、キャッシュのプレースホルダとして働きます。 このコンポーネントの目的は、キャッシュの可用性をチェックする必要があるコードを簡略化することです。 たとえば、開発中やサーバに実際のキャッシュ・サポートがない場合でも、 このキャッシュを使用するようにキャッシュ・コンポーネントを構成することができます。 そして、実際のキャッシュ・サポートが有効になったときに、対応するキャッシュ・コンポーネントに切替えて使用します。 どちらの場合も、Yii::$app->cache が null かも知れないと心配せずに、 データを取得するために同じコード Yii::$app->cache->get($key) を使用できます。
• べどどぜっちっとどのでぜうどぬづぃちっとづ〺 キャッシュされたデータを保存するために通常のファイルを使用します。 これはページ・コンテントなど大きなかたまりのデータに特に適しています。
• べどどぜっちっとどのでぜきづねぃちっとづ〺 ぐえぐ の きづねっちっとづ3 と きづねっちっとづつ4 拡張モジュールを使用します。 分散型のアプリケーションでキャッシュを扱うときには最速の一つとして考えることができます 〨例えば、複数台のサーバで、ロード・バランサがある、などの場合〩 。
• べどどぜひづつどびぜぃちっとづ〺 げづつどび5 の にづべ〭ぶちぬふづ ス ト ア に 基 づ い て キ ャ ッシュ・コンポーネントを実装しています。 〨げづつどび の バージョン〲〮〶〮〱〲 以降が必要とされます〩 。
• べどどぜっちっとどのでぜしどのぃちっとづ〺 ぐえぐ の しどのぃちっとづ6 エクステンションを使用します。 〨参照リンク7 〩• べどどぜっちっとどのでぜじぃちっとづ (非推奨)〺 ぐえぐ の じぃちっとづ8 拡張モジュールを使用します。
• べどどぜっちっとどのでぜずづのついちぴちぃちっとづ (非推奨)〺 キャッシュ・メディアとして ずづのつ いちぴち ぃちっとづ9 を使用します。
ヒント〺 同じアプリケーション内で異なるキャッシュを使用することもできます。 一般的なやり方として、小さくとも常に

https://www.php.net/manual/ja/book.memcache.php
https://www.php.net/manual/ja/book.memcached.php
5
https://redis.io/
6
https://iis.net/downloads/microsoft/wincache-extension
7
https://www.php.net/manual/ja/book.wincache.php
8
https://en.wikipedia.org/wiki/List_of_PHP_accelerators#XCache9https://files.zend.com/help/Zend-Server-6/zend-server.htm#data_cache_component.htm
34〱〰〮〲〮 データ・キャッシュ〴〹〳

使用されるデータ 〨例えば、統計データ〩 を格納する場合はメ
モリ・ベースのキャッシュ・ストレージを使用し、 大きくて使用頻度の低いデータ 〨例えば、ページ・コンテント〩 を格納
する場合はファイル・ベース、またはデータベースのキャッシュ・ストレージを使用します 。

10.2.2キャッシュ API

すべてのキャッシュ・コンポーネントが同じ基底クラス べどどぜっちっとどのでぜぃちっとづ を持っているので、以下の ぁぐぉ をサポートしています。
• でづぴ〨〩〺 指定されたキーを用いてキャッシュからデータを取得します。 データが見つからないか、もしくは有効期限が切れたり無効になったりしている場合は てちぬびづ を返します。
• びづぴ〨〩〺 キーによって識別されるデータをキャッシュに格納します。
• ちつつ〨〩〺 キーがキャッシュ内で見つからない場合に、キーによって識別されるデータをキャッシュに格納します。
• でづぴくひこづぴ〨〩〺 指定されたキーを用いてキャッシュからデータを取得します。 取得できなかった場合は、渡されたコールバック関数を実行し、関数の返り値をそのキーでキャッシュに保存し、そしてその値を返します。
• ねふぬぴどぇづぴ〨〩〺 指定されたキーを用いてキャッシュから複数のデータを取得します。
• ねふぬぴどこづぴ〨〩〺 キャッシュに複数のデータを格納します。各データはキーによって識別されます。
• ねふぬぴどぁつつ〨〩〺 キャッシュに複数のデータを格納します。 各データはキーによって識別されます。もしキャッシュ内にキーがすでに存在する場合はスキップされます。
• づへどびぴび〨〩〺 指定されたキーがキャッシュ内で見つかったかどうかを示す値を返します。
• つづぬづぴづ〨〩〺 キャッシュからキーによって識別されるデータを削除します。
• てぬふびと〨〩〺 キャッシュからすべてのデータを削除します。
補足〺 ぢははぬづちの 型の false を直接にキャッシュしてはいけません。 なぜなら、でづぴ〨〩 メソッドは、データがキャッシュ内に見つからないことを示すために戻り値として false を使用しているからです。 代りに、配列内に false を置いてキャッシュすることによって、この問題を回避して下さい。
キャッシュされたデータを取得する際に発生するオーバーヘッドを減らすために、きづねぃちっとづ〬 ぁぐぃ などのいくつかのキャッシュ・ストレージは、 バッチ・モードで複数のキャッシュされた値を取得することをサポートしています。 ねふぬぴどぇづぴ〨〩 や ねふぬぴどぁつつ〨〩 などの ぁぐぉ はこの機能を十分に引き出すために提供されています。 基礎となるキャッシュ・ス〴〹〴

ぃえぁぐごぅげ 〱〰〮 キャッシュ

トレージがこの機能をサポートしていない場合には、シミュレートされます。
べどどぜっちっとどのでぜぃちっとづ は ArrayAccess インタフェイスを継承しているので、キャッシュ・コンポーネントは配列のように扱うことができます。
以下はいくつかの例です〺$cache['var1'] = $value1;$value2 = $cache['var2'];// $cache->set('var1', $value1); と同等// $value2 = $cache->get('var2'); と同等

キャッシュのキー
キャッシュに格納される各データは、一意のキーによって識別されます。 キャッシュ内にデータを格納するときはキーを指定する必要があります。 また、あとでキャッシュからデータを取得するときは、それに対応するキーを提供しなければなりません。
キャッシュのキーとしては、文字列または任意の値を使用することができます。 キーが文字列でない場合は、自動的に文字列にシリアライズされます。
キャッシュのキーを定義する一般的なやり方として、全ての決定要素
を配列の形で含めるという方方があります。 例えば べどどぜつぢぜこっとづねち は
データベース・テーブルのスキーマ情報を以下のキーを使用してキャッシュしています。
[];__CLASS__,$this->db->dsn,$this->db->username,$name,// スキーマ・クラス名// データベース接続のデータ・ソース名// データベース接続のログイン・ユーザ// テーブル名

見ての通り、キーは一意にデータベースのテーブルを指定するために必要なすべての情報を含んでいます。
補足〺 ねふぬぴどこづぴ〨〩 または ねふぬぴどぁつつ〨〩 によってキャッシュに保存される値が持つことが出来るのは、 文字列または整数のキーだけです。それらより複雑なキーを設定する必要がある
場合は、 びづぴ〨〩 または ちつつ〨〩 によって、値を個別に保存してください。
同じキャッシュ・ストレージが異なるアプリケーションによって使用されているときは、 キャッシュのキーの競合を避けるために、各アプリ
ケーションではユニークなキーの接頭辞を指定する必要があります。 こ
れは べどどぜっちっとどのでぜぃちっとづ〺〺〤にづべぐひづてどへ プロパティを設定することで出来ます。例えば、アプリケーション構成情報で以下のように書くことができます〺〱〰〮〲〮 データ・キャッシュ〴〹〵'components' => ['cache' => ['class' => 'yii\caching\ApcCache','keyPrefix' => 'myapp',// ユニークなキャッシュのキーの接頭辞],],

相互運用性を確保するために、英数字のみを使用する必要があります。
キャッシュの有効期限
キャッシュに格納されたデータは、何らかのキャッシュ・ポリシー 〨例えば、キャッシュ・スペースがいっぱいになったときは最も古いデータが削除される、など〩 の執行によって除去されない限り、永遠に残り続けます。 この動作を変えるために びづぴ〨〩 を呼んでデータ・アイテムを保存するときに、有効期限パラメータを指定することができます。 このパラメータは、データ・アイテムが何秒間有効なものとしてキャッシュ内に残ることが出来るかを示します。 でづぴ〨〩 でデータ・アイテムを取得する際に有効期限が切れていた場合は、 キャッシュ内にデータが見つからなかったことを示す false が返されます。例えば、// 最大で 45 秒間キャッシュ内にデータを保持する$cache->set($key, $data, 45);
sleep(50);$data = $cache->get($key);if ($data === false) {// $data は有効期限が切れているか、またはキャッシュ内に見つからない}バージョン 〲〮〰〮〱〱 以降は、デフォルトの無限の有効期限に替えて特定の有効期限を指定したい場合には、 キャッシュ・コンポーネントの構成で
つづてちふぬぴいふひちぴどはの の値を指定することが出来ます。 これによって、特定の duration パラメータを毎回 びづぴ〨〩 に渡さなくてもよくなります。
キャッシュの依存
有効期限の設定に加えて、キャッシュされたデータは、いわゆる キャッ
シュの依存 〨キャッシュが依存している事物〩 の変化によって無効にする
こともできます。 例えば べどどぜっちっとどのでぜうどぬづいづばづのつづのっべ は、キャッシュがファイルの更新時刻に依存していることを表しています。 この依存が変化したときは、対応するファイルが更新されたことを意味します。 その結果、キャッシュ内で見つかった古いファイルのコンテントは、無効とされるべきであり でづぴ〨〩 は false を返さなければなりません。
キャッシュの依存は べどどぜっちっとどのでぜいづばづのつづのっべ の子孫クラスのオブジェクトとして表現されます。 びづぴ〨〩 でキャッシュにデータ・アイテム

〴〹〶

ぃえぁぐごぅげ 〱〰〮 キャッシュを格納する際に、 関連するキャッシュの依存のオブジェクトを一緒に渡すことができます。例えば、// example.txt ファイルの更新日時への依存を作成します。
$dependency = new \yii\caching\FileDependency(['fileName' =>'example.txt']);// データは 30 秒で期限切れになります。
// さらに、example.txt が変更された場合、有効期限内でも無効になります。
$cache->set($key, $data, 30, $dependency);// キャッシュはデータの有効期限が切れているかをチェックします。
// 同時に、関連付けられた依存が変更されているかもチェックします。
// これらの条件のいずれかが満たされている場合は false を返します。
$data = $cache->get($key);

以下は利用可能なキャッシュの依存の概要です〺• べどどぜっちっとどのでぜぃとちどのづついづばづのつづのっべ〺 チェーン上のいずれかの依存が変更された場合に、依存が変更されます。
• べどどぜっちっとどのでぜいぢいづばづのつづのっべ〺 指定された こけが 文のクエリ結果が変更された場合、依存が変更されます。
• べどどぜっちっとどのでぜぅへばひづびびどはのいづばづのつづのっべ〺 指定された ぐえぐ の式の結果が変更された場合、依存が変更されます。
• べどどぜっちっとどのでぜうどぬづいづばづのつづのっべ〺 ファイルの最終更新日時が変更された場合、依存が変更されます。
• べどどぜっちっとどのでぜごちでいづばづのつづのっべ〺 キャッシュされるデータ・アイテムに一つまたは複数のタグを関連付けます。 べどどぜっちっとどのでぜごちでいづばづのつづのっべ〺〺どのぶちぬどつちぴづ〨〩 を呼び出すことによって、指定されたタグ 〨複数可〩 を持つキャッシュされたデータ・アイテムを無効にすることができます。
補足〺 依存を有するキャッシュについて づへどびぴび〨〩 メソッドを使用することは避けてください。 このメソッドは、キャッシュされたデータに関連づけられた依存がある場合
でも、依存が変化したかどうかをチェックしません。 つまり、づへどびぴび〨〩 が true を返しているのに、 でづぴ〨〩 が false を返すという場合があり得ます。

10.2.3

クエリ・キャッシュ

クエリ ・キャッシ ュは、デー タ・キャッ シュ上に構築された特別なキャッシュ機能で、 データベースのクエリ結果をキャッシュするために提供されています。
クエリ・キャッシュは データベース接続 と有効な cache アプリケー
ション・コンポーネント を必要とします。 $db を べどどぜつぢぜぃはののづっぴどはの のインスタンスと仮定した場合、クエリ・キャッシュの基本的な使い方は以下のようになります〺〱〰〮〲〮 データ・キャッシュ〴〹〷$result = $db->cache(function ($db) {// クエリ・キャッシュが有効で、かつクエリ結果がキャッシュ内にある場合、// SQL クエリ結果がキャッシュから提供されます
return $db->createCommand('SELECT * FROM customer WHERE
id=1')->queryOne();});

クエリ・キャッシュは いぁく だけではなく アクティブ・レコード でも使用することができます。
$result = Customer::getDb()->cache(function ($db) {return Customer::find()->where(['id' => 1])->one();});

情報〺 いくつかの いあきこ 〨例えば きべこけが10 〩 もデータベース・
サーバ・サイドのクエリ・キャッシュをサポートしています。 どちらのクエリ・キャッシュ・メカニズムを選んでも構いません。 前述した すどど のクエリ・キャッシュにはキャッシュの依存を柔軟に指定できるという利点があり、潜在的にはより効率的です。
〲〮〰〮〱〴 以降は、下記のショートカットを使用することが出来ます。
(new Query())->cache(7200)->all();// およびUser::find()->cache(7200)->all();

構成
クエリ・キャッシュには べどどぜつぢぜぃはののづっぴどはの を通して設定可能な三つのグローバルなオプションがあります〺• づのちぢぬづけふづひべぃちっとづ〺 クエリ・キャッシュを可能にするかどうか。デフォルトは true です。 実効的にクエリ・キャッシュをオンにするには ぱふづひべぃちっとづ によって指定される有効なキャッシュを持っている必要があることに注意してください。
• ぱふづひべぃちっとづいふひちぴどはの〺 これはクエリ結果がキャッシュ内に有効な状態として 持続できる秒数を表します。 クエリ・キャッシュを永遠にキャッシュに残したい場合は 〰 を指定することができます。 このプロパティは べどどぜつぢぜぃはののづっぴどはの〺〺っちっとづ〨〩 が持続時間を指定せず呼び出されたときに使用されるデフォルト値です。
• ぱふづひべぃちっとづ〺 これはキャッシュ・アプリケーション・コンポーネン
トの ぉい を表します。 デフォルトは 'cache' です。有効なキャッシュ・コンポーネントが存在する場合にのみ、クエリ・キャッシュが使用可能になります。
10https://dev.mysql.com/doc/refman/5.1/ja/query-cache.html

〴〹〸

ぃえぁぐごぅげ 〱〰〮 キャッシュ使い方
クエリ・キャッシュを使用する必要がある複数の こけが クエリを持っている場合は べどどぜつぢぜぃはののづっぴどはの〺〺っちっとづ〨〩 を使用することができます。使い方は以下のとおりです。
$duration = 60;$dependency = ...;// クエリ結果を 60 秒間 キャッシュ// 依存のオプション$result = $db->cache(function ($db) {// ... ここで SQL クエリを実行します ...
return $result;}, $duration, $dependency);

無名関数内の任意の こけが クエリは、指定した依存とともに指定された
期間キャッシュされます。 もしキャッシュ内に有効なクエリ結果が見つかった場合は、クエリはスキップされ、代りに結果がキャッシュから提供されます。 $duration の指定がない場合 ぱふづひべぃちっとづいふひちぴどはの で指定されている値が代りに使用されます。
場合によっては cache() 内でいくつかの特定のクエリに対してクエ
リ・キャッシュを無効にしたいことが有るでしょう。 そのときは べどどぜつぢ
ぜぃはののづっぴどはの〺〺のはぃちっとづ〨〩 を使用します。
$result = $db->cache(function ($db) {// クエリ・キャッシュを使用する SQL クエリ$db->noCache(function ($db) {// クエリ・キャッシュを使用しない SQL クエリ});// ...
});

return $result;

単一のクエリのためだけにクエリ・キャッシュを使用したい場合は、コ
マンドを構築するときに べどどぜつぢぜぃはねねちのつ〺〺っちっとづ〨〩 を呼び出すことができます。例えば、// クエリ・キャッシュを使い、期間を 60 秒にセットする$customer = $db->createCommand('SELECT * FROM customer WHERE
id=1')->cache(60)->queryOne();

また、一つのコマンドに対してクエリ・キャッシュを無効にするために
べどどぜつぢぜぃはねねちのつ〺〺のはぃちっとづ〨〩 を使用することもできます。例えば、

〱〰〮〲〮 データ・キャッシュ〴〹〹$result = $db->cache(function ($db) {// クエリ・キャッシュを使用する SQL クエリ// このコマンドにはクエリ・キャッシュを使用しない$customer = $db->createCommand('SELECT * FROM customer WHERE
id=1')->noCache()->queryOne();// ...
});

return $result;

制約
リソース・ハンドラを返すようなクエリにはクエリ・キャッシュは働きません。 例えば、いくつかの いあきこ において あがくあ 型のカラムを用いる場合、 クエリ結果はカラム・データに対するリソース・ハンドラを返します。
いくつかのキャッシュ・ストレージはサイズに制約があります。 例え
ば きづねっちっとづ では、各エントリのサイズは 〱きあ が上限値です。 そのためクエリ結果のサイズがこの制約を越える場合、キャッシュは失敗します。

10.2.4キャッシュのフラッシュ <span id="cache-flushing”>

保存されている全てのキャッシュ・データを無効化する必要がある場合
は、べどどぜっちっとどのでぜぃちっとづ〺〺てぬふびと〨〩 を呼ぶことが出来ます。
コンソールから yii cache/flush を呼ぶことによっても、キャッシュをフラッシュすることが出来ます。
• yii cache〺 アプリケーションで利用可能なキャッシュのリストを表示します。
• yii cache/flush cache1 cache2〺 キャッシュ・コンポーネント cache1 とcache2 をフラッシュします 〨複数のコンポーネント名をスペースで区切って渡すことが出来ます〩• yii cache/flush-all〺 アプリケーションの全てのキャッシュ・コン
ポーネントをフラッシュします。
• yii cache/flush-schema db〺 指定された いあ 接続に対する いあ スキー
マ・キャッシュをクリアします。
情報〺 デフォルトでは、コンソール・アプリケーションは独立した構成情報ファイルを使用します。 正しい結果を得るためには、ウェブとコンソールのアプリケーション構成で同じ
キャッシュ・コンポーネントを使用していることを確認して
ください。

〵〰〰

ぃえぁぐごぅげ 〱〰〮 キャッシュ

10.3

フラグメント・キャッシュ

フラグメント・キャッシュは、ウェブ・ページの断片をキャッシュすることを指します。 例えば、ページ内の表に年間販売の概要が表示されている場合、リクエスト毎にこの表を生成するのにかかる時間を削減するために、キャッシュにこの表を格納することができます。 フラグメン
ト・キャッシュは データ・キャッシュ 上に構築されています。
フラグメント・キャッシュを使用するには ビュー で以下の構文を使用します〺
if ($this->beginCache($id)) {// ... ここに生成するコンテントを書く ...
}$this->endCache();

つまり、コンテント生成ロジックを ぢづでどのぃちっとづ〨〩 と づのつぃちっとづ〨〩 の呼
び出しのペアで囲みます。 コンテントがキャッシュ内で見つかった
場合、ぢづでどのぃちっとづ〨〩 はキャッシュされたコンテントをレンダリングして false を返し、結果として、コンテント生成ロジックがスキップされます。 それ以外の場合はコンテント生成ロジックが呼ばれ、そしてづのつぃちっとづ〨〩 が呼ばれたときに、 生成されたコンテントがキャプチャさ
れ、キャッシュに格納されます。
データ・キャッシュ と同様に、キャッシュされるコンテントを識別するためにユニークな $id が必要になります。

10.3.1キャッシュのオプション

ぢづでどのぃちっとづ〨〩 メソッドの 〲 番目のパラメータとしてオプションの配列を渡すことによって、 フラグメント・キャッシュに関する追加のオプ
ションを指定することができます。 舞台の裏側では、このオプションの配列が、実際のフラグメント・キャッシュ機能を実装する べどどぜぷどつでづぴび
ぜうひちでねづのぴぃちっとづ ウィジェットを構成するために使用されます。
持続時間
おそらくフラグメント・キャッシュで通常よく使われるであろうオプ
ションは つふひちぴどはの でしょう。 このオプションはコンテントがどれだけの時間キャッシュ内において有効であるかを指定します。 以下のコードは最大で 〱 時間コンテントの断片をキャッシュします〺
if ($this->beginCache($id, ['duration' => 3600])) {// ... ここに生成するコンテントを書く ...
}$this->endCache();〱〰〮〳〮 フラグメント・キャッシュ〵〰〱

このオプションがセットされていない場合は、デフォルトである 〶〰 が使われます。すなわち、キャッシュされたコンテントの有効期限は 〶〰 秒後に切れることになります。
依存
データ・キャッシュ と同様に、キャッシュされたコンテントの断片は依存を持つことができます。 例えば、表示されている投稿の内容は、投稿が変更されたか否かに依存します。
依存を指定するには つづばづのつづのっべ オプションに べどどぜっちっとどのでぜいづばづのつづのっべ
オブジェクトを指定するか、または依存オブジェクトを作成するための構成情報配列を指定します。 以下のコードはコンテントの断片がupdated_at カラムの値の変化に依存していることを指定しています〺$dependency = ['class' => 'yii\caching\DbDependency','sql' => 'SELECT MAX(updated_at) FROM post',];
if ($this->beginCache($id, ['dependency' => $dependency])) {// ... ここに生成するコンテントを書く ...
}$this->endCache();バリエーション
キャッシュされるコンテントには、何らかのパラメータによってバリエーションを持たせることが出来ます。 例えば、複数の言語をサポートしているウェブ・アプリケーションでは、ビュー・コードの同じ部分
が言語によってさまざまに異なるコンテントを生成することが有り得ます。 従って、現在のアプリケーションの言語に応じて、キャッシュされるコンテントのバリエーションを持つ必要があります。
キャッシュのバリエーションを指定するには ぶちひどちぴどはのび オプション
を指定します。 このオプションは、それぞれが特定のバリエーションの要素を表すスカラ値の配列でなければなりません。 例えば、言語による
キャッシュ・コンテントのバリエーションを持つためには、以下のコードを使います。
if ($this->beginCache($id, ['variations' => [Yii::$app->language]])) {// ... ここに生成するコンテントを書く ...
}$this->endCache();〵〰〲

ぃえぁぐごぅげ 〱〰〮 キャッシュキャッシュをトグルする
時として、ある条件が満たされた場合にのみフラグメント・キャッシュを有効にしたい場合があるでしょう。 たとえば、フォームが表示されているページでは、フォームをキャッシュしたいのは最初の 〨ぇぅご リクエ
ストによる〩 リクエストの場合だけです。 その後の 〨ぐくこご リクエストによる〩 フォームの表示では、フォームにユーザ入力が含まれている可能性があるため、キャッシュをすべきではありません。 これを行うには、以下のように づのちぢぬづつ オプションをセットします〺
if ($this->beginCache($id, ['enabled' => Yii::$app->request->isGet])) {// ... ここに生成するコンテントを書く ...
}$this->endCache();10.3.2キャッシュのネスト

フラグ メント・キ ャッシュは ネストする ことができ ます。つま り、キャッシュされる断片を、それ自体もキャッシュされる別の断片に入れることができます。 例えば、内側のフラグメント・キャッシュにはコメントがキャッシュされており、外側のフラグメント・キャッシュには記事内容と一緒にコメントもキャッシュされている、という形です。 以下のコードは 〲 つのフラグメント・キャッシュをネストする方法を示すものです。
if ($this->beginCache($id1)) {// ...コンテント生成ロジック...
if ($this->beginCache($id2, $options2)) {// ...コンテント生成ロジック...
}$this->endCache();// ...コンテント生成ロジック...
}$this->endCache();

ネストされたキャッシュには、異なるキャッシュ・オプションを設定することができます。 たとえば、上記の例における内側のキャッシュと外側のキャッシュに対して、異なる持続期間の値を設定する事が可能です。 これによって、外側のキャッシュでキャッシュされたデータが無効になった場合でも、内側のキャッシュが有効な内側の断片を提供することが可能になります。 しかし、その逆は真ではありません。 外側の〱〰〮〳〮 フラグメント・キャッシュ〵〰〳キャッシュが有効であると判断された場合には、内側のキャッシュが無効になった後でも、外側のキャッシュが古くなったコンテントのコピーを提供し続けます。 従って、ネストされたキャッシュの持続時間や依存の設定を間違うと、無効になった内側のキャッシュ・データが外側のキャッシュに残り続けることになるので、注意が必要です。

10.3.3ダイナミック・コンテント

フラグメント・キャッシュを使用する際、出力全体が比較的静的で、一ヶ所ないし数ヶ所だけが例外的に動的であるというような状況に遭遇するでしょう。 例えば、ページのヘッダがメイン・メニュー・バーと現在のユーザ名を一緒に表示している場合です。 もう一つの問題は、キャッシュされるコンテントに、リクエスト毎に実行しなければいけな
い ぐえぐ のコード 〨例えば、アセット・バンドルを登録するためのコード〩が含まれている場合です。 この両方の問題は、いわゆる ダイナミック・
コンテント 機能によって解決することができます。
ダイナミック・コンテントは、それがフラグメント・キャッシュの中に含まれていても、キャッシュすべきではない出力の部分を意味します。 このコンテントを常に動的にするためには、外側のコンテントがキャッシュから提供されている場合でも、 すべてのリクエストに対して、何らかの ぐえぐ コードを実行することにより生成しなければいけません。
ダイナミック・コンテントを目的の場所に挿入するには、以下のように、キャッシュされる断片内で べどどぜぢちびづぜざどづぷ〺〺ひづのつづひいべのちねどっ〨〩 を呼び出します。
if ($this->beginCache($id1)) {// ...コンテント生成ロジック...
echo $this->renderDynamic('return Yii::$app->user->identity->name;');// ...コンテント生成ロジック...
}$this->endCache();ひづのつづひいべのちねどっ〨〩 メソッドはパラメータとして ぐえぐ コードを取ります。
この ぐえぐ コードの戻り値が、ダイナミック・コンテントとして扱われます。 囲んでいる断片がキャッシュから提供されるか否かにかかわらず、
同じ ぐえぐ コードがすべてのリクエストに対して実行されます。
補足〺 バージョン 〲〮〰〮〱〴 以降、べどどぜぢちびづぜいべのちねどっぃはのぴづのぴぁぷちひづぉのぴづひてちっづ
インタフェイスとその べどどぜぢちびづぜいべのちねどっぃはのぴづのぴぁぷちひづごひちどぴ
トレイトによって、ダイナミック・コンテント ぁぐぉ が公開されています。〮 その一例としては、 べどどぜぷどつでづぴびぜうひちでねづのぴぃちっとづ
クラスを参照して下さい。

〵〰〴

10.4

ぃえぁぐごぅげ 〱〰〮 キャッシュ

ページ・キャッシュ

ページ ・キャッシ ュはサーバ ・サイドで ページ全体のコン テントを
キャッシュするものです。 後で再び同じページがリクエストされた場
合に、その内容を一から生成するのではなく、キャッシュから提供します。
ページ・キャッシュは べどどぜてどぬぴづひびぜぐちでづぃちっとづ という アクション・フィルタ によってサポートされています。 これは、コントローラ・クラスで以下のように使用することができます：
public function behaviors(){
return [['class' => 'yii\filters\PageCache','only' => ['index'],'duration' => 60,'variations' => [\Yii::$app->language,],'dependency' => ['class' => 'yii\caching\DbDependency','sql' => 'SELECT COUNT(*) FROM post',
],
],
];
}

上記のコードは、ページ・キャッシュが index アクションのみで使用されることを示しています。 ページのコンテントは最大 〶〰 秒間キャッシュされ、現在のアプリケーションの言語によるバリエーションを持ち、 投稿の総数に変化があった場合キャッシュされたページが無効になります。
御覧のように、ページ・キャッシュは フラグメント・キャッシュ ととてもよく似ています。 それらは両方とも duration、dependencies、variations、そして enabled などのオプションをサポートしています。 主な違いとしては、ページ・キャッシュは アクション・フィルタ として、フラグメン
ト・キャッシュは ウィジェット として実装されているということです。
フラグメント・キャッシュ も、ダイナミック・コンテント も、 ペー
ジ・キャッシュと併用することができます。

10.5

HTTP キャッシュ

これまでのセクションで説明したサーバ・サイドのキャッシュに加えて、ウェブ・アプリケーションは、 同じページ・コンテントを生成し送信する時間を節約するために、クライアント・サイドでもキャッシュを利用することができます。

〱〰〮〵〮 えごごぐ キャッシュ〵〰〵クライアント・サイドのキャッシュを使用するには、レンダリング結
果をキャッシュできるように、 コントローラ・アクションのフィルタとして べどどぜてどぬぴづひびぜえぴぴばぃちっとづ を設定します。 べどどぜてどぬぴづひびぜえぴぴばぃちっとづ は
GET と HEAD リクエストに対してのみ動作し、それらのリクエストに対する 〳 種類のキャッシュ関連の えごごぐ ヘッダを扱うことができます〺• がちびぴ〭きはつどてどづつ• ぅぴちで• ぃちっとづ〭ぃはのぴひはぬ

10.5.1

ヘッダ

Last-Modified ヘッダは、クライアントがキャッシュした時からページが変更されたかどうかを示すために、タイムスタンプを使用しています。
Last-Modified ヘッダの送信を有効にするには べどどぜてどぬぴづひびぜえぴぴばぃちっとづ〺〺〤ぬちびぴきはつどてどづつ プロパティを構成します。 このプロパティは、ページの更新時刻に関する さぎぉじ タイムスタンプを返す ぐえぐ のコーラブルでなければなりません。 この ぐえぐ コーラブルのシグニチャは以下のとおりです。
/*** @param Action $action 現在扱っているアクション・オブジェクト* @param array $params "params" プロパティの値* @return int ページの更新時刻を表す UNIX タイムスタンプ*/
function ($action, $params)

以下は Last-Modified ヘッダを使用する例です〺
public function behaviors(){
return [['class' => 'yii\filters\HttpCache','only' => ['index'],'lastModified' => function ($action, $params) {$q = new \yii\db\Query();
return $q->from('post')->max('updated_at');
},
],
];
}

上記のコードは index アクションでのみ えごごぐ キャッシュを有効にすべきことを記述しています。 Last-Modified は、投稿の最終更新時刻に基づいて生成される必要があります。 ブラウザが初めて index ページにアクセスしたときは、ページはサーバ上で生成されブラウザに送信されます。 もしブラウザが再度同じページにアクセスし、その期間中に投稿に変更がない場合は、サーバはページを再生成せず、 ブラウザはクラ〵〰〶ぃえぁぐごぅげ 〱〰〮 キャッシュ

イアント・サイドにキャッシュしたものを使用します。 その結果、サーバ・サイドのレンダリング処理とページ・コンテントの送信は両方ともスキップされます。

10.5.2ヘッダ【ぅのぴどぴべ ごちで】 〨略して ETag〩 ヘッダはページ・コンテントを表すためのハッシュです。 ページが変更された場合ハッシュも同様に変更されます。
サーバ・サイドで生成されたハッシュとクライアント・サイドで保持しているハッシュを比較することによって、ページが変更されたかどうか、そして再送信するべきかどうかを決定します。
ETag ヘッダの送信を有効にするには べどどぜてどぬぴづひびぜえぴぴばぃちっとづ〺〺〤づぴちでこづづつ
プロパティを設定します。 プロパティは ぅごちで のハッシュを生成するためのシードを返す ぐえぐ のコーラブルで、 以下のようなシグネチャを持たなければなりません。
/*** @param Action $action 現在扱っているアクション・オブジェクト* @param array $params "params" プロパティの値* @return string ETag のハッシュを生成するためのシードとして使用する文字列*/
function ($action, $params)

以下は ETag ヘッダを使用している例です〺
public function behaviors(){
return [['class' => 'yii\filters\HttpCache','only' => ['view'],'etagSeed' => function ($action, $params) {$post = $this->findModel(\Yii::$app->request->get('id'));return serialize([$post->title, $post->content]);
},
],
];
}

上記のコードは view アクションでのみ えごごぐ キャッシュを有効にすべきことを記述しています。 Etag えごごぐ ヘッダは、リクエストされた投稿のタイトルとコンテントに基づいて生成されなければなりません。 ブラ
ウザが初めて view ページにアクセスしたときは、ページがサーバ上で生成されブラウザに送信されます。 ブラウザが再度同じページにアクセスし、投稿のタイトルやコンテントに変更がない場合には、 サーバはページを再生成せず、ブラウザはクライアント・サイドにキャッシュしたものを使用します。 その結果、サーバ・サイドのレンダリング処理とペー
ジ・コンテント送信は両方ともスキップされます。

〱〰〮〵〮 えごごぐ キャッシュ〵〰〷ぅごちで は Last-Modified ヘ ッ ダ よ り も 複 雑 か つ〯ま た は よ り 正 確 な
キャッシング方式を可能にします。 例えば、サイトが別のテーマに切り替わった場合には ぅごちで を無効化する、といったことができます。
ぅごちで はリクエスト毎に再評価する必要があるため、負荷の高い生成方法を使うと HttpCache の本来の目的を損なって不必要なオーバーヘッドが生じる場合があります。 ページのコンテントが変更されたときにキャッシュを無効化するための式は単純なものを指定するようにして下さい。
補足〺 げうぃ 〷〲〳〲11 に準拠して Etag と Last-Modified ヘッダの両方を設定した場合、 HttpCache はその両方とも送信します。 また、もし If-None-Match ヘッダと If-Modified-Since ヘッダの両方を送信した場合は前者のみが尊重されます。

10.5.3

ヘッダ

Cache-Control ヘッダはページのための一般的なキャッシュ・ポリシーを指定します。 べどどぜてどぬぴづひびぜえぴぴばぃちっとづ〺〺〤っちっとづぃはのぴひはぬえづちつづひ プロパティにヘッダの値を設定することで、それを送ることができます。 デフォル
トでは、以下のヘッダが送信されます〺
Cache-Control: public, max-age=3600

10.5.4

セッション・キャッシュ・リミッタ

ページでセッションを使用している場合、ぐえぐ はいくつかのキャッシ ュ 関 連 の えごごぐ ヘ ッ ダ 〨ぐえぐ の ぉぎぉ 設 定 フ ァ イ ル 内 で 指 定 さ れている びづびびどはの〮っちっとづたぬどねどぴづひ など〩 を自動的に送信します。 これらのヘッダが HttpCache が実現しようとしているキャッシュ機能を妨害したり無効にしたりすることがあります。 この問題を防止するために 、HttpCache は こ れ ら の ヘ ッ ダ の 送 信 を デ フ ォ ル ト で 自 動 的 に 無 効
化 し ま す 。 こ の 動 作 を 変 更 し た い 場 合 は べどどぜてどぬぴづひびぜえぴぴばぃちっとづ〺〺〤びづびびどはのぃちっとづがどねどぴづひ プロパティを設定します。 このプロパティには
public、private、private_no_expire、そして nocache などの文字列の値を使用することができます。 これらの値についての説明は びづびびどはのたっちっとづたぬどねどぴづひ〨〩12を参照してください。

10.5.5

SEO への影響

検索エンジンのボットはキャッシュ・ヘッダを尊重する傾向があります。 クローラの中には、一定期間内に処理するドメインごとのページ数に制限を持っているものもあるため、 キャッシュ・ヘッダを導入して、処理の必要があるページ数を減らしてやると、サイトのインデックスの作成を促進できるかも知れません。
1112

https://datatracker.ietf.org/doc/html/rfc7232#section-2.4
https://www.php.net/manual/ja/function.session-cache-limiter.php〵〰〸ぃえぁぐごぅげ 〱〰〮 キャッシュ

Chapter 11

RESTful ウェブ・サービス
11.1

クイック・スタート

すどど は、げぅこごてふぬ ウェブサービス ぁぐぉ を実装する仕事を簡単にするために、一揃いのツールを提供しています。 具体的に言えば、げぅこごてふぬ ぁぐぉに関する次の機能をサポートしています。
• アクティブ・レコード のための共通 ぁぐぉ をサポートした迅速なプ
ロトタイプ作成• レスポンス形式のネゴシエーション 〨デフォルトで おこくぎ と じきがをサポート〩• 出力フィールドの選択をサポートした、カスタマイズ可能なオブジェクトのシリアライゼーション• コレクション・データと検証エラーの適切な書式設定• コレクションのページネーション、フィルタリングおよびソーティ
ング• えぁごぅくぁこ1 のサポート• えごごぐ 動詞を適切にチェックする効率的なルーティング• OPTIONS および HEAD 動詞のサポートを内蔵• 認証と権限付与• データ・キャッシュと えごごぐ キャッシュ• レート制限
以下においては、例を使って、どのようにして最小限のコーディング労力で一組の げぅこごてふぬ ぁぐぉ を構築することが出来るかを説明します。
ユーザのデータを げぅこごてふぬ ぁぐぉ によって公開したいと仮定しましょう。 ユーザのデータは user という いあ テーブルに保存されており、それにアクセスするための アクティブ・レコード クラス app\models\User が既に作成済みであるとします。
1https://en.wikipedia.org/wiki/HATEOAS

〵〰〹

〵〱〰

ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス

11.1.1

コントローラを作成する

最初に、コントローラ・クラス app\controllers\UserController を次のようにして作成します。
namespace app\controllers;
use yii\rest\ActiveController;class UserController extends ActiveController{
public $modelClass = 'app\models\User';}このコントローラ・クラスは、よく使用される一揃いの げぅこごてふぬ アクションを実装した べどどぜひづびぴぜぁっぴどぶづぃはのぴひはぬぬづひ を拡張するものです。
ねはつづぬぃぬちびび として app\models\User が指定されているため、 コントローラ
がどのモデルを使用してデータの取得と操作が出来るかがわかります。

11.1.2

URL 規則を構成する

次に、アプリケーションの構成情報において、urlManager コンポーネントの構成情報を修正します。
'urlManager' => ['enablePrettyUrl' => true,'enableStrictParsing' => true,'showScriptName' => false,'rules' => [['class' => 'yii\rest\UrlRule', 'controller' => 'user'],],]

上記の構成情報は、主として、user コントローラの さげが 規則を追加して、ユーザのデータが綺麗な さげが と意味のある えごごぐ 動詞によってア
クセスおよび操作できるようにするものです。
情報〺 すどど はコントローラの名前を自動的に複数形にしてエンド・ボイントとして使用します 〨下の「試してみる」〨〣ぴひべどので〭
どぴ〭はふぴ〩 を参照してください〩。 この振る舞いは べどどぜひづびぴぜさひぬげふぬづ〺〺〤ばぬふひちぬどぺづ プロパティを使って構成することが可能です。

11.1.3

JSON の入力を可能にするぁぐぉ が おこくぎ 形式で入力データを受け取ることが出来るように、request
アプリケーション・コンポーネント の ばちひびづひび プロパティを構成して、おこくぎ 入力のために べどどぜぷづぢぜおびはのぐちひびづひ を使うようにします。

〱〱〮〱〮 クイック・スタート〵〱〱'request' => ['parsers' => ['application/json' => 'yii\web\JsonParser',]]情報〺 上記の構成はオプションです。 上記のように構成しない場合は、ぁぐぉ は application/x-www-form-urlencoded と multipart/form-dataだけを入力形式として認識します。

11.1.4

試してみる

上記で示した最小限の労力によって、ユーザのデータにアクセスするげぅこごてふぬ ぁぐぉ を作成する仕事は既に完成しています。 作成した ぁぐぉ は次のものを含みます。
• GET /users〺 全てのユーザをページごとに一覧する• HEAD /users〺 ユーザ一覧の概要を示す• POST /users〺 新しいユーザを作成する• GET /users/123〺 ユーザ 〱〲〳 の詳細を返す• HEAD /users/123〺 ユーザ 〱〲〳 の概要を示す• PATCH /users/123 と PUT /users/123〺 ユーザ 〱〲〳 を更新する• DELETE /users/123〺 ユーザ 〱〲〳 を削除する• OPTIONS /users〺 エンド・ボイント /users に関してサポートされている動詞を示す• OPTIONS /users/123〺 エンド・ボイント /users/123 に関してサポートされている動詞を示す
作成した ぁぐぉ は、次のように、curl コマンドでアクセスすることが出来ます。
$ curl -i -H "Accept:application/json" "http://localhost/users"
HTTP/1.1 200 OK...
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,<http://localhost/users?page=2>; rel=next,<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[

{
},
{

"id": 1,
...

〵〱〲

]

ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス},...

"id": 2,...

受入れ可能なコンテント・タイプを application/xml に変更してみてくだ
さい。 すると、結果が じきが 形式で返されます。
$ curl -i -H "Accept:application/xml" "http://localhost/users"
HTTP/1.1 200 OK...
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,<http://localhost/users?page=2>; rel=next,<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/xml<?xml version="1.0" encoding="UTF-8"?><response><item><id>1</id>...
</item><item><id>2</id>...
</item>...
</response>

次のコマンドは、おこくぎ 形式でユーザのデータを持つ ぐくこご リクエストを送信して、新しいユーザを作成します。
$ curl -i -H "Accept:application/json" -H "Content-Type:application/json" \-XPOST "http://localhost/users" \-d '{"username": "example", "email": "user@example.com"}'
HTTP/1.1 201 Created...
Location: http://localhost/users/1
Content-Length: 99
Content-Type: application/json; charset=UTF-8{"id":1,"username":"example","email":"user@example.com","created_at":1414674789,"updated_at":1414

ヒント〺 さげが http://localhost/users を入力すれば、ウェブ・ブ
ラウザ経由で ぁぐぉ にアクセスすることも出来ます。 ただし、〱〱〮〱〮 クイック・スタート〵〱〳

特殊なリクエスト・ヘッダを送信するためには、何らかのブ
ラウザプラグインが必要になるでしょう。
ご覧のように、レスポンス・ヘッダの中には、総ユーザ数やページ数な
どの情報が書かれています。 また、データの他のページへナビゲートすることを可能にするリンクもあります。 例えば、http://localhost/users?page=2にアクセスすれば、ユーザのデータの次のページを取得することが出来ます。
fields と expand パラメータを使えば、どのフィールドが結果に含まれるべきかを指定することも出来ます。 例えば、さげが http://localhost/users?fields=id,email
は、id と email のフィールドだけを返します。
情報〺 気がついたかも知れませんが、http://localhost/users の結果は、いくつかの公開すべきでないフィールド、例えば
password_hash や auth_key を含んでいます。 当然ながら、これらが ぁぐぉ の結果に出現することは避けたいでしょう。 リソー
ス のセクションで説明されているように、これらのフィールドを除外することは出来ますし、また、除外しなければなりません。
さらに、http://localhost/users?sort=email や http://localhost/users?sort=-emailのように、コレクションをソートすることも出来ます。 http://localhost/users?filter[id]=10や http://localhost/users?filter[email][like]=gmail.com のように、 コレク
ションをフィルタリングすることも、データ・フィルターを使って実装することが出来ます。 詳細は、リソース のセクションを参照して下さい。

11.1.5

まとめ

すどど の げぅこごてふぬ ぁぐぉ フレームワークを使う場合は、ぁぐぉ エンド・ボイン
トをコントローラ・アクションの形式で実装します。 そして、コント
ローラを使って、単一タイプのリソースに対するエンド・ボイントを実装するアクションを編成します。
リソースは べどどぜぢちびづぜきはつづぬ クラスを拡張するデータ・モデルとして表現されます。 データベース 〨リレーショナルまたは ぎはこけが〩 を扱っている場合は、ぁっぴどぶづげづっはひつ を使ってリソースを表現することが推奨されます。
べどどぜひづびぴぜさひぬげふぬづ を使って ぁぐぉ エンド・ボイントへのルーティング
を簡単にすることが出来ます。
これは要求されてはいませんが、げぅこごてふぬ ぁぐぉ は、保守を容易にするために、 ウェブのフロントエンドやバックエンドとは別の独立したアプ
リケーションとして開発することが推奨されます。

〵〱〴

11.2

ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス

リソース

げぅこごてふぬ ぁぐぉ は、つまるところ、リソース にアクセスし、それを操作するものです。 きざぃ の枠組の中では、リソースは モデル として見ることが出来ます。
リソースをどのように表現すべきかについて制約がある訳ではありませんが、 すどど においては、通常は、次のような理由によって、リソース
を べどどぜぢちびづぜきはつづぬ またはその子クラス 〨例えば べどどぜつぢぜぁっぴどぶづげづっはひつ〩のオブジェクトとして表現することになります。
• べどどぜぢちびづぜきはつづぬ は べどどぜぢちびづぜぁひひちべちぢぬづ インタフェイスを実装しています。 これによって、リソースのデータを げぅこごてふぬ ぁぐぉ を通じて公開する仕方をカスタマイズすることが出来ます。
• べどどぜぢちびづぜきはつづぬ は 入力値の検証 をサポートしています。 これは、げぅこごてふぬ ぁぐぉ がデータ入力をサポートする必要がある場合に役に立ちます。
• べどどぜつぢぜぁっぴどぶづげづっはひつ は いあ データのアクセスと操作に対する強力なサポートを提供しています。 リソース・データがデータベースに保存されているときは、アクティブ・レコードが最適の選択です。
このセクションでは、主として、べどどぜぢちびづぜきはつづぬ クラス 〨またはその子クラス〩 から拡張したリソース・クラスにおいて、 げぅこごてふぬ ぁぐぉ を通じて返すことが出来るデータを指定する方法を説明します。 リソース・ク
ラスが べどどぜぢちびづぜきはつづぬ から拡張したものでない場合は、全てのパブリッ
クなメンバ変数が返されます。

11.2.1

フィールドげぅこごてふぬ ぁぐぉ のレスポンスにリソースを含めるとき、リソースは文字列にシリアライズされる必要があります。 すどど はこのプロセスを二つのス
テップに分けます。 最初に、リソースは べどどぜひづびぴぜこづひどちぬどぺづひ によって配列に変換されます。 次に、その配列が レスポンス・フォーマッタ によって、リクエストされた形式 〨例えば おこくぎ や じきが〩 の文字列にシリ
アライズされます。 リソース・クラスを開発するときに主として力を注ぐべきなのは、最初のステップです。
てどづぬつび〨〩 および〯または づへぴひちうどづぬつび〨〩 をオーバーライドすること
によって、 リソースのどういうデータ 〨フィールド と呼ばれます〩 を配列表現に入れることが出来るかを指定することが出来ます。 この二つのメソッドの違いは、前者が配列表現に含まれるべきフィールドのデフォ
ルトのセットを指定するのに対して、 後者はエンド・ユーザが expand
クエリ・パラメータで要求したときに配列に含めることが出来る追加のフィールドを指定する、 という点にあります。例えば、// fields() で宣言されている全てのフィールドを返す。
http://localhost/users〱〱〮〲〮 リソース〵〱〵// "id" と "email" のフィールドだけを返す (ただし、fields() で宣言されていれば) 。
http://localhost/users?fields=id,email// fields() の全てのフィールドと "profile" のフィールドを返す (ただし、"profile" が extraFields() で宣言されていれば)。
http://localhost/users?expand=profile// fields() の全てのフィールドと post の "author" フィールドを返す// (ただし、"author" が post モデルの extraFields() にあれば）。
http://localhost/comments?expand=post.author// "id" と"email" (ただし、fileds() で宣言されていれば) と// "profile" (ただし、extraFields() で宣言されていれば) を返す。
http://localhost/users?fields=id,email&expand=profile〜づぬつび〨〩だ をオーバーライドする
デフォルトでは、べどどぜぢちびづぜきはつづぬ〺〺てどづぬつび〨〩 は、モデルの全ての属性をフィールドとして返し、 べどどぜつぢぜぁっぴどぶづげづっはひつ〺〺てどづぬつび〨〩 は、いあ から投入された属性だけを返します。
fields() をオーバーライドして、フィールドを追加、削除、名前変更、または再定義することが出来ます。 fields() の返り値は配列でなけ
ればなりません。 配列のキーはフィールド名であり、配列の値は対応す
るフィールドの定義です。 フィールドの定義は、プロパティ〯属性の名前
か、あるいは、対応するフィールドの値を返す無名関数とすることが出来ます。 フィールド名がそれを定義する属性名と同一であるという特殊な場合においては、配列のキーを省略することが出来ます。例えば、// 明示的に全てのフィールドをリストする方法。(API の後方互換性を保つために) DB
テーブルやモデル属性の// 変更がフィールドの変更を引き起こさないことを保証したい場合に適している。
public function fields(){
return [// フィールド名が属性名と同じ'id',// フィールド名は "email"、対応する属性名は "email_address"'email' => 'email_address',// フィールド名は "name"、その値は PHP コールバックで定義'name' => function ($model) {return $model->first_name . ' ' . $model->last_name;},];}// いくつかのフィールドを除去する方法。親の実装を継承しつつ、// 公開すべきでないフィールドを除外したいときに適している。
public function fields(){$fields = parent::fields();〵〱〶ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス// 公開すべきでない情報を含むフィールドを削除する
unset($fields['auth_key'], $fields['password_hash'],$fields['password_reset_token']);}return $fields;

警告〺 デフォルトではモデルの全ての属性がエクスポートされる配列に含まれるため、データを精査して、 公開すべきでない情報が含まれていないことを確認すべきです。そういう情報がある場合は、 fields() をオーバーライドして、除去すべきです。上記の例では、auth_key、password_hash および
password_reset_token を選んで除去しています。
をオーバーライドする
デフォルトでは、べどどぜぢちびづぜきはつづぬ〺〺づへぴひちうどづぬつび〨〩 は空の配列を返し、べどど
ぜつぢぜぁっぴどぶづげづっはひつ〺〺づへぴひちうどづぬつび〨〩 は いあ から取得されたリレーションの名前を返します。
extraFields() によって返されるデータの形式は fields() のそれと同じです。 通常、extraFields() は、主として、値がオブジェクトであるフィールドを指定するのに使用されます。 例えば、次のようなフィールドの宣言があるとしましょう。
public function fields(){
return ['id', 'email'];}public function extraFields(){
return ['profile'];}http://localhost/users?fields=id,email&expand=profile というリクエストは、

次のような おこくぎ データを返すことが出来ます。
[

]

{

},
...

"id": 100,
"email": "100@example.com","profile": {"id": 100,"age": 30,}

〱〱〮〲〮 リソース

11.2.2〵〱〷

リンク

えぁごぅくぁこ2 は、えべばづひねづつどち ちび ぴとづ ぅのでどのづ はて ぁばばぬどっちぴどはの こぴちぴづ 〨アプリ
ケーション状態のエンジンとしてのハイパーメディア〩 の略称です。
えぁごぅくぁこ は、げぅこごてふぬ ぁぐぉ は自分が返すリソースについて、どのようなアクションがサポートされているかをクライアントが発見できるような情報を返すべきである、という概念です。 えぁごぅくぁこ のキーポイント
は、リソース・データが ぁぐぉ によって提供されるときには、 関連する情報を一群のハイパーリンクによって返すべきである、ということです。
あなたのリソース・クラスは、べどどぜぷづぢぜがどのにちぢぬづ インタフェイスを実装することによって、えぁごぅくぁこ をサポートすることが出来ます。 このインタフェイスは、リンク のリストを返すべき でづぴがどのにび〨〩 メソッド
一つだけを含みます。 典型的には、少なくとも、リソース・オブジェ
クトそのものへの さげが を表現する self リンクを返さなければなりません。例えば、
use yii\base\Model;
use yii\web\Link; // JSON ハイパーメディア API 言語に定義されているリンク・オ
ブジェクトを表す
use yii\web\Linkable;
use yii\helpers\Url;
class UserResource extends Model implements Linkable{public $id;
public $email;//...
public function fields(){
return ['id', 'email'];}public function extraFields(){
return ['profile'];}public function getLinks(){
return [Link::REL_SELF => Url::to(['user/view', 'id' => $this->id],true),'edit' => Url::to(['user/view', 'id' => $this->id], true),'profile' => Url::to(['user/profile/view', 'id' => $this->id],true),'index' => Url::to(['users'], true),];2

https://en.wikipedia.org/wiki/HATEOAS

〵〱〸

}

ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス}

UserResource オブジェクトがレスポンスで返されるとき、レスポンスは
そのユーザに関連するリンクを表現する _links 要素を含むことになります。 例えば、{}"id": 100,
"email": "user@example.com",// ...
"_links" => {"self": {"href": "https://example.com/users/100"},"edit": {"href": "https://example.com/users/100"},"profile": {"href": "https://example.com/users/profile/100"},"index": {"href": "https://example.com/users"}}

11.2.3

コレクション

リソース・オブジェクトは コレクション としてグループ化することが出来ます。 各コレクションは、同じ型のリソースのリストを含みます。
コレクションは配列として表現することも可能ですが、通常は、データ・プロバイダ として表現する方がより望ましい方法です。 これは、
データ・プロバイダがリソースの並べ替えとページネーションをサポートしているからです。 並べ替えとページネーションは、コレクションを返す げぅこごてふぬ ぁぐぉ にとっては、普通に必要とされる機能です。 例えば、
次のアクションは投稿のリソースについてデータ・プロバイダを返すものです。
namespace app\controllers;
use yii\rest\Controller;
use yii\data\ActiveDataProvider;use app\models\Post;
class PostController extends Controller{
public function actionIndex(){
return new ActiveDataProvider(['query' => Post::find(),〱〱〮〳〮 コントローラ

}

}

〵〱〹

]);

データ・プロバイダが げぅこごてふぬ ぁぐぉ のレスポンスで送信される場合
は、べどどぜひづびぴぜこづひどちぬどぺづひ が現在のページのリソースを取り出して、リ
ソース・オブジェクトの配列としてシリアライズします。 それだけでな
く、べどどぜひづびぴぜこづひどちぬどぺづひ は次の えごごぐ ヘッダを使ってページネーショ
ン情報もレスポンスに含めます。
• X-Pagination-Total-Count〺 リソースの総数• X-Pagination-Page-Count〺 ページ数
• X-Pagination-Current-Page〺 現在のページ 〨〱 から始まる〩• X-Pagination-Per-Page〺 各ページのリソース数• Link〺 クライアントがリソースをページごとにたどることが出来るようにするための一群のナビゲーションリンク
げぅこご ぁぐぉ におけるコレクションはデータ・プロバイダであるため、
データ・プロバイダの全ての機能、すなわち、ページネーションやソー
ティングを共有しています。
その一例を クイック・スタート のセクションで見ることが出来ます。
コレクションをフィルタリングするバージョン 〲〮〰〮〱〳 以降、すどど はコレクションをフィルタリングする便利な機能を提供しています。 その一例を クイック・スタート のガイドに見ることが出来ます。 エンド・ボイントをあなた自身が実装しようとしている場合、フィルタリングは データ・プロバイダのガイドの せデータ・フィ
ルタを使ってデータ・プロバイダをフィルタリングするそ〨はふぴばふぴ〭つちぴち〭
ばひはぶどつづひび〮ねつ〣〜ぬぴづひどので〭つちぴち〭ばひはぶどつづひび〭ふびどので〭つちぴち〭〜ぬぴづひび のセクションで述べられている方法で行うことが出来ます。

11.3

コントローラリソース・クラスを作成して、リソース・データをどのようにフォー
マットすべきかを指定したら、 次は、げぅこごてふぬ ぁぐぉ を通じてエンド・
ユーザにリソースを公開するコントローラ・アクションを作成します。
すどど は、げぅこごてふぬ アクションを作成する仕事を簡単にするための二つの基底コントローラ・クラスを提供しています。 すなわち、べどどぜひづびぴ
ぜぃはのぴひはぬぬづひ と べどどぜひづびぴぜぁっぴどぶづぃはのぴひはぬぬづひ です。 二つのコントローラの違いは、後者は アクティブ・レコード として表現されるリソースの扱いに特化した一連のアクションをデフォルトで提供する、という点にあります。 従って、あなたが アクティブ・レコード を使っていて、提供される組み込みのアクションに満足できるのであれば、 コントローラ・
クラスを べどどぜひづびぴぜぁっぴどぶづぃはのぴひはぬぬづひ から拡張することを検討すると良〵〲〰

ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス

いでしょう。 そうすれば、最小限のコードで強力な げぅこごてふぬ ぁぐぉ を作成することが出来ます。
べどどぜひづびぴぜぃはのぴひはぬぬづひ と べどどぜひづびぴぜぁっぴどぶづぃはのぴひはぬぬづひ は、ともに、
下記の機能を提供します。 これらのいくつかについては、後続のセクションで詳細に説明します。
• えごごぐ メソッドのバリデーション• コンテント・ネゴシエーションとデータの書式設定• 認証• レート制限
べどどぜひづびぴぜぁっぴどぶづぃはのぴひはぬぬづひ は次の機能を追加で提供します。
• 普通は必要とされる一連のアクション〺 index、view、create、update、delete、options• リクエストされたアクションとリソースに対するユーザへの権限付
与11.3.1

コントローラ・クラスを作成する

新しいコントローラ・クラスを作成する場合、コントローラ・クラスの命名規約は、 リソースの型の名前を単数形で使う、というものです。 例
えば、ユーザの情報を提供するコントローラは UserController と名付けることが出来ます。
新しいアクションを作成する仕方はウェブ・アプリケーションの場
合とほぼ同じです。 唯一の違いは、render() メソッドを呼んでビューを使って結果を表示する代りに、げぅこごてふぬ アクションの場合はデータを直接に返す、という点です。 シリアライザ と レスポンス・オブジェクト
が、 元のデータからリクエストされた形式への変換を処理します。 例えば、public function actionView($id){
return User::findOne($id);}

11.3.2

フィルタ

べどどぜひづびぴぜぃはのぴひはぬぬづひ によって提供される げぅこごてふぬ ぁぐぉ 機能のほとんど
は フィルタ の形で実装されています。 具体的に言うと、次のフィルタがリストされた順に従って実行されます。
• っはのぴづのぴぎづではぴどちぴはひ〺 コンテント・ネゴシエーションをサポート。
レスポンス形式の設定 のセクションで説明します。
• ぶづひぢうどぬぴづひ〺 えごごぐ メソッドのバリデーションをサポート。
• ちふぴとづのぴどっちぴはひ〺 ユーザ認証をサポート。 認証 のセクションで説明します。
• ひちぴづがどねどぴづひ〺 レート制限をサポート。 レート制限 のセクションで説明します。

〱〱〮〳〮 コントローラ〵〲〱

これらの名前付きのフィルタは、ぢづとちぶどはひび〨〩 メソッドで宣言されます。 このメソッドをオーバーライドして、個々のフィルタを構成した
り、どれかを無効にしたり、あなた自身のフィルタを追加したりすることが出来ます。 例えば、えごごぐ 基本認証だけを使いたい場合は、次のよ
うなコードを書くことが出来ます。
use yii\filters\auth\HttpBasicAuth;public function behaviors(){$behaviors = parent::behaviors();$behaviors['authenticator'] = ['class' => HttpBasicAuth::class,];return $behaviors;}

ぃくげこ
コントローラに ぃくげこ 〨クロス・オリジン・リソース共有〩 フィルタを追加するのは、上記の他のフィルタを追加するのより、若干複雑になります。 と言うのは、ぃくげこ フィルタは認証メソッドより前に適用されなけ
ればならないため、他のフィルタとは少し異なるアプローチが必要だからです。 また、ブラウザが認証クレデンシャルを送信する必要なく、リクエストが出来るかどうかを前もって安全に判断できるように、 ぃくげこ
プリフライト・リクエスト3 の認証を無効にする必要もあります。 下記のコードは、べどどぜひづびぴぜぁっぴどぶづぃはのぴひはぬぬづひ を拡張した既存のコントロー
ラに べどどぜてどぬぴづひびぜぃはひび フィルタを追加するのに必要なコードを示しています。
use yii\filters\auth\HttpBasicAuth;public function behaviors(){$behaviors = parent::behaviors();// 認証フィルタを削除する$auth = $behaviors['authenticator'];unset($behaviors['authenticator']);// CORS フィルタを追加する$behaviors['corsFilter'] = ['class' => \yii\filters\Cors::class,];// 認証フィルタを再度追加する$behaviors['authenticator'] = $auth;// CORS プリフライト・リクエスト (HTTP OPTIONS メソッド) の認証を回避する
3

https://developer.mozilla.org/ja/docs/Web/HTTP/CORS#preflighted_requests

〵〲〲ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス$behaviors['authenticator']['except'] = ['options'];}

return $behaviors;

11.3.3を拡張する

コントローラを べどどぜひづびぴぜぁっぴどぶづぃはのぴひはぬぬづひ から拡張する場合は、このコントローラを通じて提供しようとしているリソース・クラスの名前をねはつづぬぃぬちびび プロパティにセットしなければなりません。 リソース・クラ
スは べどどぜつぢぜぁっぴどぶづげづっはひつ から拡張しなければなりません。
アクションをカスタマイズする
デフォルトでは、べどどぜひづびぴぜぁっぴどぶづぃはのぴひはぬぬづひ は次のアクションを提供します。
• どのつづへ〺 リソースをページごとにリストする。
• ぶどづぷ〺 指定されたリソースの詳細を返す。
• っひづちぴづ〺 新しいリソースを作成する。
• ふばつちぴづ〺 既存のリソースを更新する。
• つづぬづぴづ〺 指定されたりソースを削除する。
• はばぴどはのび〺 サポートされている えごごぐ メソッドを返す。
これらのアクションは全て ちっぴどはのび〨〩 メソッドによって宣言されます。
actions() メソッドをオーバーライドすることによって、これらのアクションを構成したり、そのいくつかを無効化したりすることが出来ます。例えば、
public function actions(){$actions = parent::actions();// "delete" と "create" のアクションを無効にする
unset($actions['delete'], $actions['create']);// データ・プロバイダの準備を "prepareDataProvider()" メソッドでカスタマイ
ズする$actions['index']['prepareDataProvider'] = [$this,'prepareDataProvider'];}

return $actions;public function prepareDataProvider(){// "index" アクションのためにデータ・プロバイダを準備して返す}

どういう構成オプションが利用できるかを学ぶためには、個々のアク
ション・クラスのリファレンスを参照してください。

〱〱〮〴〮 ルーティング〵〲〳

アクセス・チェックを実行するげぅこごてふぬ ぁぐぉ によってリソースを公開するときには、たいてい、 現在のユーザがリクエストしているリソースにアクセスしたり操作したりする
許可を持っているか否かをチェックする必要があります。 これは、べどど
ぜひづびぴぜぁっぴどぶづぃはのぴひはぬぬづひ を使う場合は、っとづっにぁっっづびび〨〩 メソッドを次のようにオーバーライドすることによって出来ます。
/*** 現在のユーザの特権をチェックする。
** 現在のユーザが指定されたデータ・モデルに対して指定されたアクションを実行する特権を* 有するか否かをチェックするためには、このメソッドをオーバーライドしなければなりません。
* ユーザが権限をもたない場合は、[[ForbiddenHttpException]] が投げられなければなりません。
** @param string $action 実行されるアクションの ID。
* @param \yii\base\Model $model アクセスされるモデル。null の場合は、アクセスされる特定のモデルが無いことを意味する。
* @param array $params 追加のパラメータ* @throws ForbiddenHttpException ユーザが権限をもたない場合*/
public function checkAccess($action, $model = null, $params = []){// ユーザが $action と $model に対する権限を持つかどうかをチェック// アクセスを拒否すべきときは ForbiddenHttpException を投げる
if ($action === 'update' || $action === 'delete') {if ($model->author_id !== \Yii::$app->user->id)
throw new \yii\web\ForbiddenHttpException(sprintf('You can only%s articles that you\'ve created.', $action));}}checkAccess() メソッドは べどどぜひづびぴぜぁっぴどぶづぃはのぴひはぬぬづひ のデフォルトのアクションから呼ばれます。 新しいアクションを作成して、それに対してもアクセス・チェックをしたい場合は、新しいアクションの中からこのメソッドを明示的に呼び出さなければなりません。

ヒント〺 ロール・ベース・アクセス制御 〨げあぁぃ〩 コンポーネン
ト を使って checkAccess() を実装することも可能です。

11.4

ルーティングリソースとコントローラのクラスが準備できたら、通常のウェブ・アプ
リケーションと同じように、 http://localhost/index.php?r=user/create というような さげが を使ってリソースにアクセスすることが出来ます。

〵〲〴

ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス

実際には、綺麗な さげが を有効にして えごごぐ 動詞を利用したいというのが普通でしょう。 例えば、POST /users というリクエストが user/create
アクションへのアクセスを意味するようにする訳です。 これは、アプリ
ケーションの構成情報で urlManager アプリケーション・コンポーネントを次のように構成することによって容易に達成することが出来ます。
'urlManager' => ['enablePrettyUrl' => true,'enableStrictParsing' => true,'showScriptName' => false,'rules' => [['class' => 'yii\rest\UrlRule', 'controller' => 'user'],],]

ウェブ・アプリケーションの さげが 管理と比べたときに、上記で目に付く新しいことは、 げぅこごてふぬ ぁぐぉ リクエストのルーティングに べどどぜひづびぴ
ぜさひぬげふぬづ を使用していることです。 この特殊な さげが 規則クラスが、一揃いの子 さげが 規則を作成して、指定されたコントローラのルーティングと さげが 生成をサポートします。 例えば、上記のコードは、おおむね下記の規則と等価です。
[]'PUT,PATCH users/<id>' => 'user/update','DELETE users/<id>' => 'user/delete','GET,HEAD users/<id>' => 'user/view','POST users' => 'user/create','GET,HEAD users' => 'user/index','users/<id>' => 'user/options','users' => 'user/options',

そして、次の ぁぐぉ エンド・ボイントがこの規則によってサポートされます。
• GET /users〺 全てのユーザをページごとにリストする。
• HEAD /users〺 ユーザ一覧の概要を示す。
• POST /users〺 新しいユーザを作成する。
• GET /users/123〺 ユーザ 〱〲〳 の詳細を返す。
• HEAD /users/123〺 ユーザ 〱〲〳 の概要情報を示す。
• PATCH /users/123 と PUT /users/123〺 ユーザ 〱〲〳 を更新する。
• DELETE /users/123〺 ユーザ 〱〲〳 を削除する。
• OPTIONS /users〺 エンド・ボイント /users に関してサポートされる動詞を示す。
• OPTIONS /users/123〺 エンド・ボイント /users/123 に関してサポートされる動詞を示す。
only および except オプションを構成すると、それぞれ、どのアクションをサポートするか、 また、どのアクションを無効にするかを明示的に指定することが出来ます。例えば、

〱〱〮〴〮 ルーティング
[

],

〵〲〵

'class' => 'yii\rest\UrlRule','controller' => 'user','except' => ['delete', 'create', 'update'],

また、patterns あるいは extraPatterns を構成して、既存のパターンを再定義したり、この規則によってサポートされる新しいパターンを追加したりすることも出来ます。 例えば、エンド・ボイント GET /users/search
によって新しいアクション search をサポートするためには、extraPatterns
オプションを次のように構成します。
[]'class' => 'yii\rest\UrlRule','controller' => 'user','extraPatterns' => ['GET search' => 'search',],

エンド・ボイントの さげが ではコントローラ ぉい user が users という複数形で出現していることに気が付いたかもしれません。 これは、べどどぜひづびぴ
ぜさひぬげふぬづ が子 さげが 規則を作るときに、コントローラの ぉい を自動的に複数形にするためです。 この振舞いは べどどぜひづびぴぜさひぬげふぬづ〺〺〤ばぬふひちぬどぺづ を
false に設定することで無効にすることが出来ます。
情報〺 コントローラ ぉい の複数形化は べどどぜとづぬばづひびぜぉのてぬづっぴはひ〺〺ばぬふひちぬどぺづ〨〩 によって行われます。 このメソッドは特殊な複数形の規則を考慮します。例えば、box という単語の複数形は boxs ではなく boxes になります。
自動的な複数形化があなたの要求を満たさない場合は、べどどぜひづびぴぜさひぬげふぬづ〺〺〤っはのぴひはぬぬづひ プロパティを構成して、 エンド・ボイント さげが で使用される名前とコントローラ ぉい の対応を明示的に指定することも可能です。 例えば、次のコードはエンド・ボイント名 u をコントローラ ぉい userに割り当てます。
[]'class' => 'yii\rest\UrlRule','controller' => ['u' => 'user'],

11.4.1

内蔵の規則に対する追加の構成

べどどぜひづびぴぜさひぬげふぬづ の中に含まれるそれぞれの規則に対して適用される追加の構成を指定すると役に立つことがあります。 expand パラメータに対するデフォルトの指定が良い例です。

〵〲〶[

ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス'class' => 'yii\rest\UrlRule','controller' => ['user'],'ruleConfig' => ['class' => 'yii\web\UrlRule','defaults' => ['expand' => 'profile',
]
],

],

11.5

レスポンス形式の設定

げぅこごてふぬ ぁぐぉ のリクエストを処理するとき、アプリケーションは、通常、レスポンス形式の設定に関して次のステップを踏みます。
〱〮 レスポンス形式に影響するさまざまな要因、例えば、メディア・タ
イプ、言語、バージョンなどを決定します。 このプロセスは コン
テント・ネゴシエーション4 としても知られるものです。
〲〮 リソース・オブジェクトを配列に変換します。 リソース のセクションで説明したように、この作業は べどどぜひづびぴぜこづひどちぬどぺづひ によって実行されます。
〳〮 配列をコンテント・ネゴシエーションのステップで決定された形式の文字列に変換します。 この作業は、response アプリケーション・
コンポーネント の てはひねちぴぴづひび プロパティに登録された レスポン
ス・フォーマッタ によって実行されます。

11.5.1

コンテント・ネゴシエーション

すどど は べどどぜてどぬぴづひびぜぃはのぴづのぴぎづではぴどちぴはひ フィルタによってコンテント・
ネゴシエーションをサポートします。 げぅこごてふぬ ぁぐぉ の基底コントロー
ラ・クラス べどどぜひづびぴぜぃはのぴひはぬぬづひ は contentNegotiator という名前でこのフィルタを持っています。 このフィルタは、レスポンス形式のネゴ
シエーションと同時に言語のネゴシエーションも提供します。 例えば、げぅこごてふぬ ぁぐぉ リクエストが下記のヘッダを含んでいるとします。
Accept: application/json; q=1.0, */*; q=0.1

この場合、リクエストは おこくぎ 形式のレスポンスを受け取ることになります。例えば、次のような具合です。
4

https://en.wikipedia.org/wiki/Content_negotiation〱〱〮〵〮 レスポンス形式の設定〵〲〷$ curl -i -H "Accept: application/json; q=1.0, */*; q=0.1""http://localhost/users"
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,<http://localhost/users?page=2>; rel=next,<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[

{
},
{

]

},
...

"id": 1,...
"id": 2,...

舞台裏では、げぅこごてふぬ ぁぐぉ コントローラ・アクションが実行される前に 、べどどぜてどぬぴづひびぜぃはのぴづのぴぎづではぴどちぴはひ フ ィ ル タ が リ ク エ ス ト の Accept
えごごぐ ヘッダをチェックして、レスポンス形式 を 'json' に設定します。 アクションが実行されて、その結果のリソースのオブジェクトまたはコレクションが返されると、べどどぜひづびぴぜこづひどちぬどぺづひ が結果を配列に変換します。 そして最後に、べどどぜぷづぢぜおびはのげづびばはのびづうはひねちぴぴづひ が配列をおこくぎ 文字列に変換して、それをレスポンス・ボディに入れます。
デフォルトでは、げぅこごてふぬ ぁぐぉ は おこくぎ と じきが の両方の形式をサポートします。 新しい形式をサポートするためには、下記のよ
うに、ぁぐぉ コントローラ・クラスの中で contentNegotiator フィルタのてはひねちぴび プロパティを構成しなければなりません。
use yii\web\Response;
public function behaviors(){$behaviors = parent::behaviors();$behaviors['contentNegotiator']['formats']['text/html'] =Response::FORMAT_HTML;return $behaviors;}
formats プロパティのキーはサポートされる きぉきぅ タイプであり、値は〵〲〸

ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス

対応するレスポンス形式名です。 このレスポンス形式名は、べどどぜぷづぢ
ぜげづびばはのびづ〺〺〤てはひねちぴぴづひび の中でサポートされているものでなければなりません。

11.5.2

データのシリアライズ

上記で説明したように、べどどぜひづびぴぜこづひどちぬどぺづひ が、リソースのオブジェ
クトやコレクションを配列に変換する際に、中心的な役割を果たします。 Serializer は、べどどぜぢちびづぜぁひひちべちぢぬづ および べどどぜつちぴちぜいちぴちぐひはぶどつづひぉのぴづひてちっづのインタフェイスを実装したオブジェクトを認識します。 前者は主としてリソース・オブジェクトによって実装され、後者はリソース・コレク
ションによって実装されています。
べどどぜひづびぴぜぃはのぴひはぬぬづひ〺〺〤びづひどちぬどぺづひ プ ロ パ テ ィ に 構 成 情 報 配 列 をセットしてシリアライザを構成することが出来ます。 例えば、場合によっては、クライアントの開発作業を単純化するために、ページネー
ション情報をレスポンス・ボディに直接に含ませたいことがあるでしょう。 そうするためには、べどどぜひづびぴぜこづひどちぬどぺづひ〺〺〤っはぬぬづっぴどはのぅのぶづぬはばづ
プロパティを次のように構成します。
use yii\rest\ActiveController;class UserController extends ActiveController{
public $modelClass = 'app\models\User';public $serializer = ['class' => 'yii\rest\Serializer','collectionEnvelope' => 'items',];}

このようにすると、http://localhost/users というリクエストに対して、次のレスポンスを得ることが出来ます。
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,<http://localhost/users?page=2>; rel=next,<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8{"items": [{〱〱〮〵〮 レスポンス形式の設定

},
{
},
...

}

〵〲〹

"id": 1,...
"id": 2,...

],"_links": {"self": {"href": "http://localhost/users?page=1"},"next": {"href": "http://localhost/users?page=2"},"last": {"href": "http://localhost/users?page=50"}},"_meta": {"totalCount": 1000,"pageCount": 50,"currentPage": 1,"perPage": 20}

おこくぎ 出力を制御する
おこくぎ 形式のレスポンスを生成する おびはのげづびばはのびづうはひねちぴぴづひ クラスは
おこくぎ ヘルパ を内部的に使用します。 このフォーマッタはさまざまなオ
プションによって構成することが可能です。 例えば、〤ばひづぴぴべぐひどのぴ オプ
ションは、より読みやすいレスポンスのためのもので、開発時に有用なオプションです。 また、〤づのっはつづくばぴどはのび によって おこくぎ エンコーディ
ングの出力を制御することが出来ます。
フォーマッタは、以下のように、アプリケーションの 構成情報 の中で、response アプリケーション・コンポーネントの てはひねちぴぴづひび プロパ
ティの中で構成することが出来ます。
'response' => [// ...
'formatters' => [\yii\web\Response::FORMAT_JSON => ['class' => 'yii\web\JsonResponseFormatter','prettyPrint' => YII_DEBUG, // デバッグ・モードでは "きれい" な出
力を使用'encodeOptions' => JSON_UNESCAPED_SLASHES |JSON_UNESCAPED_UNICODE,// ...
],

〵〳〰

ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス],],

いぁく データベース・レイヤを使ってデータベースからデータを返す場
合は、全てのデータが文字列として表されます。 しかし、特に数値はおこくぎ では数として表現されなければなりませんので、これは必ずしも期
待通りの結果であるとは言えません。 一方、ぁっぴどぶづげづっはひつ レイヤを使ってデータベースからデータを取得する場合は、数値カラムの値は、べどど
ぜつぢぜぁっぴどぶづげづっはひつ〺〺ばはばふぬちぴづげづっはひつ〨〩 においてデータベースからデータが取得される際に、整数に変換されます。

11.6

認証

ウェブ・アプリケーションとは異なり、げぅこごてふぬ ぁぐぉ は通常はステート・レスです。 これは、セッションやクッキーは使用すべきでないことを意味します。 従って、ユーザの認証ステータスをセッションやクッキーで保持することが出来ないため、全てのリクエストに何らかの認証
情報を付加する必要があります。 通常使われるのは、ユーザを認証するための秘密のアクセス・トークンを全てのリクエストとともに送信する方法です。 アクセス・トークンはユーザを一意に特定して認証することが出来るものですので、 ぁぐぉ リクエストは、中間者攻撃 〨ねちの〭どの〭ぴとづ〭
ねどつつぬづ ちぴぴちっに〩 を防止するために、常に えごごぐこ 経由で送信されなけ
ればなりません。
アクセス・トークンを送信するには、いくつかの異なる方法があります。
• えごごぐ あちびどっ 認証5 〺 アクセス・トークンはユーザ名として送信されます。 この方法は、アクセス・トークンを ぁぐぉ コンシューマ側
で安全に保存することが出来る場合、 例えば ぁぐぉ コンシューマがサーバ上で走るプログラムである場合などにのみ使用されるべきです。
• クエリ・パラメータ〺 アクセス・トークンは ぁぐぉ の さげが、例えば、https://example.com/users?access-token=xxxxxxxx でクエリ・パラ
メータとして送信されます。 ほとんどのウェブ・サーバはクエリ・パラメータをサーバのログに記録するため、この手法は、 アクセ
ス・トークンを えごごぐ ヘッダを使って送信することができない
JSONP リクエストに応答するために主として使用されるべきです。
• くぁふぴと 〲6 〺 くぁふぴと〲 プロトコルに従って、 アクセス・トークンはコンシューマによって権限付与サーバから取得され、えごごぐ あづちひづひ
ごはにづのび7 経由で ぁぐぉ サーバに送信されます。
すどど は上記の全ての認証方法をサポートしています。新しい認証方法を作成することも簡単に出来ます。
https://ja.wikipedia.org/wiki/Basic%E8%AA%8D%E8%A8%BC
https://oauth.net/2/
7
https://datatracker.ietf.org/doc/html/rfc6750
56〱〱〮〶〮 認証〵〳〱

あなたの ぁぐぉ に対して認証を有効にするためには、次のステップを実行します。
〱〮 user アプリケーション・コンポーネント を構成します。
• づのちぢぬづこづびびどはの プロパティを false に設定します。
• ぬはでどのさひぬ プロパティを null に設定し、ログインページにリダ
イレクトする代りに えごごぐ 〴〰〳 エラーを表示します。
〲〮 げぅこご コントローラ・クラスにおいて、authenticator ビヘイビアを構成することによって、 どの認証方法を使用するかを指定します。
〳〮 ユーザ・アイデンティティ・クラス において べどどぜぷづぢぜぉつづのぴどぴべぉのぴづひてちっづ〺〺てどのつぉつづのぴどぴべあべぁっっづびびごはにづの〨〩 を実装します。
ステップ 〱 は必須ではありませんが、ステート・レスであるべき げぅこご〭てふぬ ぁぐぉ のために推奨されます。 づのちぢぬづこづびびどはの が false である場合、ユーザの認証ステータスがセッションを使ってリクエストをまたいで存続することはありません。 その代りに、すべてのリクエストに対して認証が実行されます。このことは、ステップ 〲 と 〳 によって達成されます。
ヒント〺 げぅこごてふぬ ぁぐぉ をアプリケーションの形式で開発する
場合は、アプリケーションの構成情報で user アプリケーショ
ン・コンポーネント〨びぴひふっぴふひづ〭ちばばぬどっちぴどはの〭っはねばはのづのぴび〮ねつ〩 づのちぢぬづこづびびどはのプロパティを構成することが出来ます。 げぅこごてふぬ ぁぐぉ をモ
ジュールとして開発する場合は、次のように、モジュールのinit() メソッドに一行を追加することが出来ます。
public function init(){
parent::init();\Yii::$app->user->enableSession = false;}

例えば、えごごぐ あちびどっ 認証を使う場合は、authenticator ビヘイビアを次のように構成することが出来ます。
use yii\filters\auth\HttpBasicAuth;public function behaviors(){$behaviors = parent::behaviors();$behaviors['authenticator'] = ['class' => HttpBasicAuth::class,];return $behaviors;}〵〳〲ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス

上で説明した三つの認証方法を全てサポートしたい場合は、次のようにCompositeAuth を使うことが出来ます。
use yii\filters\auth\CompositeAuth;use yii\filters\auth\HttpBasicAuth;use yii\filters\auth\HttpBearerAuth;use yii\filters\auth\QueryParamAuth;public function behaviors(){$behaviors = parent::behaviors();$behaviors['authenticator'] = ['class' => CompositeAuth::class,'authMethods' => [HttpBasicAuth::class,
HttpBearerAuth::class,
QueryParamAuth::class,],];return $behaviors;}
authMethods の各要素は、認証方法クラスの名前であるか、構成情報配列

でなければなりません。
findIdentityByAccessToken() の実装はアプリケーション固有のものです。 例えば、各ユーザが一つだけアクセス・トークンを持ち得るような単純なシナリオでは、アクセス・トークンをユーザのテーブルのaccess_token カラムに保存することが出来ます。 そうすれば、次のように、findIdentityByAccessToken() メソッドを User クラスにおいて簡単に実装することが出来ます。
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;class User extends ActiveRecord implements IdentityInterface{
public static function findIdentityByAccessToken($token, $type = null){
return static::findOne(['access_token' => $token]);}}

上記のように認証が有効化された後は、全ての ぁぐぉ リクエストに対して、リクエストされたコントローラ beforeAction() の段階でユーザを認証することを試みます。
認証が成功すると、コントローラはその他のチェック 〨レート制限、権限付与など〩 をしてから、アクションを実行します。 認証されたユー
ザのアイデンティティは Yii::$app->user->identity によって取得することが出来ます。

〱〱〮〷〮 レート制限〵〳〳

認証が失敗したときは、えごごぐ ステータス 〴〰〱 およびその他の適切なヘッダ 〨えごごぐ あちびどっ 認証に対する WWW-Authenticate ヘッダなど〩 を持つレ
スポンスが送り返されます。

11.6.1

権限付与

ユーザが認証された後、おそらくは、リクエストされたリソースに対してリクエストされたアクションを実行する許可を 彼または彼女が持っているかどうかをチェックしたいでしょう。 権限付与 と呼ばれるこのプロ
セスについては、権限付与 のセクションで詳細に説明されています。
あなたのコントローラが べどどぜひづびぴぜぁっぴどぶづぃはのぴひはぬぬづひ から拡張したものである場合は、 っとづっにぁっっづびび〨〩 メソッドをオーバーライドして権限付与のチェックを実行することが出来ます。 このメソッドが べどどぜひづびぴ
ぜぁっぴどぶづぃはのぴひはぬぬづひ によって提供されている内蔵のアクションから呼び出されます。

11.7

レート制限

悪用を防止するために、あなたの ぁぐぉ に レート制限 を加えることを検討すべきです。 例えば、各ユーザの ぁぐぉ 使用を 〱〰 分間で最大 〱〰〰 回までの ぁぐぉ 呼び出しに制限したいとしましょう。 ユーザから上記の期間内に多すぎるリクエストを受け取った場合は、ステータス・コード 〴〲〹〨「リクエストが多すぎる」の意味〩 を持つレスポンスを返さなければなりません。
レート制限を可能にするためには、ユーザ・アイデンティティ・クラ
ス で べどどぜてどぬぴづひびぜげちぴづがどねどぴぉのぴづひてちっづ を実装しなければなりません。
このインタフェイスは次の三つのメソッドを実装することを要求します。
• getRateLimit()〺 許可されているリクエストの最大数と期間を返します 〨例えば、[100, 600] は 〶〰〰 秒間に最大 〱〰〰 回の ぁぐぉ 呼び出しが出来ることを意味します〩。
• loadAllowance()〺 許可されているリクエストの残り数と、レート制限
が最後にチェックされたときの対応する さぎぉじ タイムスタンプを返します。
• saveAllowance()〺 許可されているリクエストの残り数と現在の さぎぉじ
タイムスタンプの両方を保存します。
ユーザ・テーブルに二つのカラムを追加して、許容されているリクエ
スト数とタイムスタンプの情報を記録するのが良いでしょう。 それらを定義すれば、loadAllowance() と saveAllowance() は、 認証された現在のユーザに対応する二つのカラムの値を読み書きするものとして実装することが出来ます。 パフォーマンスを向上させるために、これらの情報をキャッシュや ぎはこけが ストレージに保存することを検討しても構いません。
User モデルにおける実装は次のようなものになります。

〵〳〴

ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス

public function getRateLimit($request, $action){
return [$this->rateLimit, 1]; // 1秒間に $rateLimit 回のリクエスト}
public function loadAllowance($request, $action){
return [$this->allowance, $this->allowance_updated_at];}public function saveAllowance($request, $action, $allowance, $timestamp){$this->allowance = $allowance;$this->allowance_updated_at = $timestamp;$this->save();}

アイデンティティのクラスに必要なインタフェイスを実装すると、すどどは べどどぜひづびぴぜぃはのぴひはぬぬづひ のアクション・フィルタとして構成された べどど
ぜてどぬぴづひびぜげちぴづがどねどぴづひ を使って、自動的にレート制限のチェックを行うようになります。 レート制限を超えると、レート・リミッタが べどどぜぷづぢ
ぜごははきちのべげづぱふづびぴびえぴぴばぅへっづばぴどはの を投げます。
レート・リミッタは、げぅこご コントローラ・クラスの中で、 次のようにして構成することが出来ます。
public function behaviors(){$behaviors = parent::behaviors();$behaviors['rateLimiter']['enableRateLimitHeaders'] = false;
return $behaviors;}

レート制限が有効にされると、デフォルトでは、送信される全てのレス
ポンスに、 現在のレート制限の情報を含む次の えごごぐ ヘッダが付加されます。
• X-Rate-Limit-Limit 〭 一定期間内に許可されるリクエストの最大数• X-Rate-Limit-Remaining 〭 現在の期間において残っている許可されているリクエスト数• X-Rate-Limit-Reset 〭 許可されているリクエストの最大数にリセットされるまで待たなければならない秒数
これらのヘッダは、上記のコード例で示されているように、べどどぜてどぬぴづひび
ぜげちぴづがどねどぴづひ〺〺〤づのちぢぬづげちぴづがどねどぴえづちつづひび を false に設定することで無効にすることが出来ます。

11.8

バージョン管理良い ぁぐぉ はバージョン管理 されています。すなわち、一つのバージョンを絶え間なく変更するのではなく、変更と新機能は ぁぐぉ の新しいバー〱〱〮〸〮 バージョン管理〵〳〵

ジョンにおいて実装されます。 クライアント・サイドとサーバ・サイドの両方のコードを完全に制御できるウェブ・アプリケーションとは違って、ぁぐぉ はあなたの制御が及ばないクライアントによって使用されることを想定したものです。このため、ぁぐぉ の後方互換性 〨あぃ〩 は、可能な限り保たれなければなりません。 あぃ を損なうかも知れない変更が必要な
場合は、それを ぁぐぉ の新しいバージョンにおいて導入し、バージョン番
号を上げるべきです。そうすれば、既存のクライアントは、ぁぐぉ の古い
けれども動作するバージョンを使い続けることが出来ますし、新しいま
たはアップグレードされたクライアントは、新しい ぁぐぉ バージョンで新しい機能を使うことが出来ます。
ヒント〺 ぁぐぉ のバージョン番号の設計に関する詳細情報はこづねちのぴどっ ざづひびどはのどので8 を参照してください。
ぁぐぉ のバージョン管理を実装する方法としてよく使われるのは、バー
ジョン番号を ぁぐぉ の さげが に埋め込む方法です。 例えば、https://example.com/v1/users
が ぁぐぉ バージョン 〱 の /users エンド・ボイントを指す、というものです。
ぁぐぉ のバージョン管理のもう一つの方法は、最近流行しているものですが、バージョン番号を えごごぐ リクエスト・ヘッダに付ける方法です。
これは、典型的には、Accept ヘッダによって行われます。
// パラメータによってAccept: application/json; version=v1// ベンダーのコンテント・タイプによってAccept: application/vnd.company.myapp-v1+json

どちらの方法にも長所と短所があり、それぞれのアプローチに対して多くの議論があります。 下記では、この二つの方法をミックスした ぁぐぉバージョン管理の実際的な戦略を紹介します。
• ぁぐぉ 実装の各メジャー・バージョンを独立したモジュールに置き、モジュールの ぉい はメジャー・バージョン番号 〨例えば v1 や v2〩 とします。 当然ながら、ぁぐぉ の さげが はメジャー・バージョン番号を含むことになります。
• 各メジャー・バージョンの中では 〨従って対応するモジュールの中では〩 Accept えごごぐ リクエスト・ヘッダを使ってマイナー・バー
ジョン番号を決定し、 マイナー・バージョンに応じたレスポンスのための条件分岐コードを書きます。
メジャー・バージョンを提供する各モジュールは、それぞれ、指定されたバージョンのためのリソースとコントローラのクラスを含んでいなけ
ればなりません。 コードの責任範囲をより良く分離するために、共通の基底のリソースとコントローラのクラスを保持して、 それをバージョンごとの個別のモジュールでサブ・クラス化することが出来ます。 サブ・クラスの中で、Model::fields() のような具体的なコードを実装します。
あなたのコードを次のように編成することが出来ます。
8https://semver.org/

〵〳〶ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス

api/
common/controllers/
UserController.php
PostController.php
models/User.php
Post.php
modules/v1/
controllers/
UserController.php
PostController.php
models/User.php
Post.php
Module.php
v2/
controllers/
UserController.php
PostController.php
models/User.php
Post.php
Module.php

アプリケーションの構成情報は次のようなものになります。
return ['modules' => ['v1' => ['class' => 'app\modules\v1\Module',],'v2' => ['class' => 'app\modules\v2\Module',],],'components' => ['urlManager' => ['enablePrettyUrl' => true,'enableStrictParsing' => true,'showScriptName' => false,'rules' => [['class' => 'yii\rest\UrlRule', 'controller' => ['v1/user','v1/post']],['class' => 'yii\rest\UrlRule', 'controller' => ['v2/user','v2/post']],
],
],
],
];

上記のコードの結果として、https://example.com/v1/users はバージョン 〱〱〱〮〹〮 エラー処理〵〳〷のユーザ一覧を返し、 https://example.com/v2/users はバージョン 〲 のユー
ザ一覧を返すことになります。
モジュール化のおかげで、異なるメジャー・バージョンのためのコードを綺麗に分離することが出来ます。 しかし、モジュール化しても、共通の基底クラスやその他の共有リソースを通じて、モジュール間でコードを再利用することは引き続いて可能です。
マイナー・バージョン番号を扱うためには、っはのぴづのぴぎづではぴどちぴはひ ビ
ヘイビアによって提供されるコンテント・ネゴシエーションの機能を利用することが出来ます。 contentNegotiator ビヘイビアは、どのコンテン
ト・タイプをサポートするかを決定するときに、 べどどぜぷづぢぜげづびばはのびづ〺〺〤ちっっづばぴぐちひちねび プロパティをセットします。
例えば、リクエストが えごごぐ ヘッダ Accept: application/json; version=v1
を伴って送信された場合、 コンテント・ネゴシエーションの後では、べどど
ぜぷづぢぜげづびばはのびづ〺〺〤ちっっづばぴぐちひちねび に ['version' => 'v1'] という値が含まれています。
acceptParams のバージョン情報に基づいて、アクション、リソース・
クラス、シリアライザなどの個所で条件付きのコードを書いて、 適切な機能を提供することが出来ます。
マイナー・バージョンは、定義上、後方互換性を保つことを要求するものですので、コードの中でバージョンチェックをする個所はそれほど多くないものと期待されます。 そうでない場合は、たいていは、新しい
メジャー・バージョンを作成する必要がある、ということです。

11.9

エラー処理

げぅこごてふぬ ぁぐぉ リクエストを処理していて、ユーザのリクエストにエラーがあったり、何か予期しないことがサーバ上で起ったりしたときには、
単に例外を投げて、ユーザに何かがうまく行かなかったことを知らせることも出来ます。 しかし、エラーの原因 〨例えば、リクエストされたリソースが存在しない、など〩 を特定することが出来るなら、 適切な
えごごぐ ステータス・コード 〨例えば、〴〰〴 ステータス・コードを表わす
べどどぜぷづぢぜぎはぴうはふのつえぴぴばぅへっづばぴどはの〩 と一緒に例外を投げることを検討すべきです。 そうすれば、すどど は対応する えごごぐ ステータスのコードとテキストをレスポンスとともに送信します。 すどど はまた、レスポンス・ボディにも、シリアライズされた表現形式の例外を含めます。例えば、
HTTP/1.1 404 Not Found
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8{"name": "Not Found Exception","message": "The requested resource was not found.",

〵〳〸

}

ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス"code": 0,"status": 404

次のリストは、すどど の げぅこご フレームワークで使われる えごごぐ ステータ
ス・コードの要約です。
• 200〺 くか。すべて期待されたとおりに動作しました。
• 201〺 POST リクエストに対するレスポンスとしてリソースが成功裡に作成されました。 Location ヘッダが、新しく作成されたリソースを指し示す さげが を含んでいます。
• 204〺 リクエストは成功裡に処理されましたが、レスポンスはボディ・コンテントを含んでいません 〨DELTE リクエストなどの場
合〩。
• 304〺 リソースは修正されていません。キャッシュしたバージョンを使うことが可能です。
• 400〺 無効なリクエストです。これはユーザのさまざまな行為によって引き起こされます。 例えば、リクエストのボディに無効な おこくぎ
データを入れたり、無効なアクションパラメータを指定したり、など。
• 401〺 認証が失敗しました。
• 403〺 認証されたユーザは指定された ぁぐぉ エンド・ボイントにアクセ
スすることを許可されていません。
• 404〺 リクエストされたリソースは存在しません。
• 405〺 メソッドが許可されていません。どの えごごぐ メソッドが許可されているか、Allow ヘッダをチェックしてください。
• 415〺 サポートされていないメディア・タイプです。リクエストされたコンテント・タイプまたはバージョン番号が無効です。
• 422〺 データの検証が失敗しました 〨例えば POST リクエストに対するレスポンスで〩。レスポンス・ボディで詳細なエラー・メッセージをチェックしてください。
• 429〺 リクエストの数が多すぎます。レート制限のためにリクエストが拒絶されました。
• 500〺 内部的サーバエラー。これは内部的なプログラムエラーによって生じ得ます。

11.9.1

エラー・レスポンスをカスタマイズする

場合によっては、デフォルトのエラー・レスポンス形式をカスタマイズ
したいことがあるでしょう。 例えば、さまざまな えごごぐ ステータスを使ってさまざまなエラーを示すという方法によるのではなく、次に示す
ように、 えごごぐ ステータスとしては常に 〲〰〰 を使い、実際の えごごぐ ス
テータス・コードはレスポンスの おこくぎ 構造の一部として包み込む、という方式です。
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT〱〱〮〹〮 エラー処理〵〳〹

Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8{}"success": false,"data": {"name": "Not Found Exception","message": "The requested resource was not found.","code": 0,"status": 404}

アプリケーションの構成情報で response コンポーネントの beforeSend イ
ベントに応答することで、この目的を達することが出来ます。
return [// ...
'components' => ['response' => ['class' => 'yii\web\Response','on beforeSend' => function ($event) {$response = $event->sender;
if ($response->data !== null &&Yii::$app->request->get('suppress_response_code')) {$response->data = ['success' => $response->isSuccessful,'data' => $response->data,];$response->statusCode = 200;
}
},
],
],
];

上記のコードは、suppress_response_code が GET のパラメータとして渡された場合に、 レスポンスを 〨成功したものも、失敗したものも〩 上記で説明したように再フォーマットします。

〵〴〰

ぃえぁぐごぅげ 〱〱〮 げぅこごうさが ウェブ・サービス

Chapter 12

開発ツール

〵〴〱

〵〴〲

ぃえぁぐごぅげ 〱〲〮 開発ツール

Chapter 13

テスト
13.1

テスト

テストはソフトウェア開発の重要な部分です。 気付いているか否かにかかわらず、私たちは継続的にテストをしています。 例えば、ぐえぐ でクラスを書くとき、私たちはステップごとにデバッグしたり、または単純に
echo 文や die 文を使ったりして、実装が最初の計画通りに動作することを検証します。 ウェブ・アプリケーションの場合は、何らかのテスト・データをフォームに入力して、ページが期待通りにユーザと相互作用をすることを確認します。
テストを実行するプロセスを自動化して、何かを検証する必要がある
ときは、いつでも、 それを代行してくれるコードを呼び出すだけでよい
ようにすることが出来ます。 結果が計画したものと合致することを検証するコードが テスト と呼ばれ、それを作成して更に実行するプロセスがテスト自動化 として知られています。 このテストの章の主題は、このテストの自動化です。

13.1.1

テストとともに開発する

テスト駆動開発 〨ごいい〩 とビヘイビア駆動開発 〨あいい〩 のソフトウェア開発手法においては、実際のコードを書く前に、 コードの断片または全体の機能の振る舞いを一連のシナリオまたはテストとして記述します。 そして、その後で初めて、テストに合格するように実装を作成して、 意図された振る舞いが達成されていることを検証します。
一つの機能を開発するプロセスは以下のようになります。
• 実装されるべき機能を記述するテストを作成する。
• 新しいテストを走らせて、失敗することを確認する。まだ実装がな
いので、これは予期された結果です。
• 新しいテストに合格するための単純なコードを書く。
• 全てのテストを走らせて、全てが合格することを確認する。
• コードを改良して、それでも全てのテストが くか であることを確認
する。
〵〴〳

〵〴〴

ぃえぁぐごぅげ 〱〳〮 テスト

完了すれば、別の機能または改良のために、このプロセスを再び繰り返します。 既存の機能が変更される場合は、テストも変更されなければなりません。
ヒント〺 多数の小さくて単純なイテレーションを繰り返すために時間を取られていると感じる場合は、テスト・シナリオのカバー範囲を広くして、テストを再度実行するまでの作業量を増やしてみてください。 デバッグばかりやっている場合
は、逆に範囲を狭めてみてください。
全ての実装作業の前にテストを作成する理由は、そうすれば、その後で、 達成したい事柄に集中して「どのようにするか」に没頭することが出来るからです。 通常、そのようにすることは、良い抽象化、機能修正時の容易なテスト保守、また、結合度の低いコンポーネントにつながります。
ですから、このような手法の長所を要約すると次のようになります。
• 一時に一つの事柄に集中できるため、計画と実装がより良いものになる。
• より多くの機能をより詳細にテストでカバーできる。つまり、テス
トが くか なら何も問題がないと期待できる。
通常は、長い期間で見れば、かなり時間を節約する効果があります。

13.1.2

いつ、どうやって、テストするか

上記で説明したテスト・ファーストの手法は長期間にわたる比較的複雑なプロジェクトには合理的なものですが、簡単なプロジェクトでは、やりすぎとなるおそれもあります。 この手法が適切であることを示す指標がいくつかあります。
• プロジェクトは既に大きくて複雑である。
• プロジェクトの要求仕様が複雑になってきている。プロジェクトが継続的に大きくなっている。
• プロジェクトが長期にわたる予定である。
• 失敗のコストが高すぎる。
既存の実装の振る舞いをカバーするテストを作成することは、何も悪いことではありません。
• プロジェクトはレガシーなものであるが、段階的に刷新される予定である。
• 従事すべきプロジェクトを得たが、それにはテストがなかった。
どんな形式の自動化テストもやりすぎになる、という場合もあるでしょう。
• プロジェクトは単純で、この先も、複雑になる心配はない。
• これ以上かかわることはない一度限りのプロジェクトである。
ただ、このような場合であっても、時間に余裕があれば、テストを自動化することは良いことです。

〱〳〮〲〮 テスト環境の構築

13.1.3〵〴〵

参考• ごづびぴ いひどぶづの いづぶづぬはばねづのぴ〺 あべ ぅへちねばぬづ 〯 かづのぴ あづっに〮 ぉこあぎ〺 〰〳〲〱〱〴〶〵〳〰〮

13.2

テスト環境の構築

すどど 〲 は Codeception1 テスト・フレームワークとの統合を公式にサポートしており、 次のタイプのテストを作成することを可能にしています。
• 単体テスト 〭 一かたまりのコードが期待通りに動くことを検証する。
• 機能テスト 〭 ブラウザのエミュレーションによって、ユーザの視点からシナリオを検証する。
• 受入テスト 〭 ブラウザの中で、ユーザの視点からシナリオを検証する。
これら三つのタイプのテスト全てについて、すどど は、yii2-basic2 と yii2-advanced3の両方のプロジェクト・テンプレートで、 そのまま使えるテストセットを提供しています。
ベーシック・テンプレート、アドバンスト・テンプレートの両方とも、ぃはつづっづばぴどはの がプリ・インストールされて付いて来ます。 これらのテンプレートの一つを使っていない場合は、下記のコンソールコマンドを発行することで ぃはつづっづばぴどはの をインストールすることが出来ます。
composer require --dev codeception/codeception
composer require --dev codeception/specify
composer require --dev codeception/verify

13.3

単体テスト

単体テストは、一かたまりのコードが期待通りに動作することを検証するものです。 すなわち、さまざまな入力パラメータを与えて、クラスのメソッドが期待通りの結果を返すかどうかを検証します。 単体テスト
は、通常は、テストされるクラスを書く人によって開発されます。
すどど における単体テストは、ぐえぐさのどぴ と ぃはつづっづばぴどはの 〨こちらはオプションです〩 の上に構築されます。従って、それらのドキュメントを通読することが推奨されます。
• ぃはつづっづばぴどはの てはひ すどど てひちねづぷはひに4• ぃはつづっづばぴどはの さのどぴ ごづびぴび5• ぐえぐさのどぴ のドキュメントの第〲章以降6 〮https://github.com/Codeception/Codeception
https://github.com/yiisoft/yii2-app-basic
3
https://github.com/yiisoft/yii2-app-advanced
4
https://codeception.com/for/yii
5
https://codeception.com/docs/05-UnitTests
6
https://phpunit.readthedocs.io/en/9.5/writing-tests-for-phpunit.html
1
2

〵〴〶

13.3.1ぃえぁぐごぅげ 〱〳〮 テスト

ベーシック・テンプレート、アドバンスト・テンプレートのテストを実行する

アドバンスト・テンプレートでプロジェクトを開始した場合、テストの実行については、 【テスト】 のガイド7 を参照して下さい。
ベーシック・テンプレートでプロジェクトを開始した場合は、げぅぁいきぅ
の 【ぴづびぴどので】 のセクション8 を参照して下さい。

13.3.2

フレームワークの単体テスト

すどど フレームワーク自体に対する単体テストを走らせたい場合は、】すどど 〲の開発を始めよう9 【 の説明に従ってください。

13.4

機能テスト

機能テストはユーザの視点からシナリオを検証するものです。 受入テス
ト と似ていますが、えごごぐ によって通信する代りに、 ぐくこご や ぇぅご のパラメータなどの環境変数を設定しておいてから、アプリケーションのインスタンスをコードから直接に実行します。
機能テストは一般的に受入テストより高速であり、失敗した場合に詳
細なスタックトレースを提供してくれます。 経験則から言うと、特別なウェブ・サーバ設定や おちぶちこっひどばぴ による複雑な さぉ を持たない場合は、機能テストの方を選ぶべきです。
機能テストは ぃはつづっづばぴどはの フレームワークの助けを借りて実装されています。これにつては、優れたドキュメントがあります。
• ぃはつづっづばぴどはの てはひ すどど てひちねづぷはひに10• ぃはつづっづばぴどはの うふのっぴどはのちぬ ごづびぴび11

13.4.1

ベーシック・テンプレート、アドバンスト・テンプレートのテストを実行する

アドバンスト・テンプレートで開発をしている場合は、テスト実行の詳細について、 【テスト】 のガイド12 を参照して下さい。
ベーシック・テンプレートで開発をしている場合は、げぅぁいきぅ の【ぴづびぴどので】 のセクション13 を参照して下さい。
7
https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/
start-testing.md
8
https://github.com/yiisoft/yii2-app-basic/blob/master/README.md#testing9
https://github.com/yiisoft/yii2/blob/master/docs/internals-ja/
getting-started.md
10
https://codeception.com/for/yii
11
https://codeception.com/docs/04-FunctionalTests
12
https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/
start-testing.md
13
https://github.com/yiisoft/yii2-app-basic/blob/master/README.md#testing〱〳〮〵〮 受入テスト

13.5

〵〴〷

受入テスト

受入テストはユーザの視点からシナリオを検証するものです。テストされるアプリケーションは ぐとばあひはぷびづひ または実際のブラウザによってアクセスされます。 どちらの場合でも、ブラウザは えごごぐ によって通信しま
すので、アプリケーションはウェブ・サーバによってホストされる必要があります。
受入テストは ぃはつづっづばぴどはの フレームワークの助けを借りて実装されています。ぃはつづっづばぴどはの フレームワークには優れたドキュメントがあります
ので、参照して下さい。
• ぃはつづっづばぴどはの てはひ すどど てひちねづぷはひに14• ぃはつづっづばぴどはの ぁっっづばぴちのっづ ごづびぴび15

13.5.1

ベーシック・テンプレート、アドバンスト・テンプレートのテストを実行する

アドバンスト・テンプレートで開発をしている場合は、テスト実行の詳細について、 【テスト】 のガイド16 を参照して下さい。
ベーシック・テンプレートで開発をしている場合は、げぅぁいきぅ の【ぴづびぴどので】 のセクション17 を参照して下さい。

13.6

フィクスチャ

フィクスチャはテストの重要な部分です。 フィクスチャの主な目的は、テストを期待されている方法で繰り返して実行できるように、環境を固定された既知の状態に設定することです。 すどど は、ぃはつづっづばぴどはの でテストを実行する場合でも、単独でテストを実行する場合でも、 フィクス
チャを正確に定義して容易に使うことが出来るように、フィクスチャ・
フレームワークを提供しています。
すどど のフィクスチャ・フレームワークにおける鍵となる概念は、いわゆる フィクスチャ・オブジェクト です。 フィクスチャ・オブジェクト
はテスト環境のある特定の側面を表現するもので、べどどぜぴづびぴぜうどへぴふひづ またはその子クラスのインスタンスです。 例えば、ユーザの いあ テーブルが固定されたデータセットを含むことを保証するために UserFixture を使う、という具合です。 テストを実行する前に一つまたは複数のフィクス
チャ・オブジェクトをロードし、テストの完了時にアンロードします。
フィクスチャは他のフィクスチャに依存する場合があります。依存は
べどどぜぴづびぴぜうどへぴふひづ〺〺〤つづばづのつび プロパティによって定義されます。 フィ
クスチャがロードされるとき、依存するフィクスチャはそのフィクス
https://codeception.com/for/yii
https://codeception.com/docs/03-AcceptanceTests
16
https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/
start-testing.md
17
https://github.com/yiisoft/yii2-app-basic/blob/master/README.md#testing
14
15

〵〴〸

ぃえぁぐごぅげ 〱〳〮 テスト

チャの前に自動的にロードされます。 そしてフィクスチャがアンロード
されるときには、依存するフィクスチャはそのフィクスチャの後にアンロードされます。

13.6.1

フィクスチャを定義する

フィクスチャを定義するためには、べどどぜぴづびぴぜうどへぴふひづ または べどどぜぴづびぴ
ぜぁっぴどぶづうどへぴふひづ を拡張して新しいクラスを作ります。 前者は汎用目的のフィクスチャに最も適しています。 一方、後者はデータベースとアクティブ・レコードを扱うために専用に設計された拡張機能を持っています。
次のコードは、User アクティブ・レコードとそれに対応するテーブル
に関して、フィクスチャを定義するものです。
<?php
namespace app\tests\fixtures;
use yii\test\ActiveFixture;class UserFixture extends ActiveFixture{
public $modelClass = 'app\models\User';}ヒント〺 すべての ActiveFixture は、テストの目的のために
いあ テーブルを準備するものです。 べどどぜぴづびぴぜぁっぴどぶづうどへぴふひづ〺〺〤ぴちぢぬづぎちねづ プロパティまたは べどどぜぴづびぴぜぁっぴどぶづうどへぴふひづ〺〺〤ねはつづぬぃぬちびび プロパティを設定することによって、テーブルを指定することが出来ます。 後者を使う場合は、modelClass によって指定される ActiveRecord クラスからテーブル名が取得されます。
補足〺 べどどぜぴづびぴぜぁっぴどぶづうどへぴふひづ は こけが データベースにのみ適しています。 ぎはこけが データベースのためには、すどど は以下の ActiveFixture クラスを提供しています。
• きはのでは いあ〺 べどどぜねはのではつぢぜぁっぴどぶづうどへぴふひづ• ぅぬちびぴどっびづちひっと〺 べどどぜづぬちびぴどっびづちひっとぜぁっぴどぶづうどへぴふひづ 〨バージョン 〲〮〰〮〲 以降〩
ActiveFixture フィクスチャのフィクスチャ・データは通常は FixturePath/data/TableName.phpとして配置されるファイルで提供されます。 ここで FixturePath はフィ
クスチャ・クラス・ファイルを含むディレクトリを意味し、TableName はフィクスチャと関連付けられているテーブルの名前です。 上記の例では、ファイルは @app/tests/fixtures/data/user.php となります。 データ・
ファイルは、ユーザのテーブルに挿入されるデータ行の配列を返さなけ
ればなりません。 例えば、

〱〳〮〶〮 フィクスチャ

〵〴〹

<?php
return ['user1' => ['username' => 'lmayert','email' => 'strosin.vernice@jerde.com','auth_key' => 'K3nF70it7tzNsHddEiq0BZ0i-OU8S3xV','password' =>'$2y$13$WSyE5hHsG1rWN2jV8LRHzubilrCLI5Ev/iK0r3jRuwQEs2ldRu.a2',],'user2' => ['username' => 'napoleon69','email' => 'aileen.barton@heaneyschumm.com','auth_key' => 'dZlXsVnIDgIzFgX4EduAqkEPuphhOh9q','password' =>'$2y$13$kkgpvJ8lnjKo8RuoR30ay.RjDf15bMcHIF7Vz1zz/6viYG5xJExU6',],];

データ行にはエイリアスを付けることが出来て、後でテストのときにエイリアスを使って行を参照することが出来ます。 上の例では、二つの行はそれぞれ user1 および user2 というエイリアスを付けられています。
また、オート・インクリメントのカラムに対してはデータを指定する必要はありません。 フィクスチャがロードされるときに すどど が自動的に実際の値を行に入れます。
ヒント〺 べどどぜぴづびぴぜぁっぴどぶづうどへぴふひづ〺〺〤つちぴちうどぬづ プロパティを設定して、データ・ファイルの所在をカスタマイズすることが出来ます。 べどどぜぴづびぴぜぁっぴどぶづうどへぴふひづ〺〺でづぴいちぴち〨〩 をオー
バーライドしてデータを提供することも可能です。
前に説明したように、フィクスチャは別のフィクスチャに依存する場合があります。 例えば、ユーザ・プロファイルのテーブルはユーザのテー
ブルを指す外部キーを含んでいるため、UserProfileFixture は UserFixtureに依存します。 依存関係は、次のように、べどどぜぴづびぴぜうどへぴふひづ〺〺〤つづばづのつび
プロパティによって指定されます。
namespace app\tests\fixtures;
use yii\test\ActiveFixture;class UserProfileFixture extends ActiveFixture{
public $modelClass = 'app\models\UserProfile';
public $depends = ['app\tests\fixtures\UserFixture'];}依存関係は、ま た、複数のフィ クスチャが正しく定義された順序でロードされ、アンロードされることを保証します。 上記の例では、全ての外部キー参照が存在することを保証するために UserFixture は常〵〵〰

ぃえぁぐごぅげ 〱〳〮 テストに UserProfileFixture の前にロードされます。 また、同じ理由によって、UserFixture は常に UserProfileFixture がアンロードされた後でアンロードされます。
上記では、いあ テーブルに関してフィクスチャを定義する方法を示しました。 いあ と関係しないフィクスチャ 〨例えば、何らかのファイルやディレクトリに関するフィクスチャ〩 を定義するためには、より汎用的な基底クラス べどどぜぴづびぴぜうどへぴふひづ から拡張して、 ぬはちつ〨〩 と ふのぬはちつ〨〩 のメ
ソッドをオーバーライドすることが出来ます。

13.6.2

フィクスチャを使用する

ぃはつづっづばぴどはの18 を使ってコードをテストしている場合は、フィクスチャのローディングとアクセスについては、 内蔵されているサポートを使用することが出来ます。
その他のテスト・フレームワークを使っている場合は、テスト・ケー
スで べどどぜぴづびぴぜうどへぴふひづごひちどぴ を使って同じ目的を達することが出来ます。
次に、ぃはつづっづばぴどはの を使って UserProfile 単体テストクラスを書く方法
を説明します。
\Codeception\Test\Unit を拡張するあなたの単体テスト・クラスにおいて、 _fixtures() メソッドの中で使いたいフィクスチャを宣言するか、 ま
たは、アクターの haveFixtures() メソッドを直接に使用します。例えば、
namespace app\tests\unit\models;
use app\tests\fixtures\UserProfileFixture;class UserProfileTest extends \Codeception\Test\Unit{public function _fixtures(){return ['profiles' => ['class' => UserProfileFixture::class,// フィクスチャ・データは tests/_data/user.php に配置されている'dataFile' => codecept_data_dir() . 'user.php'],];}// ... テストのメソッド ...

}_fixtures() メソッドにリストされたフィクスチャは、テストが実行される前に自動的にロードされます。 前に説明したように、フィクスチャが18

https://codeception.com/

〱〳〮〶〮 フィクスチャ

〵〵〱

ロードされるときには、それが依存するフィクスチャのすべてが自動的に先にロードされます。 上の例では、UserProfileFixture は UserFixture に依存しているので、テスト・クラスのどのテスト・メソッドを走らせる
ときでも、二つのフィクスチャが連続してロードされます。 すなわち、最初に UserFixture がロードされ、次に UserProfileFixture がロードされます。
_fixtures() でフィクスチャを指定するときも、haveFixtures() でフィ
クスチャを指定するときも、 クラス名あるいはフィクスチャを指す構成
情報配列を使うことが出来ます。 構成情報配列を使うと、フィクスチャ
がロードされるときのフィクスチャのプロパティをカスタマイズすることが出来ます。
また、フィクスチャにエイリアスを割り当てることも出来ます。上記の例では、UserProfileFixture に profiles というエイリアスが与えられています。 そうすると、テスト・メソッドの中でエイリアスを使ってフィ
クスチャ・オブジェクトにアクセスすることが出来るようになります。
例えば、$profile = $I->grabFixture('profiles');は UserProfileFixture オブジェクトを返します。
さらには、UserProfileFixture は ActiveFixture を拡張するものですので、フィクスチャによって提供されたデータに対して、 次の構文を使ってアクセスすることも出来ます。
// 'user1' というエイリアスのデータ行に対応する UserProfileModel を返す$profile = $I->grabFixture('profiles', 'user1');// フィクスチャにある全てのデータ行をたどる
foreach ($I->grabFixture('profiles') as $profile) ...

13.6.3フィクスチャ・クラスとデータ・ファイルを編成する

デフォルトでは、フィクスチャ・クラスは対応するデータ・ファイルを探すときに、フィクスチャのクラス・ファイルを含むフォルダのサブ・フォルダである data フォルダの中を見ます。 簡単なプロジェクトではこの規約に従うことができます。 大きなプロジェクトでは、おそらくは、同じフィクスチャ・クラスを異なるテストに使うために、データ・ファ
イルを切り替える必要がある場合が頻繁に生じるでしょう。 従って、クラスの名前空間と同じように、データ・ファイルを階層的な方法で編成することを推奨します。 例えば、
# tests\unit\fixtures フォルダの下に
data\
components\
fixture_data_file1.php
fixture_data_file2.php
...

〵〵〲

ぃえぁぐごぅげ 〱〳〮 テスト

fixture_data_fileN.php
models\fixture_data_file1.php
fixture_data_file2.php...
fixture_data_fileN.php# 等々

このようにして、テスト間でフィクスチャのデータ・ファイルが衝突するのを回避し、必要に応じてデータ・ファイルを使い分けます。
補足〺 上の例では、フィクスチャ・ファイルには例示目的だけの名前が付けられています。 実際の仕事では、フィクス
チャ・クラスがどのフィクスチャ・クラスを拡張したものであるかに従って名前を付けるべきです。 例えば、いあ フィ
クスチャを べどどぜぴづびぴぜぁっぴどぶづうどへぴふひづ から拡張している場合
は、いあ テーブルの名前をフィクスチャのデータ・ファイル名として使うべきです。 きはのではいあ フィクスチャを べどどぜねはのではつぢ
ぜぁっぴどぶづうどへぴふひづ から拡張している場合は、コレクション名をファイル名として使うべきです。
同様な階層は、フィクスチャ・クラス・ファイルを編成するのにも使うことが出来ます。 data をルート・ディレクトリとして使うのでなく、データ・ファイルとの衝突を避けるために fixtures をルート・ディレク
トリとして使うのが良いでしょう。

13.6.4でフィクスチャを管理する

すどど は yii fixture コマンドライン・ツールでフィクスチャをサポートしています。以下の機能をサポートしています。
• 異なるストレージ 〨げいあきこ、ぎはこけが など〩 へのフィクスチャのロード• 様々な方法でのフィクスチャのアンロード 〨通常はストレージをク
リア〩• フィクスチャの自動生成およびランダム・データの投入
フィクスチャのデータ形式
次のようなフィクスチャ・データをロードするとしましょう。
# users.php ファイル - フィクスチャ・データ・パス (デフォルトでは@tests\unit\fixtures\data) に保存
return [['name' => 'Chase','login' => 'lmayert','email' => 'strosin.vernice@jerde.com',〱〳〮〶〮 フィクスチャ

],
[

];

],

〵〵〳

'auth_key' => 'K3nF70it7tzNsHddEiq0BZ0i-OU8S3xV','password' =>'$2y$13$WSyE5hHsG1rWN2jV8LRHzubilrCLI5Ev/iK0r3jRuwQEs2ldRu.a2','name' => 'Celestine','login' => 'napoleon69','email' => 'aileen.barton@heaneyschumm.com','auth_key' => 'dZlXsVnIDgIzFgX4EduAqkEPuphhOh9q','password' =>'$2y$13$kkgpvJ8lnjKo8RuoR30ay.RjDf15bMcHIF7Vz1zz/6viYG5xJExU6',

データベースにデータをロードするフィクチャを使う場合は、これらの行が users テーブルに対して適用されます。ぎはこけが フィクスチャ、例えば mongodb フィクチャを使う場合は、このデータは users コレクションに対して適用されます。 さまざまなロード戦略を実装する方法などについて公式 ドキュメント19 を参照して下さい。 上記のフィクスチャのサンプ
ルは yii2-faker エクステンションによって生成されました。これについての詳細は、自動生成のセクション を参照して下さい。 フィクスチャ・
クラスの名前は複数形であってはいけません。
フィクスチャをロードする
フィクスチャ・クラスは Fixture という接尾辞を持たなければいけません。デフォルトでは、フィクスチャは tests\unit\fixtures 名前空間の下で探されます。 この挙動は構成またはコマンド・オプションによって変更することが出来ます。-User のように名前の前に - を指定することで、ロードまたはアンロードから除外するフィクスチャを指定することが出来ます。
フィクスチャをロードするためには、次のコマンドを実行します。
補足〺 データをロードする前に、アンロードのシーケンスが実行されます。これによって、通常は、前に実行されたフィク
スチャによって挿入された 既存のデータが全てクリーンアッ
プされることになります。
yii fixture/load <fixture_name>要求される fixture_name パラメータが、データがロードされるフィクス
チャの名前を指定するものです。 いくつかのフィクスチャを一度にロードすることが出来ます。下記はこのコマンドの正しい形式です。
// `User` フィクスチャをロードする
yii fixture/load User
19

https://github.com/yiisoft/yii2/blob/master/docs/guide/test-fixtures.md〵〵〴

ぃえぁぐごぅげ 〱〳〮 テスト// 上記と同じ、"fixture" コマンドのデフォルトのアクションは "load" であるため
yii fixture User// いくつかのフィクスチャをロードする
yii fixture "User, UserProfile"// 全てのフィクスチャをロードする
yii fixture/load "*"// 同上
yii fixture "*"// 一つを除いて全てのフィクスチャをロードする
yii fixture "*, -DoNotLoadThisOne"// 異なる名前空間からフィクスチャをロードする (デフォルトの名前空間はtests\unit\fixtures)
yii fixture User --namespace='alias\my\custom\namespace'// 他のフィクスチャをロードする前に、グローバルフィクスチャ
`some\name\space\CustomFixture` をロードする。
// デフォルトでは、このオプションが `InitDbFixture` について適用され、整合性チェックが無効化/有効化されます。
// カンマで区切って複数のグローバル・フィクスチャを指定することが出来ます。
yii fixture User --globalFixtures='some\name\space\Custom'

フィクスチャをアンロードする
フィクスチャをアンロードするためには、次のコマンドを実行します。
// Users フィクスチャをアンロードする。デフォルトではフィクスチャのストレージをクリアします。(例えば、"users" テーブル、または、mongodb フィクスチャなら"users" コレクションがクリアされます。)
yii fixture/unload User// いくつかのフィクスチャをアンロードする
yii fixture/unload "User, UserProfile"// すべてのフィクスチャをアンロードする
yii fixture/unload "*"// 一つを除いて全てのフィクスチャをアンロードする
yii fixture/unload "*, -DoNotUnloadThisOne"

このコマンドでも、namespace や globalFixtures という同じオプションを適用することが出来ます。
コマンドをグローバルに構成するコマンドライン・オプションはフィクスチャ・コマンドをその場で構成することを可能にするものですが、 コマンドを一度だけ構成して済ませ〱〳〮〶〮 フィクスチャ

〵〵〵たい場合もあります。 例えば、次のように、異なるフィクスチャのパスを構成することが出来ます。
'controllerMap' => ['fixture' => ['class' => 'yii\console\controllers\FixtureController','namespace' => 'myalias\some\custom\namespace','globalFixtures' => ['some\name\space\Foo','other\name\space\Bar'],],]

フィクスチャを自動生成する
すどど は、あなたの代りに、何らかのテンプレートに従ってフィクスチャ
を自動生成することが出来ます。さまざまなデータで、また、いろいろな言語と形式で、フィクスチャを生成することが出来ます。 この機能
は、うちにづひ20 ライブラリと yii2-faker エクステンションによって実現されています。 詳細については、エクステンションの ガイド21 を参照して下さい。〮

13.6.5

まとめ

以上、フィクスチャを定義して使用する方法を説明しました。 下記に、いあ に関連した単体テストを走らせる場合の典型的なワークフローをまとめておきます。
〱〮 yii migrate ツールを使って、テストのデータベースを最新版にアップグレードする〲〮 テスト・ケースを走らせる• フィクスチャをロードする 〭 関係する いあ テーブルをクリーンアップし、フィクスチャ・データを投入する• 実際のテストを実行する• フィクスチャをアンロードする〳〮 全てのテストが完了するまで、ステップ 〲 を繰り返す

20
21

https://github.com/fzaninotto/Faker
https://github.com/yiisoft/yii2-faker/tree/master/docs/guide-ja〵〵〶

ぃえぁぐごぅげ 〱〳〮 テスト

Chapter 14

スペシャル・トピック
14.1

あなた自身のアプリケーション構造を作成する

補足〺 このセクションはまだ執筆中です。
ベーシック1 と アドバンスト2 のプロジェクト・テンプレートは、あなたの要求をほとんどカバーする優れたものですが、 あなたのプロジェクトを開始するためのあなた自身のテンプレートを作成したいこともあるでしょう。
すどど におけるプロジェクト・テンプレートは、composer.json ファイルを含み、ぃはねばはびづひ パッケージとして登録されたレポジトリであるに過ぎません。 どのようなレポジトリでも、ぃはねばはびづひ パッケージとして特定
し、create-project ぃはねばはびづひ コマンドによってインストール可能なものにすることが出来ます。
テンプレート全体を最初から構築するのは少々大変ですので、内蔵のテンプレートの一つを基礎として使うのが良いでしょう。 ここでは、ベーシック・テンプレートを使いましょう。

14.1.1

ベーシック・テンプレートをクローンする

最初のステップは、ベーシック すどど テンプレートの ぇどぴ レポジトリをクローンすることです。
git clone git@github.com:yiisoft/yii2-app-basic.git

そして、レポジトリがあなたのコンピュータにダウンロードされるのを待ちます。 テンプレートに加えられた変更がレポジトリにプッシュ・バックされることはありませんので、ダウンロードしたものから .git
ディレクトリとその中身を全て削除して構いません。
12

https://github.com/yiisoft/yii2-app-basic
https://github.com/yiisoft/yii2-app-advanced

〵〵〷

〵〵〸

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

14.1.2

ファイルを修正する

次 に 、 あ な た の テ ン プ レ ー ト に 合 う よ う に composer.json を 修 正 し ま
す 。 name、description、keywords、homepage、license お よ び support の 値を、あなたの新しいテンプレートを説明するものに変更します。 また、require、require-dev、suggest や、その他のオプションも、あなたのテンプレートの要求に合うように調整します。
補足〺 composer.json ファイルで、extra の下の writable パラ
メータを使って、 アプリケーションがテンプレートを使って作成された後に設定されるべきファイル単位のアクセス権限を指定してください。
次に、あなたが好むデフォルトの状態に合うように、アプリケーションの構造と内容を実際に修正します。 最後に、あなたのテンプレートに適用できるように、げぅぁいきぅ ファイルを更新します。

14.1.3

パッケージを作る

テンプレートが定義できたら、それを基に ぇどぴ レポジトリを作成して、ファイルをそこにプッシュします。 あなたのテンプレートをオープンソース化するつもりなら、レポジトリをホストするのには ぇどぴとふぢ3 が最適の場所です。 テンプレートを共同作業に使わないつもりであれば、どんな ぇどぴ レポジトリサイトでも構いません。
次に、ぃはねばはびづひ のためにパッケージを登録する必要があります。パ
ブリックなテンプレートであれば、パッケージは ぐちっにちでどびぴ4 に登録すべきです。 プライベートなテンプレートは、パッケージの登録が少々トリッキーです。 その説明については ぃはねばはびづひ ドキュメント5 を参照してください。

14.1.4

テンプレートを使う

すどど の新しいプロジェクト・テンプレートを作成するのに必要なことは以上です。 これで、あなたのテンプレートを使ってプロジェクトを作成することが出来ます。
composer create-project --prefer-dist --stability=dev
mysoft/yii2-app-coolone new-project

https://github.com
https://packagist.org/
5
https://getcomposer.org/doc/05-repositories.md#hosting-your-own
34〱〴〮〲〮 コンソール・アプリケーション

14.2

〵〵〹

コンソール・アプリケーション

ウェブ・アプリケーションを構築するための豊富な機能に加えて、すどど はコンソール・アプリケーションのためのフル装備のサポートを持っています。 コンソール・アプリケーションは、主として、ウェブ・サイトのために実行する必要のあるバックグラウンドのタスクやメンテナンスのタスクを作成するために使われるものです。
コンソール・アプリケーションの構造は すどど のウェブ・アプリケー
ションのそれと非常に良く似ています。 コンソール・アプリケーショ
ンは一つまたは複数の べどどぜっはのびはぬづぜぃはのぴひはぬぬづひ クラスから構成されます。コントローラはコンソール環境ではしばしば「コマンド」と呼ばれます。 また、各コントローラは、ウェブのコントローラと全く同じように、一つまたは複数のアクションを持つことが出来ます。
プロジェクト・テンプレートは、両方とも、既にコンソール・アプリ
ケーションを持っています。 レポジトリのベース・ディレクトリにある
yii スクリプトを呼び出すことによって、コンソール・アプリケーションを実行することが出来ます。 このスクリプトは、何もパラメータを追加せずに実行すると、利用できるコマンドの一覧を表示します。

スクリーン・ショットに表示されているように、デフォルトで利用できる一連のコマンドが すどど によって既に定義されています。
• ぁびびづぴぃはのぴひはぬぬづひ 〭 おちぶちこっひどばぴ と ぃここ ファイルを結合して圧縮することが出来ます。 このコマンドについては、アセットのセクション
でさらに学習することが出来ます。
• ぃちっとづぃはのぴひはぬぬづひ 〭 アプリケーションのキャッシュをフラッシュす〵〶〰

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピックることが出来ます。
• うどへぴふひづぃはのぴひはぬぬづひ 〭 テストのために、フィクスチャ・データのロードとアンロードを管理します。 このコマンドについては テス
トのフィクスチャのセクション で詳細に説明されています。
• えづぬばぃはのぴひはぬぬづひ 〭 コンソール・コマンドについてのヘルプ情報を提供します。 これがデフォルトのコマンドであり、上のスクリーン・ショットで見た出力を表示するものです。
• きづびびちでづぃはのぴひはぬぬづひ 〭 ソース・ファイルから翻訳すべきメッセージを抽出します。 このコマンドについてさらに学習するためには、国際化のセクション を参照してください。
• きどでひちぴづぃはのぴひはぬぬづひ 〭 アプリケーションのマイグレーションを管理します。 データベースのマイグレーションについては、データベー
スのマイグレーションのセクション で詳しく説明されています。
• こづひぶづぃはのぴひはぬぬづひ 〭 ぐえぐ の内蔵ウェブ・サーバを走らせることが出来ます。

14.2.1

使用方法

コンソールのコントローラ・アクションは次の構文を使って実行します。
yii <route> [--option1=value1 ... argument1 argument2 ... --option2=value2]

オプションはどの位置で指定しても構いません。
上記において、<route> はコントローラ・アクションへのルートを示すものです。 オプション 〨はばぴどはのび〩 はクラスのプロパティに代入され、引数〨ちひでふねづのぴび〩 はアクション・メソッドのパラメータとなります。
例えば、きどでひちぴづぃはのぴひはぬぬづひ〺〺〤ねどでひちぴどはのごちぢぬづ として migrations を指定し、 マイグレーションの上限を 〵 と指定して きどでひちぴづぃはのぴひはぬぬづひ〺〺
ちっぴどはのさば〨〩 を呼び出すためには、次のようにします。
yii migrate/up 5 --migrationTable=migrations

補足〺 コンソールで * を使う場合は、"*" として引用符号で囲
むことを忘れないでください。 これは、* をカレント・ディ
レクトリの全てのファイル名に置き換えられるシェルのグロブとして実行してしまうことを避けるためです。

14.2.2

エントリ・スクリプト

コンソール・アプリケーションのエントリ・スクリプトは、ウェブ・ア
プリケーションで使用されるブートストラップ・ファイル index.php に相当するものです。 コンソールのエントリ・スクリプトは通常は yii と呼ばれるもので、アプリケーションのルート・ディレクトリに配置されています。 それは次のようなコードを含んでいます。

〱〴〮〲〮 コンソール・アプリケーション〵〶〱#!/usr/bin/env php
<?php
/**
* Yii console bootstrap file.
*/defined('YII_DEBUG') or define('YII_DEBUG', true);defined('YII_ENV') or define('YII_ENV', 'dev');
require __DIR__ . '/vendor/autoload.php';
require __DIR__ . '/vendor/yiisoft/yii2/Yii.php';$config = require __DIR__ . '/config/console.php';$application = new yii\console\Application($config);$exitCode = $application->run();exit($exitCode);

このスクリプトはアプリケーションの一部として生成されるものです。
あなたの必要を満たすように、自由に編集して構いません。 エラー発生
時にスタック・トレースを見たくない、または、全体のパフォーマンス
を上げたい、という場合は、YII_DEBUG 定数を false に設定することが出来ます。 ベーシック・プロジェクト・テンプレートでも、アドバンスト・
プロジェクト・テンプレートでも、コンソール・アプリケーションのエ
ントリ・スクリプトは、開発者に優しい環境を提供するために、デフォルトでデバッグを有効にしています。

14.2.3

構成情報

上記のコードで見るように、コンソール・アプリケーションは、console.phpという名前のそれ自身の構成情報ファイルを使用します。 このファイルの中で、さまざまな アプリケーション・コンポーネント、取り分け、コンソール・アプリケーションのためのプロパティを構成しなければなりません。
ウェブ・アプリケーションとコンソール・アプリケーションが構成
情報のパラメータと値を数多く共有する場合は、共通の部分を独立したファイルに移動して、 そのファイルを両方のアプリケーション 〨ウェブとコンソール〩 の構成情報にインクルードすることを検討しても良いでしょう。 その例をアドバンスト・プロジェクト・テンプレートの中で見ることが出来ます。
ヒント〺 場合によっては、エントリ・スクリプトで指定されているのとは異なるアプリケーション構成情報を使って コン
ソール・コマンドを実行したいことがあります。 例えば、yii
migrate コマンドを使ってテストのデータベースをアップグレードするとき、 データベースが個々のテストスイートの中で構成されているような場合です。 構成情報を動的に変更するためには、コマンドを実行するときに appconfig オプション

〵〶〲

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピックを使ってカスタムの構成情報ファイルを指定するだけで大丈夫です。
yii <route> --appconfig=path/to/config.php ...

14.2.4コンソール・コマンドの補完

シェルで作業をしている場合、コマンド引数の自動補完は便利なものです。 〲〮〰〮〱〱 以降、./yii コマンドは、内蔵で あちびと および ずこえ のために補完をサポートしています。
あちびと の補完
ぢちびと っはねばぬづぴどはの がインストールされていることを確認して下さい。ほとんどの ぢちびと のインストレーションでは、デフォルトで利用可能になっています。
補完スクリプトを /etc/bash_completion.d/ に置いて下さい。
curl -Lhttps://raw.githubusercontent.com/yiisoft/yii2/master/contrib/completion/bash/yii-o /etc/bash_completion.d/yii

一時的な利用の場合は、フ ァイルをカ レント・デ ィレクトリ に置いて、source yii でカレント・セッションに読み込みます。 グローバルに
インストールした場合は、ターミナルを再起動するか、source ~/.bashrcを実行して、有効化する必要があります。
あなたの環境で補完スクリプトを読み込む他の方法については、
あちびと マニュアル6 を参照して下さい。
ずこえ の補完
補完のためのディレクトリ、例えば ~/.zsh/completion/ に補完スクリプトを置いて下さい。
mkdir -p ~/.zsh/completioncurl -Lhttps://raw.githubusercontent.com/yiisoft/yii2/master/contrib/completion/zsh/_yii-o ~/.zsh/completion/_yii

そのディレクトリを $fpath に追加します。例えば ~/.zshrc に次の記述を追加します。
fpath=(~/.zsh/completion $fpath)compinit が ロ ー ド さ れ て い る こ と を 確 認 し て 下 さ い 。 そ う で な け れば、~/.zshrc の中でロードします。
6https://www.gnu.org/software/bash/manual/html_node/
Programmable-Completion.html

〱〴〮〲〮 コンソール・アプリケーション〵〶〳

autoload -Uz compinit && compinit -i

そしてシェルをリロードします。
exec $SHELL -l

14.2.5

あなた自身のコンソール・コマンドを作成する

コンソールのコントローラとアクション
コンソール・コマンドは、べどどぜっはのびはぬづぜぃはのぴひはぬぬづひ を拡張するコント
ローラ・クラスとして定義することが出来ます。 コントローラ・クラスの中で、コントローラのサブ・コマンドに対応する一つまたは複数のアクションを定義します。各アクションの中で、その特定のサブ・コマン
ドのための適切なタスクを実装するコードを書きます。
コマンドを実行するときは、コントローラのアクションに対するルートを指定する必要があります。 例えば、ルート migrate/create
は、きどでひちぴづぃはのぴひはぬぬづひ〺〺ちっぴどはのぃひづちぴづ〨〩 アクション・メソッドに対応するサブコマンドを呼び出します。 実行時に提供されたルートにアクション ぉい が含まれない場合は、〨ウェブのコントローラの場合と同じように〩 デフォルトのアクションが実行されます。
オプション
べどどぜっはのびはぬづぜぃはのぴひはぬぬづひ〺〺はばぴどはのび〨〩 メソッドをオーバーライドすることによって、コンソール・コマンド 〨っはのぴひはぬぬづひ〯ちっぴどはのぉい〩 で利用できるオプションを指定することが出来ます。 このメソッドはコントローラ・クラスのパブリックなプロパティのリストを返さなければなりません。 コ
マンドを実行するときは、--OptionName=OptionValue という構文を使ってオプションの値を指定することが出来ます。 これはコントローラ・クラスの OptionName プロパティに OptionValue を割り当てるものです。
オプションのデフォルト値が配列型である場合、実行時にこのオプションをセットすると、 オプションの値は、入力文字列をカンマで分離することによって、配列に変換されます。
オプションのエイリアス
バージョン 〲〮〰〮〸 以降、コンソールコマンドは、オプションにエイリアスを追加するための べどどぜっはのびはぬづぜぃはのぴひはぬぬづひ〺〺はばぴどはのぁぬどちびづび〨〩 メソッドを提供しています。
エイリアスを定義するためには、コントローラで べどどぜっはのびはぬづぜぃはのぴひはぬぬづひ〺〺はばぴどはのぁぬどちびづび〨〩 をオーバーライドします。例えば、
namespace app\commands;
use yii\console\Controller;〵〶〴

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

class HelloController extends Controller{
public $message;
public function options($actionID){
return ['message'];}public function optionAliases(){return ['m' => 'message'];}}public function actionIndex(){echo $this->message . "\n";}これで、次の構文を使ってコマンドを走らせることが出来るようになります。
./yii hello -m=hello

引数
オプションに加えてに、コマンドは引数を取ることも出来ます。引数
は、リクエストされたサブ・コマンドに対応するアクション・メソッド
へのパラメータとして渡されます。 最初の引数は最初のパラメータに対応し、二番目の引数は二番目のパラメータに対応し、以下同様です。
コマンドが呼び出されたときに十分な数の引数が提供されなかったときは、対応するパラメータは、定義されていれば、宣言されているデフォ
ルト値をとります。 デフォルト値が設定されておらず、実行時に値が提供されなかった場合は、コマンドはエラーで終了します。
array タイプ・ヒントを使って、引数が配列として扱われるべきことを示すことが出来ます。 配列は入力文字列をカンマで分割することによって生成されます。
次に引数を宣言する方法を示す例を挙げます。
class ExampleController extends \yii\console\Controller{// コマンド "yii example/create test" は "actionCreate('test')" を呼び出すpublic function actionCreate($name) { ... }// コマンド "yii example/index city" は "actionIndex('city', 'name')" を呼び出す// コマンド "yii example/index city id" は call "actionIndex('city','id')" を呼び出す〱〴〮〲〮 コンソール・アプリケーション〵〶〵

public function actionIndex($category, $order = 'name') { ... }}// コマンド "yii example/add test" は "actionAdd(['test'])" を呼び出す// コマンド "yii example/add test1,test2" は "actionAdd(['test1','test2'])" を呼び出す
public function actionAdd(array $name) { ... }終了コード
終了コードを使うことはコンソール・アプリケーション開発のベスト・プラクティスです。 コマンドは何も問題が無かったことを示すために0 を返すのが慣例です。コマンドが 〱 以上の値を返したときは、何かエラーを示唆するものとみなされます。 返される数値がエラーコードであり、それによってエラーに関する詳細を見出すことが出来る場合もあります。 例えば、1 は一般的な未知のエラーを示すものとし、2 以上の全てのコードは特定のエラー、例えば、入力エラー、ファイルが見つからない、等々を示すものとすることが出来ます。
コンソール・コマンドに終了コードを返させるためには、 単にコント
ローラのアクション・メソッドで整数を返すようにします。
public function actionIndex(){if (/* 何らかの問題が発生 */ ) {echo "A problem occurred!\n";return 1;}// 何かをする
return 0;}

い く つ か 使 用 で き る 事 前 定 義 さ れ た 定 数 が あ り ま す 。 そ れ ら は べどど
ぜっはのびはぬづぜぅへどぴぃはつづ クラスで定義されています。
public function actionIndex(){if (/* 何らかの問題が発生 */ ) {echo "A problem occurred!\n";return ExitCode::UNSPECIFIED_ERROR;}// 何かをする
return ExitCode::OK;}

もっと詳細なエラー・コードを必要とする場合は、コントローラで詳細な定数を定義するのが良いプラクティスです。

〵〶〶

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

書式設定と色すどど のコンソール・コマンドは出力の書式設定をサポートしています。 これは、コマンドを走らせている端末がサポートしていない場合は、自動的に書式設定の無い出力にグレードダウンされます。
書式設定された文字列を出力することは簡単です。ボールドのテキス
トを出力するには、次のようにします。
$this->stdout("Hello?\n", Console::BOLD);

複数のスタ イルを動的に結合して文字列を構成する必要がある場合
は、ちのびどうはひねちぴ〨〩 を使うほうが良いでしょう。
$name = $this->ansiFormat('Alex', Console::FG_YELLOW);
echo "Hello, my name is $name.";

表形式
バージョン 〲〮〰〮〱〳 以降、表形式のデータをコンソールに表示するウィジェットが追加されています。次のようにして使うことが出来ます。
echo Table::widget(['headers' => ['Project', 'Status', 'Participant'],'rows' => [['Yii', 'OK', '@samdark'],['Yii', 'OK', '@cebe'],],]);詳細については ぁぐぉ リファレンス を参照して下さい。

14.3

コア・バリデータ

すどど は、一般的に使われる一連のコア・バリデータを提供しています。コ
ア・バリデータは、主として、yii\validators 名前空間の下にあります。
長ったらしいバリデータ・クラス名を使う代りに、エイリアス を使って使用するコア・バリデータを指定することが出来ます。 例えば、べどど
ぜぶちぬどつちぴはひびぜげづぱふどひづつざちぬどつちぴはひ クラスを参照するのに required という
エイリアスを使うことが出来ます。
public function rules(){return [[['email', 'password'], 'required'],];}

べどどぜぶちぬどつちぴはひびぜざちぬどつちぴはひ〺〺〤ぢふどぬぴぉのざちぬどつちぴはひび プロパティがサポートされている全てのコア・バリデータのエイリアスを宣言しています。
以下では、全てのコア・バリデータについて、主な使用方法とプロパティを説明します。

〱〴〮〳〮 コア・バリデータ

14.3.1[]〵〶〷boolean// データ型にかかわらず、"selected" が 0 または 1 であるかどうかチェック['selected', 'boolean'],// "deleted" が boolean 型であり、true または false であるかどうかチェック['deleted', 'boolean', 'trueValue' => true, 'falseValue' => false,'strict' => true],

このバリデータは、入力値が真偽値であるかどうかをチェックします。
• trueValue〺 true を表す値。デフォルト値は '1'。
• falseValue〺 false を表す値。デフォルト値は '0'。
• strict〺 入力値の型が trueValue と falseValue の型と一致しなければならないかどうか。デフォルト値は false。
補足〺 えごきが フォームで送信されたデータ入力値は全て文字列であるため、通常は、 びぴひどっぴ プロパティは false のままにすべきです。

14.3.2[]

captcha['verificationCode', 'captcha'],

このバリデータは、通常、べどどぜっちばぴっとちぜぃちばぴっとちぁっぴどはの および べどどぜっちばぴっとち
ぜぃちばぴっとち と一緒に使われ、 入力値が ぃぁぐごぃえぁ ウィジェットによって表示された検証コードと同じであることを確認します。
• caseSensitive〺 検証コードの比較で大文字と小文字を区別するかどうか。デフォルト値は false。
• captchaAction〺 ぃぁぐごぃえぁ 画像を表示する ぃぁぐごぃえぁ アクション に対応する ルート。デフォルト値は 'site/captcha'。
• skipOnEmpty〺 入力値が空のときに検証をスキップできるかどうか。
デフォルト値は false で、 入力が必須であることを意味します。

14.3.3[compare// "password" 属性の値が "password_repeat" 属性の値と同じであるかどうか検証する['password', 'compare'],// 上記と同じだが、比較する属性を明示的に指定['password', 'compare', 'compareAttribute' => 'password_repeat'],// "age" が 30 以上であるかどうか検証する

〵〶〸

]

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック['age', 'compare', 'compareValue' => 30, 'operator' => '>=', 'type' =>'number'],

このバリデータは指定された入力値を他の値と比較し、両者の関係がoperator プロパティで指定されたものであることを確認します。

• compareAttribute〺 その値が比較対象となる属性の名前。 このバリデータが属性を検証するのに使用されるとき、このプロパティのデ
フォルト値はその属性の名前に接尾辞 _repeat を付けた名前になります。 例えば、検証される属性が password であれば、このプロパ
ティのデフォルト値は password_repeat となります。
• compareValue〺 入力値が比較される定数値（または値を返すクロージャ）。 このプロパティと compareAttribute の両方が指定された場
合は、このプロパティが優先されます。
• operator〺 比較演算子。デフォルト値は == で、入力値が compareAttributeの値または compareValue と等しいことを検証することを意味します。 次の演算子がサポートされています。
〕 ==〺 二つの値が等しいことを検証。厳密でない比較を行う。
〕 ===〺 二つの値が等しいことを検証。厳密な比較を行う。
〕 !=〺 二つの値が等しくないことを検証。厳密でない比較を行う。
〕 !==〺 二つの値が等しくないことを検証。厳密な比較を行う。
〕 >〺 検証される値が比較される値よりも大きいことを検証する。
〕 >=〺 検証される値が比較される値よりも大きいか等しいことを検証する。
〕 <〺 検証される値が比較される値よりも小さいことを検証する。
〕 <=〺 検証される値が比較される値よりも小さいか等しいことを検証する。
• type〺 デフォルトの比較タイプは だびぴひどのでだ 〨文字列〩 であり、その場合、値は 〱 バイトごとに比較されます。 数値を比較する場合は、必ず 〤ぴべばづ を だのふねぢづひだ に設定して、 数値としての比較を有効にして下さい。
日付の値を比較する
っはねばちひづ バリデータは、文字列や数値を比較するためにしか使えません。 日付のような値を比較する必要がある場合は、二つの選択肢があります。 日付をある固定値と比較するときは、単に つちぴづ バリデータを使って、 その 〤ねどの や 〤ねちへ のプロパティを指定すれば良いでしょう。
フォームに入力された二つの日付、例えば、fromDate と toDate のフィールドを比較する必要がある場合は、 次のように、っはねばちひづ バリデータとつちぴづ バリデータを組み合わせて使うことが出来ます。
['fromDate', 'date', 'timestampAttribute' => 'fromDate'],['toDate', 'date', 'timestampAttribute' => 'toDate'],〱〴〮〳〮 コア・バリデータ〵〶〹['fromDate', 'compare', 'compareAttribute' => 'toDate', 'operator' => '<',
'enableClientValidation' => false],

バリデ ータは指定された順序に従って実行されま すので、ま ず最初に、fromDate と toDate に入力された値が有効な日付であることが確認されます。 そして、有効な日付であった場合は、機械が読める形式に変換されます。 その後に、これらの二つの値が っはねばちひづ バリデー
タによって比較されます。 現在、つちぴづ バリデータはクライアント・
サイド のバリデー ションを提供してい ませんので 、これはサ ーバ・サイドでのみ動作します。 そのため、っはねばちひづ バリデータについても、〤づのちぢぬづぃぬどづのぴざちぬどつちぴどはの は false に設定されています。

14.3.4date

つちぴづ バリデータには三つの異なる ショートカットがあります。
[[['from_date', 'to_date'], 'date'],[['from_datetime', 'to_datetime'], 'datetime'],[['some_time'], 'time'],]

このバリデータは、入力値が正しい書式の つちぴづ、ぴどねづ、または つちぴづぴどねづ
であるかどうかをチェックします。 オプションとして、入力値を さぎぉじ
タイムスタンプ 〨または、その他、機械による読み取りが可能な形式〩 に変換して、 ぴどねづびぴちねばぁぴぴひどぢふぴづ によって指定された属性に保存することも出来ます。
• format〺 検証される値が従っているべき日付〯時刻の書式。 これには ぉぃさ ねちのふちぬ7 で記述されている日付〯時刻のパターンを使うことが出来ます。 あるいは、ぐえぐ の Datetime クラスによって認識される書式に接頭辞 php: を付けた文字列でも構いません。 サポー
トされている書式については、とぴぴばび〺〯〯ぷぷぷ〮ばとば〮のづぴ〯ねちのふちぬ〯なち〯
つちぴづぴどねづ〮っひづちぴづてひはねてはひねちぴ〮ばとば を参照してください。 このプロパティが設定されていないときは、Yii::$app->formatter->dateFormatの値を取ります。
• timestampAttribute〺 このバリデータが、入力された日付〯時刻から変換した さぎぉじ タイムスタンプを代入することが出来る属性の名前。
これは、検証される属性と同じ属性であってもかまいません。 その場合は、元の値は検証実行後にタイムスタンプで上書きされます。
いちぴづぐどっにづひ で日付の入力を扱う8 に使用例がありますので、参照してください。
https://unicode-org.github.io/icu/userguide/format_parse/datetime/#datetime-format-syntax
8
https://github.com/yiisoft/yii2-jui/blob/master/docs/guide-ja/
topics-date-picker.md
7

〵〷〰

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピックバージョン 〲〮〰〮〴 以降では、〤ぴどねづびぴちねばぁぴぴひどぢふぴづうはひねちぴ と 〤ぴどねづびぴちねばぁぴぴひどぢふぴづごどねづずを使って、 この属性に対するフォーマットとタイム・ゾーンを指定することが出来ます。
timestampAttribute を使う場合、入力値が さぎぉじ タイムスタンプに変換されること、そして、さぎぉじ タイムスタンプは定義により さごぃ であることに注意して下さい。 すなわち、入力のタイム・ゾーン から さごぃ への変換が実行されます。 （この動作は、〲〮〰〮〳〹 以降では、〤つづてちふぬぴごどねづずはのづを設定して変更することが出来ます）• バージョン 〲〮〰〮〴 以降では、タイムスタンプの 最小値 または 最大
値 を指定することも出来ます。
入力が必須でない場合には、つちぴづ バリデータに加えて、つづてちふぬぴ バリデー
タ 〨デフォルト値フィルタ〩 を追加すれば、 空の入力値が null として保存されることを保証することが出来ます。そうしないと、データベースに
0000-00-00 という日付が保存されたり、 デート・ピッカーの入力フィールドが 1970-01-01 になったりしてしまいます。
[][['from_date', 'to_date'], 'default', 'value' => null],[['from_date', 'to_date'], 'date'],14.3.5[default// 空のときは "age" を null にする['age', 'default', 'value' => null],// 空のときは "country" を "USA" にする['country', 'default', 'value' => 'USA'],]// 空のときは "from" と "to" に今日から三日後・六日後の日付を入れる[['from', 'to'], 'default', 'value' => function ($model, $attribute) {return date('Y-m-d', strtotime($attribute === 'to' ? '+3 days' : '+6days'));}],

このバリデータはデータを検証しません。 その代りに、検証される属性が空のときに、その属性にデフォルト値を割り当てます。
• value〺 デフォルト値、または、デフォルト値をコールバックとして返すクロージャ。 検証される属性が空のときにこの値が割り当てられます。クロージャのシグニチャは、次のものでなければなりません。
function foo($model, $attribute) {// ... $value を計算 ...
return $value;}〱〴〮〳〮 コア・バリデータ〵〷〱

情報〺 値が空であるか否かを決定する方法については、独立したトピックとして、空の入力値を扱う のセクションでカバーされています。 データベース・スキーマによるデフォルト値
は、モデルの ぬはちついづてちふぬぴざちぬふづび〨〩 によってロードすることが出来ます。

14.3.6[]

double// "salary" が実数であるかどうかチェック['salary', 'double'],このバ リデータは 、入力値が実数値である かどうかを チェックし ます。のふねぢづひ バリデータと等価です。
• max〺 上限値 〨その値を含む〩。設定されていない場合は、バリデータ
が上限値をチェックしないことを意味します。
• min〺 下限値 〨その値を含む〩。設定されていない場合は、バリデータ
が下限値をチェックしないことを意味します。

14.3.7each

情報〺 このバリデータは、バージョン 〲〮〰〮〴 以降で利用できます。
[]// 全てのカテゴリ ID が整数であるかどうかチェックする['categoryIDs', 'each', 'rule' => ['integer']],

このバリデータは配列の属性に対してのみ働きます。 これは、配列の 全ての 要素が指定された検証規則による検証に成功するかどうかを調べる
ものです。 上の例では、categoryIDs 属性は配列を値として取らなければならず、配列の各要素は integer の検証規則によって検証されることになります。
• rule〺 検証規則を指定する配列。配列の最初の要素がバリデータのクラス名かエイリアスを指定します。 配列の残りの「名前・値」のペアが、バリデータ・オブジェクトを構成するのに使われます。
• allowMessageFromRule〺 埋め込まれた検証規則によって返されるエラー・メッセージを使うかどうか。 デフォルト値は true です。これが false の場合は、message をエラー・メッセージとして使います。
補足〺 属性が配列でない場合は、検証が失敗したと見なされ、
message がエラー・メッセージとして返されます。

〵〷〲

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

14.3.8[]email// "email" が有効なメール・アドレスであるかどうかチェック['email', 'email'],

このバリデータは、入力値が有効なメール・アドレスであるかどうかをチェックします。
• allowName〺 メール・アドレスに表示名 〨例えば、John Smith <john.smith@example.com>〩を許容するか否か。デフォルト値は false。
• checkDNS〺 メールのドメインが存在して ぁ または きじ レコードを持っているかどうかをチェックするか否か。 このチェックは、メー
ル・アドレスが実際には有効なものでも、一時的な いぎこ の問題によって失敗する場合があることに注意してください。 デフォルト値
は false。
• enableIDN〺 検証のプロセスが ぉいぎ 〨国際化ドメイン名〩 を考慮に入れるか否か。 デフォルト値は false。 ぉいぎ の検証を使用するためには、intl ぐえぐ 拡張をインストールして有効化する必要があることに注意してください。そうしないと、例外が投げられます。

14.3.9[exist// a1 の入力値が a1 のカラムに存在する必要がある// すなわち、a1 = 1 は、"a1" カラムに 1 の値が存在する場合に有効['a1', 'exist'],// 以下と同義['a1', 'exist', 'targetAttribute' => 'a1'],['a1', 'exist', 'targetAttribute' => ['a1' => 'a1']],// a1 の入力値が a2 のカラムに存在する必要がある// すなわち、a1 = 2 は、"a2" カラムに 2 の値が存在する場合に有効['a1', 'exist', 'targetAttribute' => 'a2'],// 以下と同義['a1', 'exist', 'targetAttribute' => ['a1' => 'a2']],// a2 の入力値が a2 のカラムに存在する必要がある。a1 がエラー・メッセージを受ける// すなわち、a2 = 2 は、"a2" カラムに 2 の値が存在する場合に有効['a1', 'exist', 'targetAttribute' => ['a2']],// 以下と同義['a1', 'exist', 'targetAttribute' => ['a2' => 'a2']],// a1 と a2 の両方が存在する必要がある。両者はともにエラー・メッセージを受け取る// すなわち、a1 = 3, a2 = 4 は、"a1" カラムに 3, "a2" カラムに 4 が存在す
る場合に有効[['a1', 'a2'], 'exist', 'targetAttribute' => ['a1', 'a2']],// 以下と同義〱〴〮〳〮 コア・バリデータ〵〷〳[['a1', 'a2'], 'exist', 'targetAttribute' => ['a1' => 'a1', 'a2' =>'a2']],// a1 と a2 の両方が存在する必要がある。a1 のみがエラー・メッセージを受け取る// すなわち、a1 = 5, a2 = 6 は、"a1" カラムに 5, "a2" カラムに 6 が存在す
る場合に有効['a1', 'exist', 'targetAttribute' => ['a1', 'a2']],// 以下と同義['a1', 'exist', 'targetAttribute' => ['a1' => 'a1', 'a2' => 'a2']],// a2 の値が a2 のカラム、a1 の値が a3 のカラムに存在する必要がある。a1 がエラー・メッセージを受け取る// すなわち、a1 = 7, a2 = 8 は、"a3" カラムに 7, "a2" カラムに 8 が存在す
る場合に有効['a1', 'exist', 'targetAttribute' => ['a2', 'a1' => 'a3']],// 以下と同義['a1', 'exist', 'targetAttribute' => ['a2' => 'a2', 'a1' => 'a3']],// a1 が存在する必要がある。a1 が配列である場合は、その全ての要素が存在する
必要がある['a1', 'exist', 'allowArray' => true],// すなわち、a1 = 9 は、"a1" カラムに 9 が存在する場合に有効//
a1 = [9, 10] は、"a1" カラムに 9 と 10 が存在する場合に有効// type_id が ProductType クラスで定義されているテーブルの id カラムに存在する必要がある// すなわち、type_id = 1 は ProductType のテーブルの "id" カラムに 1 が存在する場合に有効['type_id', 'exist', 'targetClass' => ProductType::class,'targetAttribute' => ['type_id' => 'id']],]// 同上。定義済みの "type" リレーションを使用。
['type_id', 'exist', 'targetRelation' => 'type'],

このバリデータは、入力値が アクティブ・レコード の属性によって表される テーブルの カラムに存在するか どうかをチ ェックしま す。
targetAttribute を使って アクティブ・レコード の属性を指定し、 targetClass
によって対応するクラスを指定することが出来ます。 これらを指定しない場合は、検証されるモデルの属性とクラスが使用されます。
このバリデータは、一つまたは複数のカラムに対する検証に使用することが出来ます 〨複数のカラムに対する検証の場合は、それらの属性の組
み合せが存在しなければならないことを意味します〩。
• targetClass〺 検証される入力値を探すために使用される アクティ
ブ・レコード クラスの名前。 設定されていない場合は、現在検証されているモデルのクラスが使用されます。
• targetAttribute〺 targetClass において、入力値の存在を検証するために使用される属性の名前。 設定されていない場合は、現在検証されている属性の名前が使用されます。 複数のカラムの存在を同時に検〵〷〴

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック証するために配列を使うことが出来ます。 配列の値は存在を検証するのに使用される属性であり、配列のキーは入力値が検証される属性です。 キーと値が同じ場合は、値だけを指定することが出来ます。 検証されるモデルが きはつづぬぁ であり、検証に使用されるモデル
が きはつづぬあ であるとすると、 下記のように targetAttribute を構成することが出来ます。
〕 null 〽〾 きはつづぬぁ の現在検証されている属性の値が きはつづぬあ の
同名の属性の保存されている値に対してチェックされる〕 'a' 〽〾 きはつづぬぁ の現在検証されている属性の値が きはつづぬあ の属
性 【ち】 の保存されている値に対してチェックされる〕 ['a'] 〽〾 きはつづぬぁ の属性 【ち】 の値が きはつづぬあ の属性 【ち】 の保存されている値に対してチェックされる〕 ['a' => 'a'] 〽〾 同上〕 ['a', 'b'] 〽〾 きはつづぬぁ の属性 【ち】 の値が きはつづぬあ の属性 【ち】 の保存されている値に対してチェックされ、 同時に、きはつづぬぁ の属性 【ぢ】 の値が きはつづぬあ の属性 【ぢ】 の保存されている値に対してチェックされる〕 ['a' => 'b'] 〽〾 きはつづぬぁ の属性 【ち】 の値が きはつづぬあ の属性 【ぢ】の保存されている値に対してチェックされる• targetRelation〺 バージョン 〲〮〰〮〱〴 以降は簡便な targetRelation 属
性が使えます。これは指定されたリレーションの定義によってtargetClass と targetAttribute の属性をオーバーライドするものです。
• filter〺 入力値の存在をチェックするのに使用される いあ クエリに適用される追加のフィルタ。 これには、追加のクエリ条件を表現する文字列または配列を使うことが出来ます 〨クエリ条件の書式については、べどどぜつぢぜけふづひべ〺〺ぷとづひづ〨〩 を参照してください〩。 または、function ($query) というシグニチャを持つ無名関数でも構いません。 $query は関数の中で修正できる けふづひべ オブジェクトです。
• allowArray〺 入力値が配列であることを許容するか否か。デフォルト
値は false。 このプロパティが true で入力値が配列であった場合
は、配列の全ての要素がターゲットのカラムに存在しなければなりません。 targetAttribute を配列で指定して複数のカラムに対して検証しようとしている場合は、このプロパティを true に設定することが出来ないことに注意してください。

14.3.10[]file// "primaryImage" が PNG、JPG、または GIF 形式のアップロードされた// 画像ファイルであり、ファイルサイズが 1MB 以下であるかどうかチェック['primaryImage', 'file', 'extensions' => ['png', 'jpg', 'gif'],'maxSize' => 1024*1024],

このバリデータは、入力値がアップロードされた有効なファイルである〱〴〮〳〮 コア・バリデータ〵〷〵

かどうかをチェックします。
• extensions〺 アップロードを許可されるファイル名拡張子のリスト。
リストは、配列、または、空白かカンマで区切られたファイル名拡
張子からなる文字列 〨例えば、〢でどて〬 なばで】〩 で指定することが出来ます。 拡張子名は大文字と小文字を区別しません。 デフォルト値はnull であり、すべてのファイル名拡張子が許可されることを意味します。
• mimeTypes〺 アップロードを許可されるファイルの きぉきぅ タイプのリスト。 リストは、配列、または、空白かカンマで区切られたファイルの きぉきぅ タイプからなる文字列 〨例えば、〢どねちでづ〯なばづで〬
どねちでづ〯ばので】〩 で指定することが出来ます。 特殊文字 * によるワイル
ドカードのマスクを使って、一群の きぉきぅ タイプに一致させることも出来ます。 例えば image/* は、image/ で始まる全ての きぉきぅ タ
イプ 〨image/jpeg〬 image/png など〩 を通します。 きぉきぅ タイプ名は大文字と小文字を区別しません。デフォルト値は null であり、すべての きぉきぅ タイプが許可されることを意味します。 きぉきぅ タイプの詳細については、一般的なメディア・タイプ9 を参照してください。
• minSize〺 アップロードされるファイルに要求される最小限のバイト数。デフォルト値は null であり、下限値が無いことを意味します。
• maxSize〺 アップロードされるファイルに許可される最大限のバイト数。デフォルト値は null であり、上限値が無いことを意味します。
• maxFiles〺 指定された属性が保持しうる最大限のファイル数。 デ
フォルト値は 〱 であり、入力値がアップロードされた一つだけのファイルでなければならないことを意味します。 この値が 〲 以上である場合は、入力値は最大で maxFiles 数のアップロードされたファ
イルからなる配列でなければなりません。
• checkExtensionByMimeType〺 ファイルの きぉきぅ タイプでファイル拡張
子をチェックするか否か。 きぉきぅ タイプのチェックから導かれる
拡張子がアップロードされたファイルの拡張子と違う場合に、そのファイルは無効であると見なされます。 デフォルト値は true であり、そのようなチェックが行われることを意味します。
FileValidator は べどどぜぷづぢぜさばぬはちつづつうどぬづ と一緒に使用されます。 ファイ
ルのアップロードおよびアップロードされたファイルの検証の実行に関する完全な説明は、ファイルをアップロードする のセクションを参照してください。

14.3.11[

filter// "username" と "email" の入力値をトリムする[['username', 'email'], 'filter', 'filter' => 'trim', 'skipOnArray' =>true],
9https://en.wikipedia.org/wiki/Media_type〵〷〶ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック// "phone" の入力値を正規化する['phone', 'filter', 'filter' => function ($value) {// 電話番号の入力値をここで正規化する
return $value;}],// 関数 "normalizePhone" を使って "phone" の入力値を正規化する['phone', 'filter', 'filter' => [$this, 'normalizePhone']],public function normalizePhone($value) {return $value;}]

このバリデータはデータを検証しません。 代りに、入力値にフィルタを適用して、それを検証される属性に書き戻します。
• filter〺 フィルタを定義する ぐえぐ コールバック。これには、グローバル関数の名前、無名関数などを指定することが出来ます。 関数のシグニチャは `function ($value) { return $newValue; } でなければなりません。このプロパティは必須項目です。
• skipOnArray〺 入力値が配列である場合にフィルタをスキップするか否か。デフォルト値は false。 フィルタが配列の入力を処理できない場合は、このプロパティを true に設定しなければなりません。
そうしないと、何らかの ぐえぐ エラーが生じ得ます。
ヒント〺 入力値をトリムしたい場合は、ぴひどね バリデータを直接使うことが出来ます。
ヒント〺 filter のコールバックに期待されるシグニチャを持つ
ぐえぐ 関数が多数存在します。 例えば、〨どのぴぶちぬ10 や ぢははぬぶちぬ11などを使って〩 型キャストを適用し、属性が特定の型になるように保証したい場合は、 それらの関数をクロージャで包む必要はなく、単にフィルタの関数名を指定するだけで十分です。
['property', 'filter', 'filter' => 'boolval'],['property', 'filter', 'filter' => 'intval'],14.3.12[

image// "primaryImage" が適切なサイズの有効な画像であることを検証['primaryImage', 'image', 'extensions' => 'png, jpg','minWidth' => 100, 'maxWidth' => 1000,'minHeight' => 100, 'maxHeight' => 1000,
1011https://www.php.net/manual/ja/function.intval.php
https://www.php.net/manual/ja/function.boolval.php〱〴〮〳〮 コア・バリデータ

]

〵〷〷

],

このバ リデータは 、入力値が有効な画像ファイ ルであるか どうかをチェックします。 これは 〜ぬづ バリデータを拡張するものであり、従って、そのプロパティの全てを継承しています。 それに加えて、画像の検証の目的に特化した次のプロパティをサポートしています。
• minWidth〺 画像の幅の最小値。デフォルト値は null であり、下限値がないことを意味します。
• maxWidth〺 画像の幅の最大値。デフォルト値は null であり、上限値がないことを意味します。
• minHeight〺 画像の高さの最小値。デフォルト値は null であり、下限値がないことを意味します。
• maxHeight〺 画像の高さの最大値。デフォルト値は null であり、上限
値がないことを意味します。

14.3.13[

ip// "ip_address" が有効な IPv4 または IPv6 アドレスであることを検証['ip_address', 'ip'],// "ip_address" が有効な IPv6 アドレスまたはサブネットであることを検証// 値は完全な IPv6 記法に展開される['ip_address', 'ip', 'ipv4' => false, 'subnet' => null, 'expandIPv6' =>true],]// "ip_address" が有効な IPv4 または IPv6 アドレスであることを検証// 先頭に否定文字 `!` を置くことを許可['ip_address', 'ip', 'negation' => true],

このバリデータは属性の値が有効な ぉぐぶ〴〯ぉぐぶ〶 アドレスまたはサブネッ
トであることを検証します。 正規化または ぉぐぶ〶 展開が有効にされた場
合は、属性の値を変更することも出来ます。
バリデータは以下の構成オプションを持っています。
• ipv4〺 検証の対象となる値が ぉぐぶ〴 アドレスであってよいか否か。デ
フォルト値は true。
• ipv6〺 検証の対象となる値が ぉぐぶ〶 アドレスであってよいか否か。デ
フォルト値は true。
• subnet〺 アドレスが 192.168.10.0/24 のような ぃぉいげ サブネットを持つ ぉぐ であってよいか否か。
〕 true 〭 サブネットが必要。ぃぉいげ の無いアドレスは却下されます〕 false 〭 アドレスは ぃぉいげ を伴ってはいけません〕 null 〭 ぃぉいげ は有っても無くても構いません
デフォルト値は false。

〵〷〸ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック• normalize〺 ぃぉいげ を 持 た な い ア ド レ ス に 、 最 も 短 い 〨ぉぐぶ〴 で は〳〲、ぉぐぶ〶 では 〱〲〸〩 ぃぉいげ プレフィクスを追加するか否か。 subnet
が false 以外の場合にのみ動作します。例えば、〕 10.0.1.5 は 10.0.1.5/32 に正規化され、〕 2008:db0::1 は 2008:db0::1/128 に正規化されます
デフォルト値は false。
• negation〺 検証の対象となるアドレスが先頭に否定文字 ! を持つことが出来るか否か。デフォルト値は false。
• expandIPv6〺 ぉぐぶ〶 アドレスを完全な記法に展開するか否か。 例えば、2008:db0::1 は 2008:0db0:0000:0000:0000:0000:0000:0001 に展開されます。デフォルト値は false。
• ranges〺 許容または禁止される ぉぐぶ〴 または ぉぐぶ〶 の範囲の配列。
配列が空の場合、またはこのオプションが設定されていない場合
は、全ての ぉぐ アドレスが許容されます。 そうでない場合は、最初に合致するものが見つかるまで、規則が順番にチェックされます。
どの規則にも合致しなかった場合、その ぉぐ アドレスは禁止されます。
例えば、 `ばとば せ'client_ip', 'ip', 'ranges' => ['192.168.10.128''!192.168.10.0/24','any' // 他の IP アドレスは全て許容]

そ ` この例では、192.168.10.0/24 のサブネットを除いて、全ての ぉぐぶ〴および ぉぐぶ〶 アドレスが許容されます。 ぉぐぶ〴 アドレス 192.168.10.128
も、制約の前にリストされているため、同様に許容されます。
• networks〺 ranges で使用する事が出来るネットワークのエイリアスの配列。配列の形式は、〕 キー 〭 エイリアス名〕 値 〭 文 字 列 の 配 列 。 文 字 列 は 、 範 囲 、ぉぐ ア ド レ ス 、 ま たは、他のエイリアスとすることが出来ます。 また、文字列は 〨negation オプションとは独立に〩 ! によって否定することが出来ます。
デフォルトで、次のエイリアスが定義されています。
〕 *〺 any〕 any〺 0.0.0.0/0, ::/0
〕 private〺 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fd00::/8〕 multicast〺 224.0.0.0/4, ff00::/8〕 linklocal〺 169.254.0.0/16, fe80::/10〕 localhost〺 127.0.0.0/8', ::1〕 documentation〺 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24, 2001:db8::/32〕 system〺 multicast, linklocal, localhost, documentation
情報〺 このバリデータは、バージョン 〲〮〰〮〷 以降で利用するこ〱〴〮〳〮 コア・バリデータ〵〷〹とが出来ます。

14.3.14[]in// "level" が 1, 2 または 3 であるかどうかチェック['level', 'in', 'range' => [1, 2, 3]],

このバリデータは、入力値が所与の値のリストにあるかどうかをチェックします。
• range〺 与えられた値のリスト。この中に、入力値がなければならない。
• strict〺 入力値と所与の値の比較が厳密でなければならない 〨型と値の両方が同じでなければならない〩 かどうか。 デフォルト値はfalse。
• not〺 検証結果を反転すべきか否か。デフォルト値は false。 このプ
ロパティが true に設定されているときは、入力値が所与の値のリス
トにない場合に検証が成功したとされます。
• allowArray〺 入力値が配列であることを許可するかどうか。 このプロ
パティが true であるときに、入力値が配列である場合は、配列の全ての要素が所与の値のリストにある必要があり、そうでなければ検証は失敗します。

14.3.15[]integer// "age" が整数であるかどうかチェック['age', 'integer'],

このバリデータは入力値が整数であるかどうかをチェックします。
• max〺 上限値 〨その値を含む〩。設定されていないときは、バリデータ
は上限をチェックしません。
• min〺 下限値 〨その値を含む〩。設定されていないときは、バリデータ
は下限をチェックしません。

14.3.16
[

]

match

// "username" が英字から始まり、英字、数字、アンダーバーだけで構成されているかどうかチェック['username', 'match', 'pattern' => '/^[a-z]\w*$/i']

このバリデータは、入力値が指定された正規表現に一致するかどうかをチェックします。

〵〸〰

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック• pattern〺 入力値が一致すべき正規表現。このプロパティを設定することは必須です。 そうしないと、例外が投げられます。
• not〺 検証結果を反転すべきかどうか。 デフォルト値は てちぬびづ で、入力値がパターンに一致したときにだけ検証が成功することを意味します。 このプロパティが ぴひふづ に設定されているときは、入力値がパターンに一致しない場合にだけ検証が成功したと見なされます。

14.3.17[]

number// "salary" が数値であるかどうかチェック['salary', 'number'],

このバリデータは、入力値が数値であるかどうかをチェックします。つはふぢぬづ
バリデータと等価です。
• max〺 上限値 〨その値を含む〩。設定されていないときは、バリデータ
は上限をチェックしません。
• min〺 下限値 〨その値を含む〩。設定されていないときは、バリデータ
は下限をチェックしません。

14.3.18[]

required// "username" と "password" がともに空ではないことをチェックする[['username', 'password'], 'required'],

このバリデータは、入力値が提供されており、空ではないことをチェックします。
• requiredValue〺 入力値として要求される値。このプロパティが設定されていない場合は、入力値が空ではいけないことを意味します。
• strict〺 値を検証するときに、データ型をチェックするかどうか。
デフォルト値は false。 requiredValue が設定されていない場合、このプロパティが true であるときは、バリデータは入力値が厳密な意味で null であるかどうかをチェックします。 一方、このプロパ
ティが false であるときは、値が空か否かの判断に緩い規則を使います。 requiredValue が設定されている場合、このプロパティがtrue であるときは、 入力値と requiredValue を比較するときに型のチェックを行います。
情報〺 値が空であるか否かを決定する方法については、独立したトピックとして、 空の入力値を扱う のセクションでカバーされています。

〱〴〮〳〮 コア・バリデータ

14.3.19
[
]

〵〸〱

safe

// "description" を安全な属性としてマーク['description', 'safe'],

このバリデータは検証を実行しません。 その代りに、このバリデータ
は、属性を 安全な属性 としてマークするために使われます。

14.3.20[]

string// "username" が、長さが 4 以上 24 以下の文字列であるかどうかチェック['username', 'string', 'length' => [4, 24]],

このバリデータは、入力値が一定の長さを持つ有効な文字列であるかど
うかをチェックします。
• length〺 検証される入力文字列の長さの制限を指定します。 これは、次のいずれかの形式で指定することが出来ます。
〕 一つの整数〺 文字列がちょうどその長さでなければならない、その長さ。
〕 一 つ の 要 素 を 持 つ 配 列〺 入 力 文 字 列 の 長 さ の 最 小 値 〨例 えば、[8]〩。これは min を上書きします。
〕 二つの要素を持つ配列〺 入力文字列の長さの最小値と最大値〨例えば、[8, 128]〩。 これは min と max の両方を上書きします。
• min〺 入力文字列の長さの最小値。設定されていない時は、長さの下限値がないことを意味します。
• max〺 入力文字列の長さの最大値。設定されていない時は、長さの上限値がないことを意味します。
• encoding〺 検証される入力文字列の文字エンコーディング。設定されていない時は、 アプリケーションの っとちひびづぴ の値が使われ、デフォルトでは UTF-8 となります。

14.3.21[]trim// "username" と "email" の前後にあるホワイトスペースをトリムする[['username', 'email'], 'trim'],

このバリデータはデータの検証を実行しません。その代りに、入力値の前後にあるホワイト・スペースをトリムします。 入力値が配列であるときは、このバリデータによって無視されることに注意してください。

〵〸〲ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

14.3.22[

unique// a1 の入力値が a1 のカラムにおいてユニークである必要がある// すなわち、a1 = 1 は、"a1" カラムに 1 の値が存在しない場合に有効['a1', 'unique'],// 以下と同義['a1', 'unique', 'targetAttribute' => 'a1'],['a1', 'unique', 'targetAttribute' => ['a1' => 'a1']],// a1 の入力値が a2 のカラムにおいてユニークである必要がある// すなわち、a1 = 2 は、"a2" カラムに 2 の値が存在しない場合に有効['a1', 'unique', 'targetAttribute' => 'a2'],// 以下と同義['a1', 'unique', 'targetAttribute' => ['a1' => 'a2']],// a1 と a2 の両方がユニークである必要がある。両者がともにエラー・メッセー
ジを受け取る// すなわち、a1 = 3, a2 = 4 は、"a1" カラムに 3 の値が存在せず、同時に、"a2" カラムに 4 の値が存在しない場合に有効[['a1', 'a2'], 'unique', 'targetAttribute' => ['a1', 'a2']],// 以下と同義[['a1', 'a2'], 'unique', 'targetAttribute' => ['a1' => 'a1', 'a2' =>'a2']],// a1 と a2 の両方がユニークである必要がある。a1 のみがエラー・メッセージを受け取る['a1', 'unique', 'targetAttribute' => ['a1', 'a2']],// a2 の値が a2 のカラム、a1 の値が a3 のカラムにおいてユニークである必要がある。a1 がエラー・メッセージを受け取る// すなわち、a1 = 5, a2 = 6 は、"a3" カラムに 5 の値が存在せず、同時に、"a2" カラムに 6 の値が存在しない場合に有効['a1', 'unique', 'targetAttribute' => ['a2', 'a1' => 'a3']],]// type_id が ProductType クラスで定義されているテーブルの "id" カラムにおいてユニークである必要がある// すなわち、type_id = 1 は ProductType のテーブルの "id" カラムに 1 が存在しない場合に有効['type_id', 'unique', 'targetClass' => ProductType::class,'targetAttribute' => 'id'],

このバリデータは、入力値がテーブルのカラムにおいてユニークであるかどうかをチェックします。 アクティブ・レコード モデルの属性に対してのみ働きます。 一つのカラムに対する検証か、複数のカラムに対する検証か、どちらかをサポートします。
• targetClass〺 検証される入力値を探すために使用される アクティ
ブ・レコード クラスの名前。 設定されていない場合は、現在検証されているモデルのクラスが使用されます。
• targetAttribute〺 targetClass において、入力値がユニークであること〱〴〮〳〮 コア・バリデータ〵〸〳を検証するために使用される属性の名前。 設定されていない場合
は、現在検証されている属性の名前が使用されます。 複数のカラムのユニーク性を同時に検証するために配列を使うことが出来ます。 配列の値はユニーク性を検証するのに使用される属性であり、配列のキーはその入力値が検証される属性です。 キーと値が同じ場合は、値だけを指定することが出来ます。 検証されるモデルがきはつづぬぁ であり、検証に使用されるモデルが きはつづぬあ であるとすると、 下記のように targetAttribute を構成することが出来ます。
〕 null 〽〾 きはつづぬぁ の現在検証されている属性の値が きはつづぬあ の
同名の属性の保存されている値に対してチェックされる〕 'a' 〽〾 きはつづぬぁ の現在検証されている属性の値が きはつづぬあ の属
性 【ち】 の保存されている値に対してチェックされる〕 ['a'] 〽〾 きはつづぬぁ の属性 【ち】 の値が きはつづぬあ の属性 【ち】 の保存されている値に対してチェックされる〕 ['a' => 'a'] 〽〾 同上〕 ['a', 'b'] 〽〾 きはつづぬぁ の属性 【ち】 の値が きはつづぬあ の属性 【ち】 の保存されている値に対してチェックされ、 同時に、きはつづぬぁ の属性 【ぢ】 の値が きはつづぬあ の属性 【ぢ】 の保存されている値に対してチェックされる〕 ['a' => 'b'] 〽〾 きはつづぬぁ の属性 【ち】 の値が きはつづぬあ の属性 【ぢ】の保存されている値に対してチェックされる• filter〺 入力値がユニークであることをチェックするのに使用される いあ クエリに適用される追加のフィルタ。 これには、追加のクエ
リ条件を表現する文字列または配列を使うことが出来ます 〨クエリ
条件の書式については、べどどぜつぢぜけふづひべ〺〺ぷとづひづ〨〩 を参照してください〩。 これは、または、function ($query) というシグニチャを持つ無名関数でも構いません。 $query は関数の中で修正できる けふづひべ オブジェクトです。

14.3.23[]url// "website" が有効な URL であるかどうかをチェック。
// URI スキームを持たない場合は、"website" 属性に "http://" を前置する['website', 'url', 'defaultScheme' => 'http'],

このバリデータは、入力値が有効な さげが であるかどうかをチェックします。
• validSchemes〺 有効と見なされるべき さげぉ スキームを指定する配列。
デフォルト値は ['http', 'https'] であり、http と https の さげが がともに有効と見なされることを意味します。
• defaultScheme〺 入力値がスキームの部分を持たないときに前置される
デフォルトの さげぉ スキーム。 デフォルト値は null であり、入力値を修正しないことを意味します。

〵〸〴

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック• enableIDN〺 バリデータが ぉいぎ 〨国際化ドメイン名〩 を考慮すべきか否か。デフォルト値は false。 ぉいぎ の検証を使用するためには、intl
ぐえぐ 拡張をインストールして有効化する必要があることに注意してください。 そうしないと、例外が投げられます。
補足〺 このバリデータは さげが スキームとホスト部分が正しいものであることを検証します。 さげが の残りの部分はチェックしません。また、じここ や他の攻撃に対して防御するように設計されてもいません。 アプリケーション開発における脅威に対する防御について更に学習するためにセキュリティのベス
ト・プラクティス を参照して下さい。

14.4

国際化

国際化 〨ぉ〱〸ぎ〩 とは、工学的な変更を伴わずにさまざまな言語と地域に順応できるように、 ソフトウェア・アプリケーションを設計するプロセスを指します。 潜在的なユーザが世界中にいるウェブ・アプリケーション
にとっては、このことは特に重要な意味を持ちます。 すどど は、全ての領域にわたる国際化機能を提供し、メッセージの翻訳、ビューの翻訳、日付と数字の書式設定をサポートします。

14.4.1

ロケールと言語ロケール
ロケールとは、ユーザの言語、国、そして、ユーザが彼らのユーザ・イ
ンタフェイスにおいて目にすることを期待する すべての変異形式を定義する一連のパラメータです。 ロケールは、通常、言語 ぉい と地域 ぉい から成るロケール ぉい によって定義されます。
例えば、en-US という ぉい は、「英語とアメリカ合衆国」というロケールを意味します。
すどど アプリケーションで使用される全てのロケール ぉい は、一貫性のために、 ll-CC の形式に正規化されなければなりません。 ここで ll はぉこく〭〶〳〹12 に従った小文字二つまたは三つの言語コードであり、 CC はぉこく〭〳〱〶〶13 に従った二文字の国コードです。 ロケールに関する更なる詳細は ぉぃさ プロジェクトのドキュメント14 に述べられています。
言語
すどど では、】言語】 という用語でロケールに言及することがしばしばあります。
https://www.loc.gov/standards/iso639-2/
https://en.wikipedia.org/wiki/ISO_3166-1#Current_codes
14
https://unicode-org.github.io/icu/userguide/locale/#the-locale-concept
1213〱〴〮〴〮 国際化〵〸〵

すどど のアプリケーションでは二つの言語を使用します。すなわち、• ソース言語 〺 ソース・コード中のテキスト・メッセージが書かれている言語。
• ターゲット言語 〺 コンテントをエンド・ユーザに表示するのに使用されるべき言語。
いわゆるメッセージ翻訳サービスは、主として、テキスト・メッセージをソース言語からターゲット言語に翻訳するものです。
構成
アプリケーションの言語は、アプリケーションの構成情報で次のように構成することが出来ます。
return [// ターゲット言語を日本語に設定'language' => 'ja-JP',// ソース言語を英語に設定'sourceLanguage' => 'en-US',];......

ソース言語 のデフォルト値は en-US であり、合衆国の英語を意味します。 このデフォルト値は変えないことが 推奨 されます。 なぜなら、通常は、英語から他の言語への翻訳者を見つける方が、非英語から非英語への翻訳者を見つけるより、はるかに簡単だからです。
ターゲット言語 は、エンド・ユーザの言語選択など、 さまざまな要因に基づいて、動的に設定しなければならないことがよくあります。
アプリケーションの構成情報で構成するかわりに、次の文を使ってター
ゲット言語を変更することが出来ます。
// ターゲット言語を中国語に変更\Yii::$app->language = 'zh-CN';

ヒント〺 ソース言語がコードの部分によって異なる場合は、メッセージ・ソースごとにソース言語をオーバーライドすることが出来ます。 これについては、次の説で説明します。

14.4.2

メッセージ翻訳

ソース言語からターゲット言語へメッセージ翻訳サービスは、テキスト・メッセージをある言語 〨通常は
ソース言語〩 から別の言語 〨通常は ターゲット言語〩 に翻訳するものです。
翻訳は、元のメッセージと翻訳されたメッセージを格納するメッセー
ジ・ソースの中から、翻訳対象となったメッセージを探すことにより行

〵〸〶

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

われます。 メッセージが見つかれば、対応する翻訳されたメッセージが返されます。メッセージが見つからなければ、元のメッセージが翻訳されずに返されます。
実装の仕方
メッセージ翻訳サービスを使用するためには、主として次の作業をする必要があります。
〱〮 翻訳する必要のある全てのテキスト・メッセージを すどど〺〺ぴ〨〩 メ
ソッドの呼び出しの中に包む。
〲〮 メッセージ翻訳サービスが翻訳されたメッセージを探すことが出来る一つまたは複数のメッセージ・ソースを構成する。
〳〮 翻訳者にメッセージを翻訳させて、それをメッセージ・ソースに格納する。
〱〮 テキスト・メッセージを包む すどど〺〺ぴ〨〩 メソッドは次のように使います。
echo \Yii::t('app', 'This is a string to translate!');

ここで、二番目のパラメータが翻訳されるべきテキスト・メッセージを示し、 最初のパラメータはメッセージを分類するのに使用されるカテゴ
リ名を示します。
〲〮 一つまたは複数のメッセージ・ソースを構成する すどど〺〺ぴ〨〩 メソッド
は i18n アプリケーション・コンポーネント の translate メソッドを呼んで実際の翻訳作業を実行します。 このコンポーネントはアプリケーショ
ンの構成情報の中で次のようにして構成することが出来ます。
'components' => [// ...
'i18n' => ['translations' => ['app*' => ['class' => 'yii\i18n\PhpMessageSource',//'basePath' => '@app/messages',//'sourceLanguage' => 'en-US','fileMap' => ['app' => 'app.php','app/error' => 'error.php',
],
],
],
],
],

上記のコードにおいては、べどどぜど〱〸のぜぐとばきづびびちでづこはふひっづ によってサポートされるメッセージ・ソースが構成されています。

〱〴〮〴〮 国際化〵〸〷

シンボル によるカテゴリのワイルドカード app* は、app で始まる全てのメッセージ・カテゴリが このメッセージ・ソースを使って翻訳されるべきであることを示しています。
〳〮 翻訳者にメッセージを翻訳させて、それをメッセージ・ソースに格納する べどどぜど〱〸のぜぐとばきづびびちでづこはふひっづ クラスは、単純な ぐえぐ 配列を持つ複数の ぐえぐ ファイルを使用してメッセージ翻訳を格納します。 それらのファイルが、「ソース言語」のメッセージと「ターゲット言語」の翻訳とのマップを含みます。
情報〺 それらのファイルを message コマンド を使用して自動的に生成することが出来ます。 このセクションで後で紹介します。
ぐえぐ ファイルは、それぞれ、一つのカテゴリのメッセージに対応します。 デフォルトでは、ファイル名はカテゴリ名と同じでなければなりま
せん。app/messages/nl-NL/main.ph の例を示します。
<?php
/**
* Translation map for nl-NL*/
return ['welcome' => 'welkom'];

ファイルのマッピング ただし、てどぬづきちば を構成して、別の命名方法によってカテゴリを ぐえぐ ファイルにマップすることも可能です。
上記の例では、〨ja-JP がターゲット言語であると仮定すると〩 app/errorのカテゴリは @app/messages/ja-JP/error.php という ぐえぐ ファイルにマップされます。 fileMap を構成しなければ、このカテゴリは @app/messages/ja-JP/app/error.phpにマップされることになります。
他のストレージ・タイプ 翻訳メッセージを格納するのには、ぐえぐ ファ
イル以外に、 次のメッセージ・ソースを使うことも可能です。
• べどどぜど〱〸のぜぇづぴぴづへぴきづびびちでづこはふひっづ 〭 翻訳メッセージを保持するのにぇぎさ ぇづぴぴづへぴ の きく ファイルまたは ぐく ファイルを使用する• べどどぜど〱〸のぜいぢきづびびちでづこはふひっづ 〭 翻訳メッセージを保存するのにデータ
ベース・テーブルを使用する

14.4.3

メッセージのフォーマット

メッセージを翻訳するときには、プレースホルダを埋め込んで、動的なパラメータ値で実行時に置き換えさせることが出来ます。 更には、パラメータ値をターゲット言語に応じてフォーマットさせるための特別なプ〵〸〸ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

レースホルダの構文を使うことも出来ます。 この項では、メッセージをフォーマットする様々な方法を説明します。
補足〺 以下においては、メッセージ・フォーマットの理解を助けるために、原文にはない日本語への翻訳例 〨とその出力結果〩 をコード・サンプルに追加しています。
メッセージ・パラメータ
翻訳対象となるメッセージには、一つまたは複数のパラメータ 〨プレー
スホルダとも呼びます〩 を埋め込んで、 与えられたパラメータ値で置き換えられるようにすることが出来ます。 様々なパラメータ値のセットを与えることによって、翻訳されるメッセージを動的に変化させることが出来ます。 次の例では、'Hello, {username}!' というメッセージの中のプ
レースホルダ {username} が 'Alexander' と 'Qiang' にそれぞれ置き換えられます。
$username = 'Alexander';// username が "Alexander" になった翻訳メッセージを表示
echo \Yii::t('app', 'Hello, {username}!', ['username' => $username,]);$username = 'Qiang';// username が "Qiang" になった翻訳メッセージを表示
echo \Yii::t('app', 'Hello, {username}!', ['username' => $username,]);

プレースホルダを持つメッセージを翻訳する時には、プレースホルダはそのままにしておかなければなりません。 これは、プレースホルダはYii::t() を呼んでメッセージを翻訳する時に、実際の値に置き換えられるものだからです。
// 日本語翻訳: '{username} さん、こんにちは!'プレースホルダには、名前付きプレースホルダ と 序数プレースホルダ のどちらかを使用する事が出来ます。ただし、一つのメッセージに両方を使うことは出来ません。
上記の例は名前付きプレースホルダの使い方を示すものです。 すな
わち、各プレースホルダは {name} という形式で書かれていますが、それに対して、キーが〨波括弧なしの〩プレースホルダ名であり、 値がそのプ
レースホルダを置き換える値である連想配列を渡す訳です。
序数プレースホルダは、〰 ベースの整数の序数をプレースホルダ名として使います。 このプレースホルダは、Yii::t() の呼び出しに出現する
順序に従って、パラメータ値によって置き換えられます。 次の例では、序数プレースホルダ {0}、{1} および {2} は、それぞれ、$price、$count お
よび $subtotal の値によって置き換えられます。

〱〴〮〴〮 国際化〵〸〹$price = 100;$count = 2;
$subtotal = 200;
echo \Yii::t('app', 'Price: {0}, Count: {1}, Subtotal: {2}', [$price,$count, $subtotal]);// 日本語翻訳: '価格: {0}, 数量: {1}, 小計: {2}'序数プレースホルダが一つだけの場合は、値を配列に入れずにそのまま指定することができます。
echo \Yii::t('app', 'Price: {0}', $price);

ヒント〺 たいていの場合は名前付きプレースホルダを使うべきです。 と言うのは、翻訳者にとっては、パラメータ名がある方が、翻訳すべきメッセージ全体をより良く理解できるからです。
パラメータのフォーマット
メッセージのプレースホルダにフォーマットの規則を追加して指定し、パラメータ値がプレースホルダを置き換える前に適切にフォーマットされるようにすることが出来ます。 次の例では、price のパラメータ値の型は数値として扱われ、通貨の形式でフォーマットされます。
$price = 100;
echo \Yii::t('app', 'Price: {0,number,currency}', $price);補足〺 パラメータのフォーマットには、どのぴぬ ぐえぐ 拡張15 のイ
ンストールが必要です。
プレースホルダにフォーマット規則を指定するためには、短い構文または完全な構文のどちらかを使うことが出来ます。
短い形式: {name,type}
完全な形式: {name,type,style}補足〺 {}、\mintinline{text}{}、'、# などの特殊な文字を使用する必要がある場合は、その部分の文字列を ' で囲んでください。
echo Yii::t('app', "Example of string with ''-escaped characters'':'{' '}' '{test}' {count,plural,other{''count'' value is # '#{}'}}",['count' => 3]);+```

このようなプレースホルダを指定する方法についての完全な説明は、ぉぃさ
ドキュメント16 を参照してください。以下では、よくある使用方法をいく
つか示します。
https://www.php.net/manual/ja/intro.intl.php
https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classMessageFormat.html
15
16

〵〹〰

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

数値$sum = 12345;
echo \Yii::t('app', 'Balance: {0,number}', $sum);// 日本語翻訳: '差引残高: {0,number}'// 日本語出力: '差引残高: 12,345'

オプションのパラメータとして、integer、currency、percent のスタイルを指定することが出来ます。
$sum = 12345;
echo \Yii::t('app', 'Balance: {0,number,currency}', $sum);// 日本語翻訳: '差引残高: {0,number,currency}'// 日本語出力: '差引残高: ￥12,345'

または、数値をフォーマットするカスタム・パターンを指定することも出来ます。
$sum = 12345;
echo \Yii::t('app', 'Balance: {0,number,,000,000000}', $sum);// 日本語翻訳: '差引残高: {0,number,,000,000000}'// 日本語出力: '差引残高: 000,012345'

カスタムフォーマットで使用される文字については、 ぉぃさ ぁぐぉ リファ
レンス17 の 【こばづっどちぬ ぐちぴぴづひの ぃとちひちっぴづひび】 のセクションに記述されています。
数値は常に翻訳先のロケールに従ってフォーマットされます。 つまり、ロケールを変更せずに、小数点や桁区切りを変更することは出来ません。 それらをカスタマイズしたい場合は べどどぜど〱〸のぜうはひねちぴぴづひ〺〺
ちびいづっどねちぬ〨〩 や べどどぜど〱〸のぜうはひねちぴぴづひ〺〺ちびぃふひひづのっべ〨〩 を使うことが出来ます。
日付パラメータ値は日付としてフォーマットされます。例えば、

echo \Yii::t('app', 'Today is {0,date}', time());// 日本語翻訳: '今日は {0,date} です。'// 日本語出力: '今日は 2015/01/07 です。'

オプションのパラメータとして、short、medium、long、そして full のスタ
イルを指定することが出来ます。
echo \Yii::t('app', 'Today is {0,date,short}', time());// 日本語翻訳: '今日は {0,date,short} です。'// 日本語出力: '今日は 2015/01/07 です。'
17
https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classDecimalFormat.html

〱〴〮〴〮 国際化〵〹〱

日付の値をフォーマットするカスタム・パターンを指定することも出来ます。
echo \Yii::t('app', 'Today is {0,date,yyyy-MM-dd}', time());// 日本語翻訳: '今日は {0,date,yyyy-MM-dd} です。'// 日本語出力: '今日は 2015-01-07 です。'

書式のリファレンス18 〮時刻

パラメータ値は時刻としてフォーマットされます。例えば、

echo \Yii::t('app', 'It is {0,time}', time());// 日本語翻訳: '現在 {0,time} です。'// 日本語出力: '現在 22:37:47 です。'

オプションのパラメータとして、short、medium、long、そして full のスタ
イルを指定することが出来ます。
echo \Yii::t('app', 'It is {0,time,short}', time());// 日本語翻訳: '現在 {0,time,short} です。'// 日本語出力: '現在 22:37 です。'

時刻の値をフォーマットするカスタム・パターンを指定することも出来ます。
echo \Yii::t('app', 'It is {0,date,HH:mm}', time());// 日本語翻訳: '現在 {0,time,HH:mm} です。'// 日本語出力: '現在 22:37 です。'

書式のリファレンス19 〮綴り パラメータ値は数値として取り扱われ、綴りとしてフォーマット
されます。例えば、// 出力例 : "42 is spelled as forty-two"echo \Yii::t('app', '{n,number} is spelled as {n,spellout}', ['n' => 42]);// 日本語翻訳: '{n,number} は、文字で綴ると {n,spellout} です。'// 日本語出力: '42 は、文字で綴ると 四十二 です。'

デフォルトでは、数値は基数として綴られます。それを変更することは可能です。
https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_
1SimpleDateFormat.html#details
19
https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_
1SimpleDateFormat.html#details
18

〵〹〲

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック// 出力例 : "I am forty-seventh agent"echo \Yii::t('app', 'I am {n,spellout,%spellout-ordinal} agent', ['n' =>47]);// 日本語翻訳: '私は{n,spellout,%spellout-ordinal}の工作員です。'// 日本語出力: '私は第四十七の工作員です。'

だびばづぬぬはふぴ〬〧 と だ
あなたが使用しているロケールで利用可能なオプションのリストについては、 とぴぴばび〺〯〯どのぴぬ〮ひねっひづちぴどぶづ〮ひふ〯20 の 【ぎふねぢづひどので びっとづねちび〬 こばづぬぬはふぴ】
を参照してください。
序数 パラメータ値は数値として取り扱われ、順序を表す文字列としてフォーマットされます。例えば、// 出力: "You are the 42nd visitor here!"echo \Yii::t('app', 'You are the {n,ordinal} visitor here!', ['n' => 42]);

序数については、スペイン語などの言語では、さらに多くのフォーマッ
トがサポートされています。
// 出力: "471ª"
echo \Yii::t('app', '{n,ordinal,%digits-ordinal-feminine}', ['n' => 471]);

だはひつどのちぬ〬〧 と だ
あなたが使用しているロケールで利用可能なオプションのリストについては、 とぴぴばび〺〯〯どのぴぬ〮ひねっひづちぴどぶづ〮ひふ〯21 の 【ぎふねぢづひどので びっとづねちび〬 くひつどのちぬ】 を参照してください。
補足〺 上記のソース・メッセージを、プレースホルダのス
タイルを守って日本語に翻訳すると、〧あなたはこのサイトのほの〬はひつどのちぬぽの訪問者です〧 となります。 しかし、その出力結
果は、〧あなたはこのサイトの第〴〲の訪問者です〧 となり、意味は通じますが、日本語としては若干不自然なものになります。
プレースホルダのスタイル自体も、翻訳の対象として、より適切なものに変更することが可能であることに注意してください。
この場合も、〧あなたはこのサイトのほの〬ばぬふひちぬ〬〽〱ほ最初ぽ はぴとづひほ〣番
目ぽぽの訪問者です〧 のように翻訳するほうが適切でしょう。
20
21

https://intl.rmcreative.ru/
https://intl.rmcreative.ru/〱〴〮〴〮 国際化〵〹〳

継続時間 パラメータ値は秒数として取り扱われ、継続時間を表す文字
列としてフォーマットされます。例えば、// 出力: "You are here for 47 sec. already!"echo \Yii::t('app', 'You are here for {n,duration} already!', ['n' => 47]);

継続時間については、さらに多くのフォーマットがサポートされています。
// 出力: '130:53:47'
echo \Yii::t('app', '{n,duration,%in-numerals}', ['n' => 471227]);

だつふひちぴどはの〬〧 と だ
あなたが使用しているロケールで利用可能なオプションのリストについては、 とぴぴばび〺〯〯どのぴぬ〮ひねっひづちぴどぶづ〮ひふ〯22 の 【ぎふねぢづひどので びっとづねちび〬 いふひちぴどはの】
を参照してください。
補足〺 このソース・メッセージを だあなたはこのサイトに既にほの〬つふひちぴどはのぽの間滞在しています〧 と翻訳した場合の出力結
果は、〧あなたはこのサイトに既に〴〷の間滞在しています〧 となります。 これも、プレースホルダのスタイルも含めて全体を翻訳し直す方が良いでしょう。 どうも、ぉぃさ ライブラリ
は、なちたおぐ の数値関連の書式指定においては、割と貧弱な実装にとどまっている印象です。
複数形 言語によって、複数形の語形変化はさまざまに異なります。すどど
は、さまざまな形式の複数形語形変化に対応したメッセージ翻訳のための便利な方法を提供しています。 それは、非常に複雑な規則に対しても、十分に機能するものです。 語形変化の規則を直接に処理する代りに、特定の状況における語形変化した言葉の翻訳を提供するだけで十分です。
// $n = 0 の場合の出力: "There are no cats!"// $n = 1 の場合の出力: "There is one cat!"// $n = 42 の場合の出: "There are 42 cats!"
echo \Yii::t('app', 'There {n,plural,=0{are no cats} =1{is one cat}other{are # cats}}!', ['n' => $n]);

上記の複数形規則の引数において、= はぴったりその値であることを意味します。従って、=0 はぴったりゼロ、=1 はぴったり 〱 を表します。 otherはそれ以外の数を表します。# は ターゲット言語に従ってフォーマット
された n の値によって置き換えられます。
複数形の規則が非常に複雑な言語もあります。 例えば、次のロシア語の例では、=1 が n = 1 にぴったりと一致するのに対して、one が 21 や 101などに一致します。
22https://intl.rmcreative.ru/〵〹〴

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピックЗдесь {n,plural,=0{котов нет} =1{есть один кот} one{# кот} few{# кота}many{# котов} other{# кота}}!

これら other、few、many などの特別な引数の名前は言語によって異なります。 特定のロケールに対してどんな引数を指定すべきかを学ぶためには、とぴぴばび〺〯〯どのぴぬ〮ひねっひづちぴどぶづ〮ひふ〯23 の 【ぐぬふひちぬ げふぬづび〬 ぃちひつどのちぬ】 を参照してください。 あるいは、その代りに、ふのどっはつづ〮はひで の規則のリファレンス24 を参照することも出来ます。
補足〺 上記のロシア語のメッセージのサンプルは、主として翻訳メッセージとして使用されるものです。 アプリケーションの ソース言語 を ru-RU にしてロシア語から他の言語に翻訳するという設定にしない限り、オリジナルのメッセージとしては使用されることはありません。
Yii::t() の呼び出しにおいて、オリジナルのメッセージに対する翻訳が見つからない場合は、 ソース言語 の複数形規則がオ
リジナルのメッセージに対して適用されます。
文字列が以下のようなものである場合のために offset というパラメータがあります。
$likeCount = 2;
echo Yii::t('app', 'You {likeCount,plural,
offset: 1=0{did not like this}=1{liked this}one{and one other person liked this}other{and # others liked this}}', ['likeCount' => $likeCount]);// 出力: 'You and one other person liked this'補足〺 上記のソース・メッセージの日本語翻訳は以下のようなものになります。
だ猫はほの〬 ばぬふひちぬ〬 〽〰ほいませんぽ はぴとづひほ〣匹いますぽぽ。〧
日本語では単数形と複数形を区別しませんので、たいていの場合、=0 と other を指定するだけで事足ります。 横着をして、{n, plural, ...} を {n, number} に置き換えても、多分、大きな問題は生じないでしょう。
23
24

https://intl.rmcreative.ru/
https://cldr.unicode.org/index/cldr-spec/plural-rules〱〴〮〴〮 国際化〵〹〵

序数選択肢 パラメータのタイプとして selectordinal を使うと、翻訳先
ロケールの言語規則に基づいて序数のための文字列を選択することが出来ます。
$n = 3;echo Yii::t('app', 'You are the {n,selectordinal,one{#st} two{#nd} few{#rd}other{#th}} visitor', ['n' => $n]);// 英語の出力// You are the 3rd visitor// ロシア語の翻訳'You are the {n,selectordinal,one{#st} two{#nd} few{#rd} other{#th}}visitor' => 'Вы {n, selectordinal, other{#-й}} посетитель',// ロシア語の出力// Вы 3-й посетитель

フォーマットは複数形で使われるものと非常に近いものです。 特定のロケールに対してどんな引数を指定すべきかを学ぶためには、とぴぴばび〺〯〯どのぴぬ〮ひねっひづちぴどぶづ〮ひふ〯25の 【ぐぬふひちぬ げふぬづび〬 くひつどのちぬ】 を参照してください。 あるいは、その代りに、ふのどっはつづ〮はひで の規則のリファレンス26 を参照することも出来ます。
選択肢 パラメータのタイプとして select を使うと、パラメータの値に基づいて表現を選択することが出来ます。例えば、// 出力: "Snoopy is a dog and it loves Yii!"echo \Yii::t('app', '{name} is a {gender} and {gender,select,female{she}male{he} other{it}} loves Yii!', ['name' => 'Snoopy','gender' => 'dog',]);

上記の式の中で、female と male が gender が取り得る値であり、other がそれらに一致しない値を処理します。 それぞれの取り得る値の後には、波括弧で囲んで対応する表現を指定します。
補足〺 日本語翻訳〺 だほのちねづぽ は ほでづのつづひぽ であり、ほでづのつづひ〬びづぬづっぴ〬てづねちぬづほ彼
女ぽ ねちぬづほ彼ぽ はぴとづひほそれぽぽは すどど を愛しています。〧
日本語出力〺 だこのははばべ は つはで であり、それは すどど を愛しています。〧
デフォルトのメッセージ・ソースを指定する構成されたカテゴリのどれにもマッチしないカテゴリのためのフォールバックとして使用される、デフォルトのメッセージ・ソースを指定する
https://intl.rmcreative.ru/
https://unicode-org.github.io/cldr-staging/charts/37/supplemental/
language_plural_rules.html
25
26

〵〹〶

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピックことが出来ます。 これは、ワイルドカードのカテゴリ * を構成することによって可能になります。 そうするためには、アプリケーションの構成
情報に次のように追加します。
// i18n コンポーネントを構成する'i18n' => ['translations' => ['*' => ['class' => 'yii\i18n\PhpMessageSource'
],
],
],

こうすることで、個別に構成することなくカテゴリを使うことが可能になり、すどど 〱〮〱 の振る舞いと同じになります。 カテゴリのメッセージは、
デフォルトの翻訳の basePath すなわち @app/messages の下にあるファイル
から読み込まれます。
echo Yii::t('not_specified_category', 'message from unspecified category');

この場合、メッセージは @app/messages/<LanguageCode>/not_specified_category.php
から読み込まれます。
モジュールのメッセージを翻訳する
モジュール用のメッセージを翻訳したいけれども、全てのメッセージに対して一つの翻訳ファイルを使うことは避けたい、という場合には、次のようにすることが出来ます。
<?php
namespace app\modules\users;
use Yii;
class Module extends \yii\base\Module{
public $controllerNamespace = 'app\modules\users\controllers';
public function init(){
parent::init();$this->registerTranslations();}
public function registerTranslations(){
Yii::$app->i18n->translations['modules/users/*'] = ['class' => 'yii\i18n\PhpMessageSource','sourceLanguage' => 'en-US',〱〴〮〴〮 国際化

}

];

〵〹〷

'basePath' => '@app/modules/users/messages','fileMap' => ['modules/users/validation' => 'validation.php','modules/users/form' => 'form.php',...
],

public static function t($category, $message, $params = [], $language =null){
return Yii::t('modules/users/' . $category, $message, $params,$language);}}

上記の例では、マッチングのためにワイルドカードを使い、次に必要なファイルごとに各カテゴリをフィルタリングしています。 fileMap を使わずに、カテゴリを同じ名前のファイルにマップする規約を使って済ませることも出来ます。 以上のようにすれば、直接に Module::t('validation','your custom validation message') や Module::t('form', 'some form label') な
どを使用することが出来ます。
ウィジェットのメッセージを翻訳する
モジュールに適用できる同じ規則をウィジェットにも適用することが出来ます。例えば、<?php
namespace app\widgets\menu;
use yii\base\Widget;use Yii;
class Menu extends Widget{
public function init(){
parent::init();$this->registerTranslations();}
public function registerTranslations(){$i18n = Yii::$app->i18n;$i18n->translations['widgets/menu/*'] = ['class' => 'yii\i18n\PhpMessageSource','sourceLanguage' => 'en-US',〵〹〸

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック}];'basePath' => '@app/widgets/menu/messages','fileMap' => ['widgets/menu/messages' => 'messages.php',],

public function run(){echo $this->render('index');}public static function t($category, $message, $params = [], $language =null){
return Yii::t('widgets/menu/' . $category, $message, $params,$language);}}
fileMap を使わずに、カテゴリを同じ名前のファイルにマップする規約を使って済ませることも出来ます。 これで、直接に Menu::t('messages', 'new
messages {messages}', ['{messages}' => 10]) を使用することが出来ます。
補足〺 ウィジェットのためには ど〱〸の ビューも使うことが出来ます。コントローラのための同じ規則がウィジェットにも適用されます。
フレームワーク・メッセージを翻訳する
すどど には、検証エラーとその他いくつかの文字列に対するデフォルトの翻訳メッセージが付属しています。これらのメッセージは、全て だべどど〧 というカテゴリの中にあります。 場合によっては、あなたのアプリケーショ
ンのために、デフォルトのフレームワーク・メッセージの翻訳を修正したいことがあるでしょう。 そうするためには、i18n アプリケーション・
コンポーネント を以下のように構成してください。
'i18n' => ['translations' => ['yii' => ['class' => 'yii\i18n\PhpMessageSource','sourceLanguage' => 'en-US','basePath' => '@app/messages'
],
],
],

これで、あなたの修正した翻訳を @app/messages/<language>/yii.php に置くことが出来ます。

〱〴〮〴〮 国際化〵〹〹

欠落している翻訳の処理
ソースに翻訳が欠落している場合でも、すどど はリクエストされたメッセー
ジの内容を表示します。 この振舞いは、原文のメッセージが正当かつ詳細なテキストである場合には、非常に好都合です。しかし、場合によっては、それだけでは十分ではありません。 リクエストされた翻訳がソースに欠落しているときに、何らかの特別な処理を実行する必要がある場合もあります。 そういう処理は、べどどぜど〱〸のぜきづびびちでづこはふひっづ の
ねどびびどのでごひちのびぬちぴどはの イベントを使うことによって達成できます。
例えば、全ての欠落している翻訳に何か目立つマークを付けて、ページに表示されたときに簡単に見つけられるようにしましょう。 最初にイベント・ハンドラをセットアップする必要があります。これはアプリ
ケーションの構成によって行うことが出来ます。
'components' => [// ...
'i18n' => ['translations' => ['app*' => ['class' => 'yii\i18n\PhpMessageSource','fileMap' => ['app' => 'app.php','app/error' => 'error.php',],'on missingTranslation' =>['app\components\TranslationEventHandler','handleMissingTranslation']
],
],
],
],

次に、私たち独自のイベント・ハンドラを実装する必要があります。
<?php
namespace app\components;
use yii\i18n\MissingTranslationEvent;class TranslationEventHandler{
public static function handleMissingTranslation(MissingTranslationEvent$event){$event->translatedMessage = "@MISSING:{$event->category}.{$event->message} FOR LANGUAGE {$event->language}
@";
}
}

〶〰〰

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

このイベント・ハンドラによって べどどぜど〱〸のぜきどびびどのでごひちのびぬちぴどはのぅぶづのぴ〺〺〤ぴひちのびぬちぴづつきづびびちでづ がセットされた場合は、それが翻訳結果として表示されます。
補足〺 全てのメッセージ・ソースは、欠落した翻訳をそれぞれ独自に処理します。 いくつかのメッセージ・ソースを使っていて、それらが同じ方法で欠落した翻訳を取り扱うようにしたい場合は、対応するイベント・ハンドラを全てのメッセー
ジ・ソースそれぞれに割り当てなければなりません。
コマンドを使う
翻訳は ばとば ファイル、〮ばは ファイル、または つちぴちぢちびづ に保存することが出来ます。追加のオプションについてはそれぞれのクラスを参照してください。
まず最初に、構成情報ファイルを作成する必要があります。 どこに保存したいかを決めて、次のコマンドを発行してください。
./yii message/config-template path/to/config.php

作成されたファイルを開いて、あなたの要求に合わせてパラメータを修正します。特に、下記の項目に注意を払ってください。
• languages〺 あなたのアプリケーションが翻訳されるべき言語を表す
配列。
• messagePath〺 メッセージファイルを保存するパス。これは、アプリ
ケーションの構成情報で記述されている i18n の basePath と合致しなければなりません。
だ〮〯べどど ねづびびちでづ〯っはの〜で〧 コ マ ン ド を 使 っ て 、ぃがぉ 経 由 で 、 指 定 し た オ プ
ションを持つ設定ファイルを動的に生成することも可能です。 例え
ば、languages と messagePath のパラメータは、次のようにして設定することが出来ます。
./yii message/config --languages=de,ja --messagePath=messages
path/to/config.php

利用可能なオプションのリストを取得するためには、次のコマンドを実行します。
./yii help message/config

構成情報ファイルの編集が完了すれば、ついに、下記のコマンドを使ってメッセージを抽出することが出来ます。
./yii message path/to/config.php

また、オプションを指定して、抽出のパラメータを動的に変更することも出来ます。
これで、〨あなたがファイル・ベースの翻訳を選択していた場合は〩messagePath ディレクトリにファイルが出現します。

〱〴〮〴〮 国際化

14.4.4〶〰〱

ビューの翻訳

個々のテキスト・メッセージを翻訳する代りに、ビュー・スクリプト
全体を翻訳したい場合があるでしょう。 この目的を達するためには、
ビュー を翻訳して、 ターゲット言語と同じ名前のサブ ・ディレク ト
リに保存するだけで大丈夫です。 例えば、views/site/index.php というビューをターゲット言語 ru-RU に翻訳したい場合は、翻訳したビューを
views/site/ru-RU/index.php というファイルとして保存します。 このようにすると、べどどぜぢちびづぜざどづぷ〺〺ひづのつづひうどぬづ〨〩 メソッド、または、このメソッドを呼び出す他のメソッド 〨例えば べどどぜぢちびづぜぃはのぴひはぬぬづひ〺〺ひづのつづひ〨〩〩を呼んで views/site/index.php をレンダリングするたびに、 翻訳された
views/site/ru-RU/index.php が代りにレンダリングされるようになります。
補足〺 ターゲット言語 が ソース言語 と同じ場合は、 翻訳されたビューの有無にかかわらず、オリジナルのビューがレンダリングされます。

14.4.5

数値と日付の値を書式設定する

詳細は データのフォーマット のセクションを参照して下さい。

14.4.6

PHP 環境をセットアップする

すどど は 、べどどぜど〱〸のぜうはひねちぴぴづひ ク ラ ス の 数 値 や 日 付 の 書 式 設 定 や 、べどどぜど〱〸のぜきづびびちでづうはひねちぴぴづひ を使うメッセージのフォーマッティングなど、ほとんどの国際化機能を提供するために ぐえぐ どのぴぬ 拡張27 を使います。
この二つのクラスは、intl がインストールされていない場合に備えて基本的な機能を提供するフォールバックを実装しています。 だだし、このフォールバックの実装は、英語がターゲット言語である場合にのみ十分に機能するものす。 従って、国際化機能が必要とされる場合は、intl を
インストールすることが強く推奨されます。
ぐえぐ どのぴぬ 拡張28 は、さまざまに異なる全てのロケールについて知識と書式の規則を提供する ぉぃさ ライブラリ29 に基礎を置いています。 ぉぃさのバージョンが異なると、日付や数値のフォーマットの結果も異なる場
合があります。 あなたのウェブ・サイトが全ての環境で同じ出力をすることを保証するためには、 全ての環境において同じバージョンの ぐえぐ
どのぴぬ 拡張 〨従って同じバージョンの ぉぃさ〩 をインストールすることが推奨されます。
どのバージョンの ぉぃさ が ぐえぐ によって使われているかを知るために、次のスクリプトを走らせることが出来ます。このスクリプトは、使用されている ぐえぐ と ぉぃさ のバージョンを出力します。
https://www.php.net/manual/ja/book.intl.php
https://www.php.net/manual/ja/book.intl.php
29
https://icu.unicode.org/
27
28

〶〰〲

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック<?phpecho "PHP: " . PHP_VERSION . "\n";echo "ICU: " . INTL_ICU_VERSION . "\n";echo "ICU Data: " . INTL_ICU_DATA_VERSION . "\n";さらに、バージョン 〴〹 以上の ぉぃさ を使用する事も推奨されます。そうすることによって、このドキュメントで説明されている全ての機能を使うことが出来るようになります。 例えば、〴〹 未満の ぉぃさ は、複数形規則における # プレースホルダをサポートしていません。 入手できる ぉぃさ
バージョン については、とぴぴばび〺〯〯どっふ〮ふのどっはつづ〮はひで〯つはぷのぬはちつ を参照してください。 バージョン番号の採番方式が 〴〮〸 リリースの後に変更されたことに注意してください 〨すなわち、ぉぃさ 〴〮〸、ぉぃさ 〴〹、ぉぃさ 〵〰、等々となっています〩。
これに加えて、ぉぃさ ライブラリとともに出荷されるタイム・ゾーン・
データベースの情報も古くなっている可能性があります。 タイム・ゾー
ン・データベースの更新に関する詳細は ぉぃさ マニュアル30 を参照してください。 出力の書式設定には ぉぃさ タイム・ゾーン・データベースが使用されますが、ぐえぐ によって使われるタイム・ゾーン・データベースも影響する可能性があります。 ぐえぐ のタイム・ゾーン・データベース
は、timezonedb ばづっぬ パッケージ31 の最新版をインストールすることによって更新することが出来ます。

14.5

メール送信

補足〺 このセクションはまだ執筆中です。
すどど は電子メールの作成と送信をサポートしています。 ただし、フレー
ムワークのコアが提供するのは、コンテント作成の機能と基本的なインタフェイスだけです。 実際のメール送信メカニズムはエクステンション
によって提供されなければなりません。 と言うのは、メール送信はプロジェクトが異なるごとに異なる実装が必要とされるでしょうし、通常、外部のサービスやライブラリに依存するものだからです。
ごく一般的な場合であれば、べどど〲〭びぷどてぴねちどぬづひ32 公式エクステンションを使用することが出来ます。

14.5.1

構成

メール・コンポーネントの構成は、あなたが選んだエクステンションに依存します。 一般的には、アプリケーションの構成情報は次のようなものになる筈です。
https://unicode-org.github.io/icu/userguide/datetime/timezone/#updating-the-time-zone-data
31
https://pecl.php.net/package/timezonedb
32
https://www.yiiframework.com/extension/yiisoft/yii2-swiftmailer
30〱〴〮〵〮 メール送信〶〰〳

return [//....
'components' => ['mailer' => ['class' => 'yii\swiftmailer\Mailer','useFileTransport' => false,'transport' => ['class' => 'Swift_SmtpTransport','encryption' => 'tls','host' => 'your_mail_server_host','port' => 'your_smtp_port','username' => 'your_username','password' => 'your_password',
],
],
],
];

14.5.2

基本的な使用方法

いったん mailer コンポーネントを構成すれば、次のコードを使って電子メールのメッセージを送信することが出来るようになります。
Yii::$app->mailer->compose()->setFrom('from@domain.com')->setTo('to@domain.com')->setSubject('メッセージの題')->setTextBody('プレーンテキストのコンテント')->setHtmlBody('<b>HTML のコンテント</b>')->send();上の例では、compose() メソッドでメール・メッセージのインスタンスを作成し、それに値を投入して送信しています。 必要であれば、このプロセスにもっと複雑なロジックを置くことも可能です。
$message = Yii::$app->mailer->compose();if (Yii::$app->user->isGuest) {$message->setFrom('from@domain.com');} else {$message->setFrom(Yii::$app->user->identity->email);}$message->setTo(Yii::$app->params['adminEmail'])->setSubject('メッセージの題')->setTextBody('プレーン・テキストのコンテント')->send();補足〺 すべての mailer エクステンションは、二つの主要なク
ラス、すなわち、Mailer と Message のセットとして提供されます。 Mailer は常に Message のクラス名と仕様を知っています。
Message オブジェクトのインスタンスを直接に作成しようとしてはいけません。常に compose() メソッドを使って作成してく
ださい。

〶〰〴

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

いくつかのメッセージを一度に送信することも出来ます。
$messages = [];foreach ($users as $user) {$messages[] = Yii::$app->mailer->compose()// ...
->setTo($user->email);}
Yii::$app->mailer->sendMultiple($messages);

メール・エクステンションの中には、単一のネットワーク・メッセージを使うなどして、この手法の恩恵を享受することが出来るものもいくつかあるでしょう。

14.5.3

メールのコンテントを作成する

すどど は実際のメール・メッセージを特別なビュー・ファイルによって作成することを許容しています。 デフォルトでは、それらのファイルは@app/mail というパスに配置されなければなりません。
以下はメール・ビュー・ファイルの内容の例です。
<?php
use yii\helpers\Html;
use yii\helpers\Url;/* @var $this \yii\web\View ビュー・コンポーネントのインスタンス *//* @var $message \yii\mail\BaseMessage 新しく作成されたメール・メッセージのイ
ンスタンス */?><h2>ワン・クリックで私たちのサイトのホームページを訪問することが出来ます</h2><? = Html::a('ホームページへ', Url::home('http')) ?>ビュー・ファイルによってメッセージを作成するためには、単に compose()
メソッドにビューの名前を渡すだけで十分です。
Yii::$app->mailer->compose('home-link') // ここでビューのレンダリング結果がメッセージのボディになります->setFrom('from@domain.com')->setTo('to@domain.com')->setSubject('メッセージの題')->send();ビュー・ファイルの中で利用できる追加のビュー・パラメータを compose()
メソッドに渡すことができます。
Yii::$app->mailer->compose('greetings', ['user' => Yii::$app->user->identity,'advertisement' => $adContent,]);〱〴〮〵〮 メール送信〶〰〵

えごきが と平文テキストのメッセージ・コンテントに違うビューを指定することが出来ます。
Yii::$app->mailer->compose(['html' => 'contact-html','text' => 'contact-text',]);

ビュー名をスカラーの文字列として渡した場合は、そのレンダリング結
果は えごきが ボディとして使われます。 そして、平文テキストのボディ
は えごきが のボディから全ての えごきが 要素を削除することによって作成されます。
ビューのレンダリング結果はレイアウトで包むことが出来ます。レイ
アウトは、べどどぜねちどぬぜあちびづきちどぬづひ〺〺〤とぴねぬがちべはふぴ と べどどぜねちどぬぜあちびづきちどぬづひ〺〺〤ぴづへぴがちべはふぴ を使ってセットアップすることが可能です。 レイアウト
は、通常のウェブ・アプリケーションのレイアウトと同じように働きます。 レイアウトは、メールの ぃここ スタイルや、その他の共有されるコン
テントをセットアップするために使うことが出来ます。
<?php
use yii\helpers\Html;/* @var $this \yii\web\View ビュー・コンポーネントのインスタンス *//* @var $message \yii\mail\MessageInterface 作成されるメッセージ *//* @var $content string メイン・ビューのレンダリング結果 */?><?php $this->beginPage() ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=<? =Yii::$app->charset ?> " /><style type="text/css">.heading {...}.list {...}.footer {...}</style><?php $this->head() ?></head><body><?php $this->beginBody() ?><? = $content ?><div class="footer">よろしくお願いします。<? = Yii::$app->name ?> チーム</div><?php $this->endBody() ?></body></html><?php $this->endPage() ?>〶〰〶ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

14.5.4

ファイルの添付attach() メソッド、attachContent() メソッドを使って、メッセージにファイルを添付することが出来ます。
$message = Yii::$app->mailer->compose();// ローカル・ファイル・システムからファイルを添付する$message->attach('/path/to/source/file.pdf');// 添付ファイルをその場で生成する$message->attachContent('添付される内容', ['fileName' => 'attach.txt','contentType' => 'text/plain']);14.5.5

画像の埋め込み

embed() メソッドを使って、メッセージのコンテントに画像を埋め込むことが出来ます。 このメソッドは添付ファイルの ぉい を返しますので、それを img タグで使わなければなりません。 このメソッドはビュー・ファ
イルによってメッセージのコンテントを作成するときに簡単に使うことが出来ます。
Yii::$app->mailer->compose('embed-email', ['imageFileName' =>'/path/to/image.jpg'])// ...
->send();そして、ビュー・ファイルの中では、次のコードを使うことが出来ます。
<img src="<?= $message->embed($imageFileName); ?>">

14.5.6

テストとデバッグ

開発者は、実際にどのようなメールがアプリケーションによって送信されたか、その内容はどのようなものであったか、等をチェックしなければならないことが多くあります。 すどど は、そのようなチェックが出来ることを yii\mail\BaseMailer::useFileTransport によって保証しています。
このオプションを有効にすると、メールのメッセージ・データが、通常のように送信される代りに、ローカル・ファイルに強制的に保存されます。 ファイルは、yii\mail\BaseMailer::fileTransportPath、デフォルトでは@runtime/mail の下に保存されます。
補足〺 メッセージをファイルに保存するか、実際の受信者に送信するか、どちらかを選ぶことが出来ますが、両方を同時に実行することは出来ません。

〱〴〮〶〮 パフォーマンス・チューニング

〶〰〷メール・メッセージのファイルは通常のテキストエディタで開くことが出来ますので、実際のメッセージ・ヘッダやコンテントなどを閲覧することが出来ます。 このメカニズムは、アプリケーションのデバッグや単体テストを実行する際に、真価を発揮するでしょう。
補足〺 メール・メッセージのファイルの内容は \yii\mail\MessageInterface::toString()
によって作成されますので、 あなたのアプリケーションで使用している実際のメール・エクステンションに依存したものになります。

14.5.7

あなた自身のメール・ソリューションを作成する

あなた自身のカスタム・メール・ソリューションを作成するためには、
二つのクラスを作成する必要があります。 すなわち、一つは Mailer であり、もう一つは Message です。 yii\mail\BaseMailer と yii\mail\BaseMessage
をあなたのソリューションの基底クラスとして使うことが出来ます。
これらのクラスが、このガイドで説明された基本的なロジックを既に持っています。しかし、それを使用することは強制されていません。
yii\mail\MailerInterface と yii\mail\MessageInterface のインタフェイスを実装すれば十分です。 そして、あなたのソリューションをビルドするために、全ての抽象メソッドを実装しなければなりません。

14.6

パフォーマンス・チューニング

あなたのウェブ・アプリケーションのパフォーマンスに影響を及ぼす要因は数多くあります。 環境の要因もありますし、あなたのコードに関係する要因もあります。また、すどど そのものに関係する要因もあります。 このセクションでは要因のほとんどを列挙して、どのようにそれらを修正すればあなたのアプリケーションのパフォーマンスを向上させることが出来るかを説明します。

14.6.1

PHP 環境を最適化する

ぐえぐ 環境を正しく構成することは非常に重要です。最大のパフォーマンスを得るためには、• 最新の安定した ぐえぐ バージョンを使うこと。使用する ぐえぐ のメジャー・リリースを上げると、顕著なパフォーマンスの改善がもた
らされることがあります。
• くばっちっとづ33 〨ぐえぐ 〵〮〵 以降〩 または ぁぐぃ34 〨ぐえぐ 〵〮〴〩 を使って、 バ
イト・コード・キャッシュを有効にすること。 バイト・コード・キャッシュによって、リクエストが入ってくるたびに ぐえぐ スクリ
33
34

https://www.php.net/manual/ja/book.opcache.php
https://www.php.net/manual/ja/book.apcu.php〶〰〸ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック
プトを解析してインクルードする時間の浪費を避けることが出来ます。
• realpath() キャッシュをチューニングする35 〮14.6.2デバッグ・モードを無効にする

本番環境でアプリケーションを実行するときには、デバッグ・モードを無効にしなければなりません。 すどど は、YII_DEBUG という名前の定数の値を使って、デバッグ・モードを有効にすべきか否かを示します。 デバッ
グ・モードが有効になっているときは、すどど はデバッグ情報の生成と記録のために時間を余計に費やします。
エントリ・スクリプト の冒頭に次のコード行を置くことによってデバッグ・モードを無効にすることが出来ます。
defined('YII_DEBUG') or define('YII_DEBUG', false);

情報〺 YII_DEBUG のデフォルト値は false です。 従って、アプ
リケーション・コードの他のどこかでこのデフォルト値を変更していないと確信できるなら、単に上記の行を削除してデバッグ・モードを無効にしても構いません。

14.6.3キャッシュのテクニックを使う

さまざまなキャッシュのテクニックを使うと、あなたのアプリケーショ
ンのパフォーマンスを目に見えて改善することが出来ます。 たとえば、
あなたのアプリケーションが きちひにつはぷの 形式のテキスト入力をユーザに許可している場合、解析済みの きちひにつはぷの のコンテントをキャッシュす
ることを考慮してください。 そうすれば、リクエストごとに毎回同じ
きちひにつはぷの テキストの解析を繰り返すことを回避できるでしょう。 すどどによって提供されているキャッシュのサポートについて学ぶためにはキャッシュ のセクションを参照してください。

14.6.4

スキーマ・キャッシュを有効にする

スキーマ・キャッシュは、アクティブ・レコード を使おうとする場合には、いつでも有効にすべき特別なキャッシュ機能です。 ご存じのように、アクティブ・レコードは、賢いことに、あなたがわざわざ記述しな
くても、 いあ テーブルに関するスキーマ情報 〨カラムの名前、カラムのタ
イプ、外部キー制約など〩 を自動的に検出します。 アクティブ・レコー
ドはこの情報を取得するために追加の こけが クエリを実行しています。 ス
キーマ・キャッシュを有効にすると、取得されたスキーマ情報はキャッシュに保存されて将来のクエリで再利用されるようになります。
スキーマ・キャッシュを有効にするためには、アプリケーションの構成情報 の中で、 cache アプリケーション・コンポーネント にスキーマ情35

https://github.com/samdark/realpath_cache_tuner

〱〴〮〶〮 パフォーマンス・チューニング

〶〰〹

報を保存するように構成し、べどどぜつぢぜぃはののづっぴどはの〺〺〤づのちぢぬづこっとづねちぃちっとづを true に設定します。
return [// ...
'components' => [// ...
'cache' => ['class' => 'yii\caching\FileCache',],'db' => ['class' => 'yii\db\Connection','dsn' => 'mysql:host=localhost;dbname=mydatabase','username' => 'root','password' => '','enableSchemaCache' => true,// スキーマ・キャッシュの持続時間'schemaCacheDuration' => 3600,];],

14.6.5],// スキーマ情報を保存するのに使用されるキャッシュ・コンポーネントの名前'schemaCache' => 'cache',

アセットを結合して最小化する

複雑なウェブ・ページでは、多数の ぃここ や おちぶちこっひどばぴ のアセット・ファ
イルをインクルードすることがよくあります。 えごごぐ リクエストの回数、および、これらのアセットの全体としてのダウンロード・サイズを削減するために、アセットを単一のファイルに結合して、それを圧縮することを考慮すべきです。 これによって、ページのロードにかかる時間とサーバの負荷を大きく削減することが出来ます。 詳細については、アセット のセクションを参照してください。

14.6.6

セッションのストレージを最適化する

デフォルトでは、セッションのデータはファイルに保存されます。 これは、session_write_close() が呼ばれる 〨すどど では Yii::$app->session->close()
によって呼び出されます〩 か、あるいはリクエストの処理が終了して、セッションが閉じられる時点まで、ファイルが開かれるのをロックするという実装になっています。 セッション・ファイルがロックされている間は、同じセッションを使用しようとする全てのリクエストはブロックされ、最初のリクエストがセッション・ファイルを解放するのを待たなければなりません。 開発時はこれでも構いません。おそらく、小さなプ
ロジェクトでも、これで大丈夫でしょう。 しかし、大量のリクエストを並列処理するとなると、データベースのような、もっと洗練されたスト〶〱〰

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

レージを使う方が良いでしょう。 すどど はさまざまなセッション・ストレー
ジのサポートを内蔵しています。 これらのストレージは、アプリケー
ションの構成情報 の中で session コンポーネントを次のように構成することによって使用することが出来ます。
return [// ...
'components' => ['session' => ['class' => 'yii\web\DbSession',// デフォルトの 'db' 以外の DB コンポーネントを使用したい場合は// 以下を設定する// 'db' => 'mydb',

];

],

],

// デフォルトの session テーブルをオーバーライドするためには以下を設定する// 'sessionTable' => 'my_session',

上記の構成は、セッション・データの保存にデータベース・テーブルを使用するものです。 デフォルトでは、db アプリケーション・コンポー
ネントをデータベース接続として使用し、セッション・データを session
テーブルに保存します。 ただし、前もって session テーブルを次のように作っておく必要があります。
CREATE TABLE session (id CHAR(40) NOT NULL PRIMARY KEY,
expire INTEGER,
data BLOB)

べどどぜぷづぢぜぃちっとづこづびびどはの を使って、セッションをキャッシュに保存することも出来ます。 理論上、サポートされている キャッシュ・ストレージ のどれでも使うことが出来ます。 ただし、キャッシュ・ストレージの中には、容量の上限に達したときにキャッシュされたデータをフラッシュするものがあることに注意してください。 この理由により、主として容量の上限が無い種類のキャッシュ・ストレージを使用すべきです。
あなたのサーバに げづつどび36 がある場合は、べどどぜひづつどびぜこづびびどはの によって ひづつどび をセッション・ストレージとして使用することを強く推奨します。

14.6.7

データベースを最適化する

いあ クエリの実行とデータベースからのデータ取得がウェブ・アプリケー
ションのパフォーマンスの主たるボトルネックになることがよくありま36

https://redis.io/〱〴〮〶〮 パフォーマンス・チューニング

〶〱〱す。 データ・キャッシュ の使用によってパフォーマンスの劣化を緩和することは出来ますが、問題を完全に解決することは出来ません。 データ
ベースが膨大なデータを抱えている場合、キャッシュされたデータが無効化されたときに最新のデータを取得するためのコストは、 データベー
スとクエリが適切に設計されていないと、法外なものになり得ます。
いあ クエリのパフォーマンスを向上させるための一般的なテクニック
は、フィルタの対象になるテーブル・カラムにインデックスを作成することです。 例えば、username によってユーザのレコードを検索する必要があるなら、username に対してインデックスを作成するべきです。 ただ
し、インデックスを付けると こぅがぅぃご クエリを非常に速くすることが出来る代りに、ぉぎこぅげご、さぐいぁごぅ、または いぅがごぅ のクエリが遅くなることに注意してください。
複雑な いあ クエリについては、クエリの解析と準備の時間を節約する
ために、データベース・ビューを作成することが推奨されます。
最後にもう一つ大事なことですが、こぅがぅぃご クエリで がぉきぉご を使ってください。 こうすることで、大量のデータが返されて、ぐえぐ のために確保されたメモリを使い尽くすということがなくなります。

14.6.8プレーンな配列を使う

アクティブ・レコード は非常に使い勝手のよいものですが、データベー
スから大量のデータを取得する必要がある場合は、プレーンな配列を使うほどには効率的ではありません。 そういう場合は、アクティブ・レ
コードを使ってデータを取得する際に asArray() を呼んで、 取得したデー
タがかさばるアクティブ・レコードのオブジェクトではなく配列として表現されるようにすることを考慮するのが良いでしょう。 例えば、
class PostController extends Controller{
public function actionIndex(){$posts = Post::find()->limit(100)->asArray()->all();}}

return $this->render('index', ['posts' => $posts]);

上記において、$posts は、テーブル行の配列としてデータを代入されることになります。各行はプレーンな配列になります。 $i 番目の行の title
カラムにアクセスするためには、$posts[$i]['title'] という式を使うことが出来ます。
クエリを構築するのに いぁく を使って、データをプレーンな配列に取得することも出来ます。

〶〱〲

14.6.9ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

Composer オートローダを最適化する

ぃはねばはびづひ のオートローダは、ほとんどのサードパーティのクラス・ファ
イルをインクルードするのに使われますので、 次のコマンドを実行してぃはねばはびづひ のオートローダを最適化することを考慮すべきです。
composer dumpautoload -o

さらに加えて、 ちふぴとはひどぴちぴどぶづ っぬちびび ねちばび37 および ぁぐぃふ っちっとづ38 の使用を検討して下さい。 ただし、この二つの最適化があなたの特定のケースに適切である場合もあれば、そうでない場合もあります。

14.6.10

オフラインでデータを処理する

リクエストが何らかのリソース集約的な操作を必要とするものである場
合は、そういう操作が終るまでユーザを待たせずに、 オフラインモード
で操作を実行する方策を考えるべきです。
オフラインでデータを処理するための方法が二つあります。すなわ
ち、プルとプッシュです。
プルの方法では、リクエストが何らかの複雑な操作を必要とするたびに、タスクを作成してデータベースなどの持続的ストレージに保存します。 そうしておいて、別の独立したプロセス 〨例えばクロンジョブ〩 を使い、タスクを引き出して処理します。 この方法は、実装は容易ですが、いくつかの欠点があります。 例えば、タスクのプロセスはストレージから定期的にタスクを引き出さなければなりません。 引き出す間隔が長す
ぎると、タスクの処理に大きな遅延が生じます。しかし、間隔が短すぎると、オーバーヘッドが大きくなります。
プッシュの方法では、タスクを管理するのにメッセージ・キュー 〨例
えば、げちぢぢどぴきけ、ぁっぴどぶづきけ、ぁねちぺはの こけこ など〩 を使用します。 新しいタスクがキューに入れられるたびに、タスクを処理するプロセスが起動されたり通知を受けたりして、タスク処理がトリガされます。

14.6.11

パフォーマンス・プロファイリング

あなたは、あなたのコードをプロファイルして、パフォーマンスのボト
ルネックを発見し、それに応じた適切な手段を講じるべきです。 次のプ
ロファイリング・ツールが役に立つでしょう。
• すどど のデバッグ・ツールバーとデバッガ39• あぬちっに〜ひづ40
https://getcomposer.org/doc/articles/autoloader-optimization.md#
optimization-level-2-a-authoritative-class-maps
38
https://getcomposer.org/doc/articles/autoloader-optimization.md#
optimization-level-2-b-apcu-cache
39
https://github.com/yiisoft/yii2-debug/blob/master/docs/guide-ja/README.
md
40
https://blackfire.io/37〱〴〮〷〮 共有ホスティング環境〶〱〳• じえぐひはて41• じいづぢふで プロファイラ42

14.6.12

アプリケーションをスケーラブルなものにする覚悟を決める

何をやっても助けにならないときは、あなたのアプリケーションをス
ケーラブルにすることを試みましょう。良い導入記事が ぃはの〜でふひどので ち すどど〲 ぁばばぬどっちぴどはの てはひ ちの ぁふぴはびっちぬどので こぴちっに 〨すどど 〲 アプリケーションを自動ス
ケール環境のために構成する〩43 の中で提供されています。

14.7

共有ホスティング環境

共有ホスティング環境では、たいてい、構成やディレクトリ構造について大きな制約があります。 それでも、ほとんどの場合、少し調整をすれ
ば、すどど 〲〮〰 を共有ホスティング環境で走らせることが可能です。

14.7.1

ベーシック・プロジェクト・テンプレートを配備する

通例、共有ホスティング環境では、一つのウェブ・ルートしかありませんので、可能であればベーシック・プロジェクト・テンプレートを使用して下さい。 まず、すどど をインストールする のセクションを参照して、
プロジェクト・テンプレートをローカル環境にインストールします。 そして、ローカル環境でアプリケーションが動くようにした後で、共有ホスティング環境でホスト出来るようにいくつかの修正を行います。
ウェブ・ルートの名前を変える
うごぐ またはその他の手段であなたの共有ホストに接続します。おそら
く、下記のようなディレクトリが見えるでしょう。
configlogs
www

上記で www はウェブ・サーバのウェブ・ルート・ディレクトリです。
別の名前かもしれません。よくある名前は、www、htdocs、public_html です。
私たちのベーシック・プロジェクト・テンプレートではウェブ・ルー
トの名前は web になっています。 あなたのウェブ・サーバにアップロー
ドする前に、ローカルのウェブ・ルートの名前をあなたのサーバに適合するように変更します。 すなわち、web から www や public_html など、何であれ、あなたの共有ホストのウェブ・ルートの名前に変更します。
https://www.php.net/manual/ja/book.xhprof.php
https://xdebug.org/docs/profiler
43
https://github.com/samdark/yii2-cookbook/blob/master/book/scaling.md
41
42

〶〱〴

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

うごぐ ルート・ディレクトリは書き込み可能
ルート・レベルのディレクトリ、すなわち、config、logs、www があるディ
レクトリに対して書き込みが出来るのであれば、 assets、commands などをそのままルート・レベルのディレクトリにアップロードします。
ウェブ・サーバのための追加設定使用されているウェブ・サーバが ぁばちっとづ である場合は、次の内容を持つ.htaccess ファイルを web 〨または public_html など、要するに、index.php があるディレクトリ〩 に追加する必要があります。
Options +FollowSymLinks
IndexIgnore */*RewriteEngine on# ディレクトリかファイルが存在すれば、それを直接使う
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d# それ以外は、index.php にフォワードする
RewriteRule . index.php

のでどのへ の場合は、追加の構成ファイルは必要がない筈です。
必要条件をチェックする
すどど を走らせるためには、あなたのウェブ・サーバは すどど の必要条件を満たさなければなりません。最低限の必要条件は ぐえぐ 〵〮〴 です。 必要条
件をチェックするために、requirements.php をルート・ディレクトリから
ウェブ・ルート・ディレクトリにコピーして、 https://example.com/requirements.phpという さげが を使ってブラウザ経由で走らせます。後でファイルを削除す
るのを忘れないでください。

14.7.2

アドバンスト・プロジェクト・テンプレートを配備する

アドバンスト・プロジェクト・テンプレートを共有ホストに配備することは、ベーシック・プロジェクト・テンプレートを配備するのに比べると少しトリッキーにはなりますが、可能です。 アドバンスト・プロジェ
クト・テンプレートのドキュメント44 で説明されている指示に従って下さい。
44
https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide-ja/
topic-shared-hosting.md

〱〴〮〸〮 テンプレートエンジンを使う

14.8

〶〱〵

テンプレートエンジンを使う

デフォルトでは、すどど は ぐえぐ をテンプレート言語として使いますが、ごぷどで45
や こねちひぴべ46 などの他のレンダリング・エンジンをサポートするように
すどど を構成することが出来ます。
view コンポーネントがビューのレンダリングに責任を持っています。
このコンポーネントのビヘイビアを構成することによって、カスタム・テンプレート・エンジンを追加することが出来ます。
['components' => ['view' => ['class' => 'yii\web\View','renderers' => ['tpl' => ['class' => 'yii\smarty\ViewRenderer',//'cachePath' => '@runtime/Smarty/cache',],'twig' => ['class' => 'yii\twig\ViewRenderer','cachePath' => '@runtime/Twig/cache',// twig のオプションの配列'options' => ['auto_reload' => true,],'globals' => ['html' => '\yii\helpers\Html'],'uses' => ['yii\bootstrap'],],// ...
],],],]

上記のコードにおいては、こねちひぴべ と ごぷどで の両者がビュー・ファイルによって使用可能なものとして構成されています。 しかし、これらのエク
ステンションをプロジェクトで使うためには、composer.json ファイルも修正して、これらのエクステンションを含める必要があります。
"yiisoft/yii2-smarty": "~2.0.0","yiisoft/yii2-twig": "~2.0.0",

上のコードを composer.json の require セクションに追加します。変更をファイルに保存した後、コマンドラインで composer update --prefer-distを実行することによってエクステンションをインストールすることが出来ます。
具体的にテンプレート・エンジンを使用する方法については、それぞれのドキュメントで詳細を参照してください。
45
46

https://twig.symfony.com/
https://www.smarty.net/

〶〱〶ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック• ごぷどで ガイド47• こねちひぴべ ガイド48

14.9

サードパーティのコードを扱う

時々、すどど アプリケーションの中でサードパーティのコードを使用する必要があることがあります。 あるいは、サードパーティのシステムの中ですどど をライブラリとして使用したいこともあるでしょう。このセクション
では、こういう目的をどうやって達成するかを説明します。

14.9.1

Yii の中でサードパーティのライブラリを使う

すどど アプリケーションの中でサードパーティのライブラリを使うために主として必要なことは、 そのライブラリのクラスが適切にインクルードされること、または、オートロード可能であることを保証することです。
ぃはねばはびづひ パッケージを使う
多くのサードパーティ・ライブラリは ぃはねばはびづひ49 パッケージの形式でリリースされています。 そのようなライブラリは、次の二つの簡単なス
テップを踏むことによって、インストールすることが出来ます。
〱〮 アプリケーションの composer.json ファイルを修正して、どの ぃはね〭
ばはびづひ パッケージをインストールしたいかを指定する。
〲〮 composer install を実行して、指定したパッケージをインストールする。
インストールされた ぃはねばはびづひ パッケージ内のクラスは、ぃはねばはびづひ のオートローダを使ってオートロードすることが出来ます。 アプリケー
ションの エントリ・スクリプト に、 ぃはねばはびづひ のオートローダをインストールするための下記の行があることを確認してください。
// Composer のオートローダをインストール
require __DIR__ . '/../vendor/autoload.php';// Yii クラス・ファイルをインクルード
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';
https://www.yiiframework.com/extension/yiisoft/yii2-twig/doc/guide/
https://www.yiiframework.com/extension/yiisoft/yii2-smarty/doc/guide/49
https://getcomposer.org/
47
48

〱〴〮〹〮 サードパーティのコードを扱う〶〱〷

ダウンロードしたライブラリを使う
ライブラリが ぃはねばはびづひ パッケージとしてリリースされていない場合は、そのライブラリのインストールの指示に従ってインストールしなければなりません。 たいていの場合は、リリース・ファイルを手動でダウンロードし、BasePath/vendor ディレクトリの下に解凍する必要があります。
ここで BasePath は、アプリケーションの ぢちびづ ばちぴと を表すものです。
ライブラリがそれ自身のオートローダを持っている場合は、それをア
プリケーションの エントリ・スクリプト でインストールすることが出来ます。 複数のオートローダ・クラスの中で すどど のクラス・オートローダが優先されるように、 ライブラリのオートローダは Yii.php ファイルをインクルードする前にインストールすることを推奨します。
ライブラリがクラスオートローダを提供していない場合でも、クラスの命名規約が ぐこげ〭〴50 に従っている場合は、ライブラリのクラスをオー
トロードするのに すどど のクラス・オートローダを使うことが出来ます。
必要なことは、ライブラリのクラスによって使われている全てのルート
名前空間に対して ルート・エイリアス を宣言することだけです。 例えば、ライブラリを vendor/foo/bar ディレクトリの下にインストールしたとしましょう。 そしてライブラリのクラスは xyz ルート名前空間の下にあるとします。 この場合、アプリケーションの構成情報において、次のコードを含めれば良いのです。
['aliases' => ['@xyz' => '@vendor/foo/bar',],]

上記のどちらにも当てはまらない場合、おそらくそのライブラリは、クラス・ファイルを探して適切にインクルードするために、ぐえぐ の どのっぬふつづ
ばちぴと 設定に依存しているのでしょう。 この場合は、ぐえぐ どのっぬふつづ ばちぴと の設定に関するライブラリの指示に従うしかありません。
最悪の場合として、ライブラリが全てのクラス・ファイルを明示的にインクルードすることを要求している場合は、 次の方法を使ってクラスを必要に応じてインクルードすることが出来るようになります。
• ライブラリに含まれるクラスを特定する。
• アプリケーションの エントリ・スクリプト において、 クラスと対応するファイル・パスを Yii::$classMap としてリストアップする。
例えば、
Yii::$classMap['Class1'] = 'path/to/Class1.php';
Yii::$classMap['Class2'] = 'path/to/Class2.php';
50

https://www.php-fig.org/psr/psr-4/

〶〱〸ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

14.9.2

サードパーティのシステムで Yii を使う

すどど は数多くの優れた機能を提供していますので、サードパーティのシス
テム 〨例えば、しはひつぐひづびび、おははねぬち、または、他の ぐえぐ フレームワーク
を使って開発されるアプリケーション〩 を開発したり機能拡張したりするのをサポートするために すどど の機能のいくつかを使用したいことがあるでしょう。 例えば、べどどぜとづぬばづひびぜぁひひちべえづぬばづひ クラスや アクティブ・レ
コード をサードパーティのシステムで使いたいことがあるでしょう。 この目的を達するためには、主として、二つのステップを踏む必要があります。 すなわち、すどど のインストールと、すどど のブートストラップです。
サードパーティのシステムが ぃはねばはびづひ を使って依存を管理している
場合は、 単に下記のコマンドを実行すれば すどど をインストールすることが出来ます。
composer require yiisoft/yii2

データベース抽象レイヤなど、アセットに関係しない すどど の機能だけを使用したい場合は、 あはぷづひ および ぎぐき のパッケージのインストールを阻止する特別な っはねばはびづひ パッケージが必要になります。 詳細については っづぢづ〯ちびびづぴてひづづ〭べどど〲51 を参照して下さい。
ぃはねばはびづひ に関する更なる情報や、インストールの過程で出現しうる問題に対する解決方法については、 一般的な ぃはねばはびづひ によるインス
トール のセクションを参照してください。
そうでない場合は、すどど のリリースを ダウンロード52 して、 BasePath/vendor
ディレクトリに解凍してください。
次に、サードパーティのシステムのエントリ・スクリプトを修正します。次のコードをエントリ・スクリプトの先頭に追加してください。
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';$yiiConfig = require __DIR__ . '/../config/yii/web.php';
new yii\web\Application($yiiConfig); // ここで run() を呼ばない

ごらんのように、上記のコードは典型的な すどど アプリケーションの エン
トリ・スクリプト と非常に良く似ています。 唯一の違いは、アプリケー
ションのインスタンスが作成された後に run() メソッドが呼ばれない、という点です。 run() を呼ぶと すどど がリクエスト処理のワークフローを制御するようになりますが、 この場合はリクエストを処理する別のアプリ
ケーションが既に存在していますので、これは必要ではないからです。
すどど アプリケーションでの場合と同じように、サードパーティ・シス
テムが走っている環境に基づいて すどど のアプリケーション・インスタン
スを構成する必要があります。 例えば、アクティブ・レコード の機能を使うためには、サードパーティ・システムによって使用されている いあ
51
52

https://github.com/cebe/assetfree-yii2
https://www.yiiframework.com/download/〱〴〮〹〮 サードパーティのコードを扱う〶〱〹

接続の設定を使って db アプリケーション・コンポーネント を構成しなけ
ればなりません。
これで、すどど によって提供されているほとんどの機能を使うことが出来ます。 例えば、アクティブ・レコード・クラスを作成して、それを使ってデータベースを扱うことが出来ます。

14.9.3Yii 2 を Yii 1 とともに使う

あなたが すどど 〱 を前から使っている場合は、たぶん、稼働中の すどど 〱 アプ
リケーションを持っているでしょう。 アプリケーション全体を すどど 〲 で書き直す代りに、すどど 〲 でのみ利用できる機能を使ってアプリケーション
を機能拡張したいこともあるでしょう。 このことは、以下に述べるようにして、実現できます。
補足〺 すどど 〲 は ぐえぐ 〵〮〴 以上を必要とします。 あなたのサーバと既存のアプリケーションが ぐえぐ 〵〮〴 以上をサポートしていることを確認しなければなりません。
最初に、直前の項 で述べられている指示に従って、すどど 〲 を既存のアプリ
ケーションにインストールします。
次に、アプリケーションのエントリ・スクリプトを以下のように修正します。
// カスタマイズされた Yii クラスをインクルード (下記で説明)
require __DIR__ . '/../components/Yii.php';// Yii 2 アプリケーションの構成$yii2Config = require __DIR__ . '/../config/yii2/web.php';
new yii\web\Application($yii2Config); // ここで run() を呼ばない。yii2 app はサービス・ロケータとしてのみ使用される。
// Yii 1 アプリケーションの構成$yii1Config = require __DIR__ . '/../config/yii1/main.php';
Yii::createWebApplication($yii1Config)->run();

すどど 〱 と すどど 〲 の両者が Yii クラスを持っているため、二つを結合するカ
スタム・バージョンを作成する必要があります。 上記のコードでカスタマイズされた Yii クラス・ファイルをインクルードしていますが、これは下記のようにして作成することが出来ます。
$yii2path = '/path/to/yii2';
require $yii2path . '/BaseYii.php'; // Yii 2.x$yii1path = '/path/to/yii1';
require $yii1path . '/YiiBase.php'; // Yii 1.x
class Yii extends \yii\BaseYii{

〶〲〰

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック// YiiBase (1.x) のコードをここにコピー・ペースト}

spl_autoload_unregister(array('YiiBase','autoload'));spl_autoload_register(array('Yii','autoload'));Yii::$classMap = include($yii2path . '/classes.php');// Yii 2 オートローダを Yii 1 によって登録Yii::registerAutoloader(['yii\BaseYii', 'autoload']);// 依存注入コンテナを作成
Yii::$container = new yii\di\Container;

以上です。 これで、あなたのコードのどの部分においても、Yii::$app を使って すどど 〲 アプリケーション・インスタンスにアクセスすることが出来、Yii::app() によって すどど 〱 アプリケーション・インスタンスを取得することが出来ます。
echo get_class(Yii::app()); // 'CWebApplication' を出力
echo get_class(Yii::$app); // 'yii\web\Application' を出力

14.10

Yii をマイクロ・フレームワークとして使う

すどど はベーシック・テンプレートやアドバンスト・テンプレートに含まれる機能なしで使うことが簡単にできます。言葉を換えれば、すどど は既にマ
イクロ・フレームワークです。すどど を使うためにテンプレートによって提供されているディレクトリ構造を持つことは要求されていません。
このことは、アセットやビューなどの事前定義されたテンプレート・
コードを必要としない場合には、特に好都合です。そのような場合の一
つが おこくぎ ぁぐぉ です。以下に続くセクションで、どのようにしてそれを実現するかを示します。

14.10.1

Yii をインストールする

プロジェクト・ファイルのためのディレクトリを作成し、ワーキング・
ディレクトリをそのパスに変更します。例で使用されているコマンドはさぎぉじ ベースのものですが、同様のコマンドが しどのつはぷび にもあります。
mkdir micro-app
cd micro-app

補足〺 続けるためには ぃはねばはびづひ についての知識が多少必要です。ぃはねばはびづひ の使い方をまだ知らない場合は、時間を取って、ぃはねばはびづひ ぇふどつづ53 を読んでください。
micro-app ディレクトリの下に composer.json ファイルを作成し、あなたの好みのエディタを使って、下記を追加します。
53

https://getcomposer.org/doc/00-intro.md〱〴〮〱〰〮 すぉぉ をマイクロ・フレームワークとして使う
{

}

〶〲〱

"require": {"yiisoft/yii2": "~2.0.0"},"repositories": [{"type": "composer","url": "https://asset-packagist.org"}]

ファイルを保存して composer install コマンドを実行します。これによって、フレームワークがその全ての依存とともにインストールされます。

14.10.2

プロジェクトの構造を作成する

フレームワークをインストールしたら、次は、アプリケーションの エン
トリ・ポイント を作成します。エントリ・ポイントは、アプリケーショ
ンを開こうとしたときに、一番最初に実行されるファイルです。セキュリティ上の理由により、エントリ・ポイントを置くディレクトリは別にして、それをウェブ・ルートとします。
web ディレクトリを作成して、下記の内容を持つ index.php をそこに置
きます。
<?php
// 実運用サーバに配備するときは次の2行をコメント・アウトする
defined('YII_DEBUG') or define('YII_DEBUG', true);defined('YII_ENV') or define('YII_ENV', 'dev');
require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');$config = require __DIR__ . '/../config.php';(new yii\web\Application($config))->run();また config.php という名前のファイルを作成し、アプリケーションの全ての構成情報をそこに含ませます。
<?php
return ['id' => 'micro-app',// アプリケーションの basePath は `micro-app` ディレクトリになります'basePath' => __DIR__,// この名前空間からアプリケーションは全てのコントローラを探します'controllerNamespace' => 'micro\controllers',// 'micro' 名前空間からのクラスのオートロードを可能にするためにエイリアスを設定します'aliases' => ['@micro' => __DIR__,

〶〲〲

];

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック],

情報〺 構成情報を index.php ファイルに持つことも出来ます
が、別のファイルに持つことを推奨します。 そうすれば、後で示しているように、同じ構成情報をコンソール・アプリ
ケーションから使うことが出来ます。
これであなたのプロジェクトはコーディングの準備が出来ました。プ
ロジェクトのディレクトリ構造を決定するのは、名前空間に注意する限り、あなた次第です。

14.10.3

最初のコントローラを作成する

controllers ディレクトリを作成し、SiteController.php というファイルを追加します。 これが、パス情報を持たないリクエストを処理する、デフォルトのコントローラです。
<?php
namespace micro\controllers;
use yii\web\Controller;class SiteController extends Controller{
public function actionIndex(){
return 'こんにちは!';}}このコントローラに違う名前を使いたい場合は、名前を変更して べどど
ぜぢちびづぜぁばばぬどっちぴどはの〺〺〤つづてちふぬぴげはふぴづ をそれに応じて変更します。 例えば、DefaultController であれば、'defaultRoute' => 'default/index' と変更します。
この時点で、プロジェクトの構造は次のようになっています。
micro-app/|– composer.json|– config.php|– web/|– index.php|– controllers/|– SiteController.php

まだウェブ・サーバをセットアップしていない場合は、ウェブ・サーバの構成ファイル例 を参照すると良いでしょう。 もう一つのオプション
は、ぐえぐ の内蔵ウェブ・サーバを利用する yii serve コマンドを使うことです。 micro-app/ ディレクトリから、次のコマンドを実行します。

〱〴〮〱〰〮 すぉぉ をマイクロ・フレームワークとして使う〶〲〳

vendor/bin/yii serve --docroot=./web

アプリケーションの さげが をブラウザで開くと、SiteController::actionIndex()
で返された 【こんにちは〡】 という文字列が表示される筈です。
情報〺 私たちの例では、アプリケーションのデフォルトの名前
空間 app を micro に変更しています。 これは、あなたがその名前に縛られていないことを示すためです〨万一あなたが縛られていると思っている場合を考えて〩。 そして、コントローラの名前空間 を修正し、正しいエイリアスを設定しています。

14.10.4

REST API を作成する

私たちの 【マイクロ・フレームワーク】 の使い方を示すために、記事のための簡単な げぅこご ぁぐぉ を作成しましょう。 だ この ぁぐぉ が何らかのデータを提供するためには、まず、データベースが必要です。 データベース接続の構成をアプリケーション構成に追加します。
'components' => ['db' => ['class' => 'yii\db\Connection','dsn' => 'sqlite:@micro/database.sqlite',],],

情報〺 ここでは話を簡単にするために びぱぬどぴづ データベースを使用します。他のオプションについては データベースのガイドを参照してください。
次に、データベース・マイグレーション を作成して、記事のテーブルを作成します。 既に述べたように、独立した構成情報ファイルがあることを確認してください。 下記のコンソール・コマンドを実行するためには、それが必要です。 次のコマンドを実行すると、データベース・マイ
グレーション・ファイルが作成され、そして、マイグレーションがデー
タベースに適用されます。
vendor/bin/yii migrate/create --appconfig=config.php create_post_table--fields="title:string,body:text"
vendor/bin/yii migrate/up --appconfig=config.php
models ディレクトリを作成し、Post.php ファイルをそのディレクトリに置きます。以下がそのモデルのためのコードです。
<?php
namespace micro\models;
use yii\db\ActiveRecord;〶〲〴

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

class Post extends ActiveRecord{
public static function tableName(){
return '{{post}}';}}情報〺 ここで作成されたモデルは ぁっぴどぶづげづっはひつ クラスのもの
で、post テーブルのデータを表します。 詳細な情報は アクティブ・レコードのガイド を参照してください。
私たちの ぁぐぉ で記事データへのアクセスを提供するために、controllersに PostController を追加します。
<?php
namespace micro\controllers;
use yii\rest\ActiveController;class PostController extends ActiveController{
public $modelClass = 'micro\models\Post';}

public function behaviors(){// 動作のために認証済みユーザであることを要求する rateLimiter を削除$behaviors = parent::behaviors();
unset($behaviors['rateLimiter']);return $behaviors;}

この時点で私たちの ぁぐぉ は以下の さげが を提供します。
• /index.php?r=post 〭 全ての記事をリストする• /index.php?r=post/view&id=1 〭 ぉい 〱 の記事を表示する• /index.php?r=post/create 〭 記事を作成する• /index.php?r=post/update&id=1 〭 ぉい 〱 の記事を更新する• /index.php?r=post/delete&id=1 〭 ぉい 〱 の記事を削除する
ここから開始して、あなたのアプリケーションの開発を更に進めるために、次のガイドを読むと良いでしょう。
• ぁぐぉ は今のところ入力として さげが エンコードされたフォームデー
タだけを理解します。 本物の おこくぎ ぁぐぉ にするためには、べどどぜぷづぢ
ぜおびはのぐちひびづひ を構成する必要があります。
• さげが をもっと馴染みやすいものにするためには、ルーティングを構成しなければなりません。 方法を知るためには げぅこご のルーティ
ングのガイド を参照してください。

〱〴〮〱〰〮 すぉぉ をマイクロ・フレームワークとして使う〶〲〵• 更に参照すべき文書を知るために 先を見通す のセクションを読んでください。

〶〲〶

ぃえぁぐごぅげ 〱〴〮 スペシャル・トピック

Chapter 15

ウィジェット〶〲〷〶〲〸

ぃえぁぐごぅげ 〱〵〮 ウィジェット

Chapter 16

ヘルパ
16.1

ヘルパ

補足〺 このセクションはまだ執筆中です。
すどど は、一般的なコーディングのタスク、例えば、文字列や配列の操作、えごきが コードの生成などを手助けする多くのクラスを提供しています。 これらのヘルパ・クラスは yii\helpers 名前空間の下に編成されており、すべてスタティックなクラス 〨すなわち、スタティックなプロパティとメソッドのみを含み、インスタンス化すべきでないクラス〩 です。
ヘルパ・クラスは、そのスタティックなメソッドの一つを直接に呼び出すことによって使用します。例えば、
use yii\helpers\Html;
echo Html::encode('Test > test');補足〺 ヘルパ・クラスをカスタマイズする ことをサポートするために、すどど はコア・ヘルパ・クラスのすべてを二つのクラスに分割しています。 すなわち、基底クラス 〨例えばBaseArrayHelper〩 と具象クラス 〨例えば ArrayHelper〩 です。 ヘル
パを使うときは、具象クラスのみを使うべきであり、基底ク
ラスは決して使ってはいけません。

16.1.1

コア・ヘルパ・クラス

以下のコア・ヘルパ・クラスが すどど のリリースにおいて提供されています。
• 配列ヘルパ• ぃはのびはぬづ• うどぬづえづぬばづひ• うはひねちぴぃはのぶづひぴづひ• えぴねぬ ヘルパ
〶〲〹

〶〳〰

ぃえぁぐごぅげ 〱〶〮 ヘルパ• えぴねぬぐふひど〜づひ• ぉねちでどのづ 〨べどど〲〭どねちでどのづ エクステンションによって提供〩• ぉの〝づっぴはひ• おびはの• きちひにつはぷの• こぴひどのでえづぬばづひ• さひぬ ヘルパ
• ざちひいふねばづひ

16.1.2

ヘルパ・クラスをカスタマイズする

コア・ヘルパ・クラス 〨例えば べどどぜとづぬばづひびぜぁひひちべえづぬばづひ〩 をカスタマイズするためには、 そのヘルパに対応する基底クラス 〨例えば べどどぜとづぬばづひび
ぜあちびづぁひひちべえづぬばづひ〩 を拡張するクラスを作成して、名前空間も含めて、対応する具象クラス 〨例えば べどどぜとづぬばづひびぜぁひひちべえづぬばづひ〩 と同じ名前を付けます。 このクラスが、フレームワークのオリジナルの実装を置き換えるものとしてセットアップされます。
次の例は、べどどぜとづぬばづひびぜぁひひちべえづぬばづひ クラスの ねづひでづ〨〩 メソッドをカ
スタマイズする方法を示すものです。
<?php
namespace yii\helpers;class ArrayHelper extends BaseArrayHelper{
public static function merge($a, $b){// あなた独自の実装}}

あなたのクラスを ArrayHelper.php という名前のファイルに保存します。
このファイルはどこに置いても構いません。例えば、@app/components に置くことにしましょう。
次に、アプリケーションの エントリ・スクリプト で、 次のコード行を yii.php ファイルをインクルードする行の後に追加して、すどど クラス・
オートローダ に、 フレームワークから本来のヘルパ・クラスをロードする代りに、あなたのカスタム・クラスをロードすべきことを教えます。
Yii::$classMap['yii\helpers\ArrayHelper'] ='@app/components/ArrayHelper.php';

ヘルパ・クラスのカスタマイズは、ヘルパの既存の関数の振る舞いを変更したい場合にだけ役立つものであることに注意してください。 アプリ
ケーションの中で使用する関数を追加したい場合は、 そのための独立したヘルパを作成する方が良いでしょう。

〱〶〮〲〮 配列ヘルパ

16.2

〶〳〱

配列ヘルパ

ぐえぐ の充実した配列関数1 への追加として、 すどど の配列ヘルパは、配列をさらに効率的に扱うことを可能にするスタティックなメソッドを提供
しています。

16.2.1

値を取得する配列、オブジェクト、またはその両方から成る複雑な構造から標準的なぐえぐ を使って値を取得することは、非常に面倒くさい仕事です。 最初に
isset でキーの存在をチェックしなければならず、次に、キーが存在していれば値を取得し、存在していなければ、 デフォルト値を提供しなければなりません。
class User{public $name = 'Alex';}$array = ['foo' => ['bar' => new User(),]];$value = isset($array['foo']['bar']->name) ? $array['foo']['bar']->name :null;

すどど はこのための非常に便利なメソッドを提供しています。
$value = ArrayHelper::getValue($array, 'foo.bar.name');

メソッドの最初の引数は、どこから値を取得しようとしているかを指定します。 二番目の引数は、データの取得の仕方を指定します。これは、以下の一つとすることが出来ます。
• 値を読み出すべき配列のキーまたはオブジェクトのプロパティの名前。
• ドットで分割された配列のキーまたはオブジェクトのプロパティ名のセット。上の例で使用した形式です。
• 値を返すコールバック。
コールバックは次の形式でなければなりません。
$fullName = ArrayHelper::getValue($user, function ($user, $defaultValue) {return $user->firstName . ' ' . $user->lastName;});

三番目のオプションの引数はデフォルト値であり、指定されない場合はnull となります。以下のようにして使用します。
$username = ArrayHelper::getValue($comment, 'user.username', 'Unknown');1

https://www.php.net/manual/ja/book.array.php〶〳〲

ぃえぁぐごぅげ 〱〶〮 ヘルパ

16.2.2

値を設定する$array = ['key' => ['in' => ['k' => 'value']]];
ArrayHelper::setValue($array, 'key.in', ['arr' => 'val']);// `$array` で値を書くためのパスは配列として指定することも出来ます
ArrayHelper::setValue($array, ['key', 'in'], ['arr' => 'val']);

結果として、$array['key']['in'] の初期値は新しい値によって上書きされ
ます。
[

]

'key' => ['in' => ['arr' => 'val']]

パスが存在しないキーを含んでいる場合は、キーが作成されます。
// `$array['key']['in']['arr0']` が空でなければ、値が配列に追加される
ArrayHelper::setValue($array, 'key.in.arr0.arr1', 'val');// `$array['key']['in']['arr0']` の値を完全に上書きしたい場合はArrayHelper::setValue($array, 'key.in.arr0', ['arr1' => 'val']);結果は以下のようになります[]'key' => ['in' => ['k' => 'value','arr0' => ['arr1' => 'val']]]

16.2.3配列から値を取り除く

値を取得して、その直後にそれを配列から削除したい場合は、remove メ
ソッドを使うことが出来ます。
$array = ['type' => 'A', 'options' => [1, 2]];$type = ArrayHelper::remove($array, 'type');

このコードを実行した後では、$array には ['options' => [1, 2]] が含まれ、$type は A となります。 getValue メソッドとは違って、remove は単純なキー名だけをサポートすることに注意してください。

〱〶〮〲〮 配列ヘルパ

16.2.4〶〳〳

キーの存在をチェックする

ArrayHelper::keyExists は、大文字と小文字を区別しないキーの比較をサポートすることを除いて、 ちひひちべたにづべたづへどびぴび2 と同じ動作をします。例えば、$data1 = ['userName' => 'Alex',];$data2 = ['username' => 'Carsten',];if (!ArrayHelper::keyExists('username', $data1, false) ||!ArrayHelper::keyExists('username', $data2, false)) {echo "username を提供してください。";}

16.2.5

カラムを取得する

データ行またはオブジェクトの配列から、あるカラムの値を取得する必要があることがよくあります。良くある例は、ぉい のリストの取得です。
$array = [['id' => '123', 'data' => 'abc'],['id' => '345', 'data' => 'def'],];$ids = ArrayHelper::getColumn($array, 'id');

結果は ['123', '345'] となります。
追加の変形が要求されたり、値の取得方法が複雑であったりする場合
は、 無名関数を二番目の引数として指定することが出来ます。
$result = ArrayHelper::getColumn($array, function ($element) {return $element['id'];});

16.2.6

配列を再インデックスする指定されたキーに従って配列にインデックスを付けるために、index メ
ソッドを使うことが出来ます。 入力値は、多次元配列であるか、オブジェクトの配列でなければなりません。 $key は、サブ配列のキーの名
前、オブジェクトのプロパティの名前、または、キーとして使用される値を返す無名関数とすることが出来ます。
$groups 属性はキーの配列であす。これは、入力値の配列を一つまたは複数のサブ配列にグループ化するために キーとして使用されます。
2https://www.php.net/manual/ja/function.array-key-exists.php〶〳〴

ぃえぁぐごぅげ 〱〶〮 ヘルパ

特定の要素の $key 属性またはその値が null であるとき、$groups が定義されていない場合は、その要素は破棄されて、結果には入りません。
そうではなく、$groups が指定されている場合は、 配列の要素はキー無し
で結果の配列に追加されます。
例えば、$array = [['id' => '123', 'data' => 'abc', 'device' => 'laptop'],['id' => '345', 'data' => 'def', 'device' => 'tablet'],['id' => '345', 'data' => 'hgi', 'device' => 'smartphone'],];$result = ArrayHelper::index($array, 'id');

結果は、id 属性の値をキーとする連想配列になります。
['123' => ['id' => '123', 'data' => 'abc', 'device' => 'laptop'],'345' => ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone']// 元の配列の2番目の要素は、同じ id であるため、最後の要素によって上書きされます]$key として無名関数を渡しても同じ結果になります。
$result = ArrayHelper::index($array, function ($element) {return $element['id'];});
id を〳番目の引数として渡すと、$array を id によってグループ化することが出来ます。
$result = ArrayHelper::index($array, null, 'id');

結果は、最初のレベルが id でグループ化され、第〲のレベルはインデッ
クスされていない連想配列になります。
[]'123' => [['id' => '123', 'data' => 'abc', 'device' => 'laptop']],'345' => [ // このインデックスを持つ全ての要素が結果の配列に入る['id' => '345', 'data' => 'def', 'device' => 'tablet'],['id' => '345', 'data' => 'hgi', 'device' => 'smartphone'],]無名関数を配列のグループ化に使うことも出来ます。
$result = ArrayHelper::index($array, 'data', [function ($element) {return $element['id'];}, 'device']);〱〶〮〲〮 配列ヘルパ〶〳〵

結果は、最初のレベルが id でグループ化され、第〲のレベルが device でグループ化され、 第〳のレベルが data でインデックスされた連想配列に
なります。
[

]

'123' => ['laptop' => ['abc' => ['id' => '123', 'data' => 'abc', 'device' => 'laptop']]],'345' => ['tablet' => ['def' => ['id' => '345', 'data' => 'def', 'device' => 'tablet']],'smartphone' => ['hgi' => ['id' => '345', 'data' => 'hgi', 'device' =>'smartphone']]]

16.2.7

マップを作成する

多次元配列またはオブジェクトの配列からマップ 〨キー・値 のペア〩 を作成するためには map メソッドを使うことが出来ます。 $from と $to のパラメータで、マップを構成するキー名またはプロパティ名を指定します。
オプションで、グループ化のためのフィールド $group に従って、マップ
をグループ化することも出来ます。例えば、$array = [['id' => '123', 'name' => 'aaa', 'class' => 'x'],['id' => '124', 'name' => 'bbb', 'class' => 'x'],['id' => '345', 'name' => 'ccc', 'class' => 'y'],];$result = ArrayHelper::map($array, 'id', 'name');// 結果は次のようになります// [//'123' => 'aaa',//'124' => 'bbb',//'345' => 'ccc',// ]$result = ArrayHelper::map($array, 'id', 'name', 'class');// 結果は次のようになります// [//'x' => [//'123' => 'aaa',//'124' => 'bbb',//],//'y' => [//'345' => 'ccc',〶〳〶ぃえぁぐごぅげ 〱〶〮 ヘルパ

//
// ]

],

16.2.8

多次元配列の並べ替え

multisort メソッドは、オブジェクトの配列または入れ子にされた配列

を、一つまたは複数のキーによって並べ替えることを手助けします。例
えば、$data = [['age' => 30, 'name' => 'Alexander'],['age' => 30, 'name' => 'Brian'],['age' => 19, 'name' => 'Barney'],];
ArrayHelper::multisort($data, ['age', 'name'], [SORT_ASC, SORT_DESC]);

並べ替えの後には、$data に次のデータが入っています。
[['age' => 19, 'name' => 'Barney'],['age' => 30, 'name' => 'Brian'],['age' => 30, 'name' => 'Alexander'],];

並べ替えで参照するキーを指定する二番目の引数は、一つのキーであれ
ば文字列、複数のキーであれば配列を取ることが出来ます。 さらに、次のような無名関数でも構いません。
ArrayHelper::multisort($data, function($item) {// 存在していれば 'age' で、さもなくば 'name' でソート
return isset($item['age']) ? ['age', 'name'] : 'name';});

三番目の引数は並べ替えの順序です。 一つのキーによる並べ替えの場合
は、SORT_ASC か SORT_DESC のいずれかです。 複数の値による並べ替えの場
合は、並べ替えの順序の配列を渡して、値ごとに違う順序で並べ替えることが出来ます。
最後の引数は並べ替えのフラグで、 ぐえぐ の びはひぴ〨〩3 関数に渡されるのと同じ値を取ることが出来ます。

16.2.9配列の型を検出する

配列が添字配列であるか連想配列であるかを知ることが出来ると便利です。例を挙げましょう。
3https://www.php.net/manual/ja/function.sort.php〱〶〮〲〮 配列ヘルパ〶〳〷// キーは指定されていない$indexed = ['Qiang', 'Paul'];echo ArrayHelper::isIndexed($indexed);// 全てのキーは文字列$associative = ['framework' => 'Yii', 'version' => '2.0'];
echo ArrayHelper::isAssociative($associative);

16.2.10

値を HTML エンコード / デコードする

文字列の配列の中にある特殊文字を えごきが エンティティにエンコード、または、えごきが エンティティからデコードするために、下記の関数を使うことが出来ます。
$encoded = ArrayHelper::htmlEncode($data);$decoded = ArrayHelper::htmlDecode($data);

デフォルトでは、値だけがエンコードされます。二番目の引数を false として渡すことによって、配列のキーもエンコードすることが出来ます。
エンコードにはアプリケーションの文字セットが使用されますが、三番目の引数によってそれを変更することも出来ます。

16.2.11配列をマージする

ぁひひちべえづぬばづひ〺〺ねづひでづ〨〩 を使って、二つまたはそれ以上の配列を再帰的に一つの配列にマージすることが出来ます。 各配列に同じ文字列のキー値を持つ要素がある場合は、 〨ちひひちべたねづひでづたひづっふひびどぶづ〨〩4 とは違って〩後のものが前のものを上書きします。 両方の配列が、同じキーを持つ配列型の要素を持っている場合は、再帰的なマージが実行されます。 添字型の要素については、後の配列の要素が前の配列の要素の後に追加されます。
べどどぜとづぬばづひびぜさのびづぴぁひひちべざちぬふづ オブジェクトを使って前の配列にある値を非設定に指定したり、 べどどぜとづぬばづひびぜげづばぬちっづぁひひちべざちぬふづ オブジェクトを使って再帰的なマージでなく前の値の上書きを強制したりすることが
出来ます。
例えば、
$array1 = ['name' => 'Yii','version' => '1.1','ids' => [1,],
'validDomains' => ['example.com','www.example.com',],'emails' => [4https://www.php.net/manual/ja/function.array-merge-recursive.php

〶〳〸

];

ぃえぁぐごぅげ 〱〶〮 ヘルパ],'admin' => 'admin@example.com','dev' => 'dev@example.com',$array2 = ['version' => '2.0','ids' => [2,],'validDomains' => new \yii\helpers\ReplaceArrayValue(['yiiframework.com','www.yiiframework.com',]),'emails' => ['dev' => new \yii\helpers\UnsetArrayValue(),],];$result = ArrayHelper::merge($array1, $array2);

結果は次のようになります。
[]'name' => 'Yii','version' => '2.0','ids' => [1,2,],
'validDomains' => ['yiiframework.com','www.yiiframework.com',],'emails' => ['admin' => 'admin@example.com',],

16.2.12

オブジェクトを配列に変換する

オブジェクトまたはオブジェクトの配列を配列に変換する必要があることがよくあります。 最もよくあるのは、げぅこご ぁぐぉ によってデータ配列を提供するなどの目的で、アクティブ・レコード・モデルを変換する場合です。そうするために、次のコードを使うことが出来ます。
$posts = Post::find()->limit(10)->all();$data = ArrayHelper::toArray($posts, ['app\models\Post' => ['id','title',// 結果配列のキー名 => プロパティの値

〱〶〮〲〮 配列ヘルパ

]);

],

〶〳〹

'createTime' => 'created_at',// 結果配列のキー名 => 無名関数が返す値'length' => function ($post) {return strlen($post->content);},

最初の引数が変換したいデータです。この例では、Post ぁげ モデルを変換しようとしています。
二番目の引数は、クラスごとの変換マップです。ここでは、Post モデ
ルの変換マップを設定しています。 変換マップの配列が、一連のマップを含んでいます。各マップは以下のいずれかの形式を取ります。
• フィールド名 〭 そのままインクルードされる。
• キー〯値 のペア 〭 配列のキー名にしたい文字列と、値を取得すべきモデルのカラムの名前。
• キー〯値 のペア 〭 配列のキー名にしたい文字列と、値を返すコール
バック。
単一のモデルに対する上記の変換の結果は以下のようになります。
['id' => 123,
'title' => 'test','createTime' => '2013-01-01 12:00AM','length' => 301,]

特定のクラスについて、配列に変換するデフォルトの方法を提供するためには、 そのクラスの ぁひひちべちぢぬづ インタフェイスを実装することが出来ます。

16.2.13配列の中にあるかどうか調べる

ある要素が配列の中に存在するかどうか、また、一連の要素が配列のサブセットであるかどうか、ということを調べる必要がある場合がよくあります。 ぐえぐ は in_array() を提供していますが、これはサブセットや\Traversable なオブジェクトをサポートしていません。
この種のチェックを助けるために、べどどぜとづぬばづひびぜぁひひちべえづぬばづひ は どびぉの〨〩および どびこふぢびづぴ〨〩 を どのたちひひちべ〨〩5 と同じシグニチャで提供しています。
// true
ArrayHelper::isIn('a', ['a']);// true
ArrayHelper::isIn('a', new ArrayObject(['a']));// true
ArrayHelper::isSubset(new ArrayObject(['a', 'c']), new ArrayObject(['a','b', 'c']));
5https://www.php.net/manual/ja/function.in-array.php〶〴〰

ぃえぁぐごぅげ 〱〶〮 ヘルパ

16.3

Html ヘルパ

全てのウェブ・アプリケーションは大量の えごきが マークアップを生成します。 マークアップが静的な場合は、ぐえぐ と えごきが を一つのファイルに混ぜる6 ことによって効率よく生成することが可能ですが、マークアップを動的にするとなると、何らかの助けが無ければ、処理がトリッキーになってきます。 すどど はそのような手助けを えぴねぬ ヘルパの形式で提供します。 これは、よく使われる えごきが タグとそのオプションやコンテントを処理するための一連のスタティック・メソッドを提供するものです。
補足〺 あなたのマークアップがおおむね静的なものである場合
は、えごきが を直接に使用する方が適切です。 何でもかんでもえぴねぬ ヘルパの呼び出しでラップする必要はありません。

16.3.1

基礎

動的な えごきが を文字列の連結によって構築していると、あっという間に乱雑なコードになります。 そのため、すどど はタグのオプションを操作し、それらのオプションに基づいてタグを構築する一連のメソッドを提供します。
タグを生成する
タグを生成するコードは次のようなものです。
<?= Html::tag('p', Html::encode($user->name), ['class' => 'username']) ?>最初の引数はタグの名前です。二番目の引数は、開始タグと終了タグの間に囲まれることになるコンテントです。 Html::encode を使っていることに注目してください。 これは、必要な場合には えごきが を使うことが出来るように、コンテントが自動的にはエンコードされないからです。 三番目の引数は えごきが のオプション、言い換えると、タグの属性です。この配列で、キーは class、href、target などの属性の名前であり、値は属性の値です。
上記のコードは次の えごきが を生成します。
<p class="username">samdark</p>

開始タグまたは終了タグだけが必要な場合は、Html::beginTag() または
Html::endTag() のメソッドを使うことが出来ます。

オプションは多くの えぴねぬ ヘルパのメソッドとさまざまなウィジェッ
トで使用されます。 その全ての場合において、いくつか追加の処理がなされることを知っておいてください。
• 値が null である場合は、対応する属性はレンダリングされません。
6https://www.php.net/manual/ja/language.basic-syntax.phpmode.php〱〶〮〳〮 えごきが ヘルパ〶〴〱• 値が真偽値である属性は、真偽値属性 〨ぢははぬづちの ちぴぴひどぢふぴづび〩7 として扱われます。
• 属性の値は えぴねぬ〺〺づのっはつづ〨〩 を使って えごきが エンコードされます。
• 属性の値が配列である場合は、次のように処理されます。
〕 属性が べどどぜとづぬばづひびぜえぴねぬ〺〺〤つちぴちぁぴぴひどぢふぴづび にリストされているデータ属性である場合、例えば data や ng である場合
は、 値の配列にある要素の一つ一つについて、属性のリス
ト が レ ン ダ リ ン グ さ れ ま す 。 例 え ば 、'data' => ['id' => 1,'name' => 'yii'] は data-id="1" data-name="yii" を生成します。
また、'data' => ['params' => ['id' => 1, 'name' => 'yii'], 'status'=> 'ok'] は data-params='{"id":1,"name":"yii"}' data-status="ok" を生成します。 後者の例において、下位の配列に対して おこくぎ形式が使用されていることに注意してください。
〕 属性がデータ属性でない場合は、値は おこくぎ エンコードされます。 例えば、['params' => ['id' => 1, 'name' => 'yii'] はparams='{"id":1,"name":"yii"}' を生成します。
ぃここ のクラスとスタイルを形成する
えごきが タグのオプションを構築する場合、たいていは、デフォルトの値から始めて必要な修正をする、という方法をとります。 ぃここ クラスを追加または削除するために、次のコードを使用することが出来ます。
$options = ['class' => 'btn btn-default'];
if ($type === 'success') {Html::removeCssClass($options, 'btn-default');
Html::addCssClass($options, 'btn-success');}
echo Html::tag('div', 'Pwede na', $options);// $type が 'success' の場合、次のようにレンダリングされる// <div class="btn btn-success">Pwede na</div>

配列形式を使って複数の ぃここ クラスを指定することも出来ます。
$options = ['class' => ['btn', 'btn-default']];echo Html::tag('div', 'Save', $options);// '<div class="btn btn-default">Save</div>' をレンダリングするクラスを追加・削除する際にも配列形式を使うことが出来ます。
$options = ['class' => 'btn'];
7
https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#
boolean-attributes

〶〴〲ぃえぁぐごぅげ 〱〶〮 ヘルパ

if ($type === 'success') {Html::addCssClass($options, ['btn-success', 'btn-lg']);}echo Html::tag('div', 'Save', $options);// '<div class="btn btn-success btn-lg">Save</div>' をレンダリングする
Html::addCssClass() はクラスの重複を防止しますので、同じクラスが二度出現するかも知れないと心配する必要はありません。
$options = ['class' => 'btn btn-default'];
Html::addCssClass($options, 'btn-default'); // クラス 'btn-default' は既に存在する
echo Html::tag('div', 'Save', $options);// '<div class="btn btn-default">Save</div>' をレンダリングするぃここ のクラスオプションを配列形式で指定する場合には、名前付きのキーを使ってクラスの論理的な目的を示すことが出来ます。 この場
合、Html::addCssClass() で同じキーを持つクラスを指定しても無視されます。
$options = ['class' => ['btn','theme' => 'btn-default',]];
Html::addCssClass($options, ['theme' => 'btn-success']); // 'theme' キーは既に使用されている
echo Html::tag('div', 'Save', $options);// '<div class="btn btn-default">Save</div>' をレンダリングするぃここ のスタイルも style 属性を使って、同じように設定することが出来ます。
$options = ['style' => ['width' => '100px', 'height' => '100px']];// style="width: 100px; height: 200px; position: absolute;" となる
Html::addCssStyle($options, 'height: 200px; position: absolute;');// style="position: absolute;" となる
Html::removeCssStyle($options, ['width', 'height']);

ちつつぃびびこぴべぬづ〨〩 を使うときには、ぃここ プロパティの名前と値に対応する「キー〭値」ペアの配列か、 または、width: 100px; height: 200px; のような文字列を指定することが出来ます。 この二つの形式は、っびびこぴべぬづうひはねぁひひちべ〨〩と っびびこぴべぬづごはぁひひちべ〨〩 を使って、双方向に変換することが出来ます。

〱〶〮〳〮 えごきが ヘルパ〶〴〳

ひづねはぶづぃびびこぴべぬづ〨〩 メソッドは、削除すべきプロパティの配列を受け取ります。 プロパティが一つだけである場合は、文字列で指定することも出来ます。
コンテントをエンコードおよびデコードする
コンテントが適切かつ安全に えごきが として表示されるためには、コンテント内の特殊文字がエンコードされなければなりません。 特殊文
字のエンコードとデコードは、ぐえぐ では とぴねぬびばづっどちぬっとちひび8 と とぴねぬびばづ〭
っどちぬっとちひびたつづっはつづ9 によって行われます。 これらのメソッドを直接使用する場合の問題は、文字エンコーディングと追加のフラグを毎回指定しなければならないことです。 フラグは毎回同じものであり、文字エンコー
ディングはセキュリティ問題を防止するためにアプリケーションのそれと一致すべきものですから、 すどど は二つのコンパクトかつ使いやすいメ
ソッドを用意しました。
$userName = Html::encode($user->name);echo $userName;$decodedUserName = Html::decode($userName);

16.3.2

フォーム

フォームのマークアップを扱う仕事は、極めて面倒くさく、エラーを生
じがちなものです。 このため、フォームのマークアップの仕事を助けるための一群のメソッドがあります。
補足〺 モデルを扱っており、検証が必要である場合は、ぁっぴどぶづうはひねを使うことを検討してください。
フォームを作成するフォームを開始するためには、次のように ぢづでどのうはひね〨〩 メソッドを使うことが出来ます。
<?= Html::beginForm(['order/update', 'id' => $id], 'post', ['enctype' =>'multipart/form-data']) ?>最初の引数は、フォームが送信されることになる さげが です。これは さひぬ〺〺ぴは〨〩 によって受け入れられる すどど のルートおよびパラメータの形式で指定することが出来ます。 第二の引数は使われるメソッドです。post がデフォルトです。第三の引数はフォームタグのオプションの配列です。
上記の場合では、ぐくこご リクエストにおけるフォーム・データのエン
コーディング方法を multipart/form-data に変更しています。 これはファ
イルをアップロードするために必要とされます。
フォーム・タグを閉じるのは簡単です。
89https://www.php.net/manual/ja/function.htmlspecialchars.php
https://www.php.net/manual/ja/function.htmlspecialchars-decode.php〶〴〴

ぃえぁぐごぅげ 〱〶〮 ヘルパ<?= Html::endForm() ?>ボタン
ボタンを生成するためには、次のコードを使うことが出来ます。
<?= Html::button('押してね !', ['class' => 'teaser']) ?><? = Html::submitButton('送信', ['class' => 'submit']) ?><? = Html::resetButton('リセット', ['class' => 'reset']) ?>最初の引数は、三つのメソッドのどれでも、ボタンのタイトルであり、第二の引数はオプションです。 タイトルはエンコードされませんので、エンド・ユーザからデータを取得する場合は えぴねぬ〺〺づのっはつづ〨〩 を使ってエンコードしてください。
インプット・フィールド
インプットのメソッドには二つのグループがあります。 一つは active か
ら始まるものでアクティブ・インプットと呼ばれます。もう一方は active
から始まらないものです。 アクティブ・インプットは、データを指定されたモデルと属性から取得しますが、通常のインプットでは、データは直接に指定されます。
最も汎用的なメソッドは以下のものです。
タイプ、インプットの名前、値、オプション<?= Html::input('text', 'username', $user->name, ['class' => $username]) ?>タイプ、モデル、モデルの属性名、オプション<? = Html::activeInput('text', $user, 'name', ['class' => $username]) ?>インプットのタイプが前もって判っている場合は、ショートカットメ
ソッドを使う方が便利です。
• べどどぜとづぬばづひびぜえぴねぬ〺〺ぢふぴぴはのぉのばふぴ〨〩• べどどぜとづぬばづひびぜえぴねぬ〺〺びふぢねどぴぉのばふぴ〨〩• べどどぜとづぬばづひびぜえぴねぬ〺〺ひづびづぴぉのばふぴ〨〩• べどどぜとづぬばづひびぜえぴねぬ〺〺ぴづへぴぉのばふぴ〨〩〬 べどどぜとづぬばづひびぜえぴねぬ〺〺ちっぴどぶづごづへぴぉのばふぴ〨〩• べどどぜとづぬばづひびぜえぴねぬ〺〺とどつつづのぉのばふぴ〨〩〬 べどどぜとづぬばづひびぜえぴねぬ〺〺ちっぴどぶづえどつつづのぉのばふぴ〨〩• べどどぜとづぬばづひびぜえぴねぬ〺〺ばちびびぷはひつぉのばふぴ〨〩 〯 べどどぜとづぬばづひびぜえぴねぬ〺〺ちっぴどぶづぐちびびぷはひつぉのばふぴ〨〩• べどどぜとづぬばづひびぜえぴねぬ〺〺てどぬづぉのばふぴ〨〩〬 べどどぜとづぬばづひびぜえぴねぬ〺〺ちっぴどぶづうどぬづぉのばふぴ〨〩• べどどぜとづぬばづひびぜえぴねぬ〺〺ぴづへぴちひづち〨〩〬 べどどぜとづぬばづひびぜえぴねぬ〺〺ちっぴどぶづごづへぴちひづち〨〩
ラジオとチェックボックスは、メソッドのシグニチャの面で少し異なっています。
<?= Html::radio('agree', true, ['label' => '同意します']) ?><? = Html::activeRadio($model, 'agree', ['class' => 'agreement']) ?><? = Html::checkbox('agree', true, ['label' => '同意します']) ?><? = Html::activeCheckbox($model, 'agree', ['class' => 'agreement']) ?>〱〶〮〳〮 えごきが ヘルパ〶〴〵

ドロップダウン・リストとリスト・ボックスは、次のようにしてレンダリングすることが出来ます。
<?= Html::dropDownList('list', $currentUserId, ArrayHelper::map($userModels,'id', 'name')) ?><? = Html::activeDropDownList($users, 'id', ArrayHelper::map($userModels,'id', 'name')) ?><? = Html::listBox('list', $currentUserId, ArrayHelper::map($userModels,'id', 'name')) ?><? = Html::activeListBox($users, 'id', ArrayHelper::map($userModels, 'id','name')) ?>最初の引数はインプットの名前、第二の引数は現在選択されている値です。そして第三の引数は「キー〭値」のペアであり、配列のキーはリストの値、配列の値はリストのラベルです。
複数の選択肢を選択できるようにしたい場合は、チェックボックス・
リストが最適です。
<?= Html::checkboxList('roles', [16, 42], ArrayHelper::map($roleModels,'id', 'name')) ?><? = Html::activeCheckboxList($user, 'role', ArrayHelper::map($roleModels,'id', 'name')) ?>そうでない場合は、ラジオ・リストを使います。
<?= Html::radioList('roles', [16, 42], ArrayHelper::map($roleModels, 'id','name')) ?><? = Html::activeRadioList($user, 'role', ArrayHelper::map($roleModels,'id', 'name')) ?>ラベルとエラーインプットと同じように、ラベルを生成するメソッドが二つあります。
モデルからデータを取るアクティブなラベルと、データを直接受け入れ
るアクティブでないラベルです。
<?= Html::label('ユーザ名', 'username', ['class' => 'label username']) ?><? = Html::activeLabel($user, 'username', ['class' => 'label username']) ?>一つまたは複数のモデルから取得したエラーを要約として表示するためには、次のコードを使うことが出来ます。
<?= Html::errorSummary($posts, ['class' => 'errors']) ?>個別のエラーを表示するためには、次のようにします。
<?= Html::error($post, 'title', ['class' => 'error']) ?>〶〴〶

ぃえぁぐごぅげ 〱〶〮 ヘルパ

インプットの名前と値モデルに基づいてインプット・フィールドの名前、ぉい、値を取得するメソッドがあります。 これらは主として内部的に使用されるものですが、場合によっては重宝します。
// Post[title]echo Html::getInputName($post, 'title');// post-title
echo Html::getInputId($post, 'title');// '私の最初の投稿'
echo Html::getAttributeValue($post, 'title');// $post->authors[0]echo Html::getAttributeValue($post, '[0]authors[0]');

上記において、最初の引数はモデルであり、第二の引数は属性を示す式です。これは最も単純な形式においては属性名ですが、配列の添字を前および〯または 後に付けた属性名とすることも出来ます。配列の添字は主として表形式データ入力のために使用されます。
• [0]content は、表形式データ入力で使われます。表形式入力の最初のモデルの 【っはのぴづのぴ】 属性を表します。
• dates[0] は、〢つちぴづび】 属性の最初の配列要素を表します。
• [0]dates[0] は、表形式入力の最初のモデルの 【つちぴづび】 属性の最初の配列要素を表します。
前後の添字なしに属性名を取得するためには、次のコードを使うことが出来ます。
// datesecho Html::getAttributeName('dates[0]');16.3.3

スタイルとスクリプト

埋め込みのスタイルとスクリプトをラップするタグを生成するメソッド
が二つあります。
<?= Html::style('.danger { color: #f00; }', ['media' => 'print']) ?>これは次の HTML を生成します。
<style media="print">.danger { color: #f00; }</style><? = Html::script('alert("こんにちは!");') ?>これは次の HTML を生成します。
<script>alert("こんにちは!");</script>

〱〶〮〳〮 えごきが ヘルパ〶〴〷

ぃここ ファイルの外部スタイルをリンクしたい場合は、次のようにします。
<?= Html::cssFile('@web/css/ie5.css', ['condition' => 'IE 5']) ?>これは次の HTML を生成します。
<!--[if IE 5]><link href="https://example.com/css/ie5.css" /><![endif]-->

最初の引数は さげが であり、第二の引数はオプションの配列です。通常のオプションに加えて、次のものを指定することが出来ます。
• condition 〭 指定された条件を使って <link を条件付きコメントで囲みます。 条件付きコメントなんて、使う必要が無くなっちゃえば良いのにね 〻〩• noscript 〭 true に設定すると <link を <noscript> タグで囲むことができます。 この場合、おちぶちこっひどばぴ がブラウザでサポートされていない
か、ユーザが おちぶちこっひどばぴ を無効にしたときだけ、ぃここ がインクルードされます。
おちぶちこっひどばぴ ファイルをリンクするためには、次のようにします。
<?= Html::jsFile('@web/js/main.js') ?>ぃここ と同じように、最初の引数はインクルードされるファイルへのリンクを指定するものです。オプションを第二の引数として渡すことが出来ます。 オプションに置いて、cssFile のオプションと同じように、condition を指定することが出来ます。

16.3.4

ハイパーリンク

ハイパーリンクを手軽に生成できるメソッドがあります。
<?= Html::a('プロファイル', ['user/view', 'id' => $id], ['class' =>'profile-link']) ?>最初の引数はタイトルです。これはエンコードされませんので、エンド・ユーザから取得したデータを使う場合は、Html::encode() でエンコードする必要があります。 第二の引数が、<a タグの href に入ることになるものです。 どのような値が受け入れられるかについて、詳細は さひぬ〺〺ぴは〨〩を参照してください。 第三の引数は、タグのプロパティの配列です。
mailto リンクを生成する必要があるときは、次のコードを使うことが出来ます。
<?= Html::mailto('連絡先', 'admin@example.com') ?>〶〴〸

16.3.5ぃえぁぐごぅげ 〱〶〮 ヘルパ

画像

イメージタグを生成するためには次のようにします。
<?= Html::img('@web/images/logo.png', ['alt' => '私のロゴ']) ?>これは次の HTML を生成します。
<img src="https://example.com/images/logo.png" alt="私のロゴ" />最初の引数は、エイリアス 以外にも、ルートとパラメータ、または さげがを受け入れることが出来ます。さひぬ〺〺ぴは〨〩 と同様です。

16.3.6

リスト

順序なしリストは、次のようにして生成することが出来ます。
<?= Html::ul($posts, ['item' => function($item, $index) {return Html::tag('li',$this->render('post', ['item' => $item]),['class' => 'post']);}]) ?>

順序付きリストを生成するためには、代りに Html:ol() を使ってくださ
い。

16.4

Url ヘルパ

さひぬ ヘルパは さげが を管理するための一連のスタティック・メソッドを提供します。

16.4.1

よく使う URL を取得する

よく使う さげが を取得するために使うことが出来るメソッドが二つあります。すなわち、ホーム さげが と、現在のリクエストのベース さげが を取得するメソッドです。 ホーム さげが を取得するためには、次のようにします。
$relativeHomeUrl = Url::home();$absoluteHomeUrl = Url::home(true);$httpsAbsoluteHomeUrl = Url::home('https');

パラメータが渡されない場合は、生成される さげが は相対 さげが になります。 パラメータとして true を渡せば、現在のスキーマの絶対 さげが を取得することが出来ます。または、スキーマ 〨http〬 https〩 を明示的に指定しても構いません。
現在のリクエストのベース さげが を取得するためには、次のようにします。

〱〶〮〴〮 さげが ヘルパ〶〴〹$relativeBaseUrl = Url::base();$absoluteBaseUrl = Url::base(true);$httpsAbsoluteBaseUrl = Url::base('https');

このメソッドの唯一のパラメータは、Url::home() の場合と全く同じ動作をします。

16.4.2

URL を生成する

与えられたルートへの さげが を生成するためには、Url::toRoute() メソッ
ドを使います。 このメソッドは、べどどぜぷづぢぜさひぬきちのちでづひ を使って さげが を生成します。
$url = Url::toRoute(['product/view', 'id' => 42]);

ルートは、文字列として指定することが出来ます 〨例えば、site/index〩。
または、生成される さげが に追加のクエリ・パラメータを指定したい場合
は、配列を使うことも出来ます。配列の形式は、以下のようにしなければなりません。
// /index.php?r=site%2Findex&param1=value1&param2=value2 を生成['site/index', 'param1' => 'value1', 'param2' => 'value2']

アンカーの付いた さげが を生成したい場合は、# パラメータを持つ配列を使うことが出来ます。例えば、// /index.php?r=site%2Findex&param1=value1#name を生成['site/index', 'param1' => 'value1', '#' => 'name']

ルートは、絶対ルートか相対ルートかのどちらかです。絶対ルートは先頭にスラッシュを持ち 〨例えば /site/index〩、相対ルートは持ちません 〨例
えば site/index または index〩。 相対ルートは次の規則に従って絶対ルートに変換されます。
• ルートが空文字列である場合は、現在の ルート が使用されます。
• ルートがスラッシュを全く含まない場合は 〨例えば index〩、カレン
ト・コントローラのアクション ぉい であると見なされて、 カレン
ト・コントローラの ふのどぱふづぉつ が前置されます。
• ルートが先頭にスラッシュを含まない場合は 〨例えば site/index〩、
カレント・モジュールに対する相対ルートと見なされて、 カレン
ト・モジュールの ふのどぱふづぉつ が前置されます。
バージョン 〲〮〰〮〲 以降では、エイリアス の形式でルートを指定することが出来ます。 その場合は、エイリアスが最初に実際のルートに変換され、そのルートが上記の規則に従って絶対ルートに変換されます。
以下に、このメソッドの使用例をいくつか挙げます。

〶〵〰

ぃえぁぐごぅげ 〱〶〮 ヘルパ// /index.php?r=site%2Findex
echo Url::toRoute('site/index');// /index.php?r=site%2Findex&src=ref1#nameecho Url::toRoute(['site/index', 'src' => 'ref1', '#' => 'name']);// /index.php?r=post%2Fedit&id=100
エイリアス "@postEdit" は "post/edit"と定義されていると仮定
echo Url::toRoute(['@postEdit', 'id' => 100]);// https://www.example.com/index.php?r=site%2Findex
echo Url::toRoute('site/index', true);// https://www.example.com/index.php?r=site%2Findex
echo Url::toRoute('site/index', 'https');

もうひとつ、ぴはげはふぴづ〨〩 と非常によく似た Url::to() というメソッドがあります。 唯一の違いは、このメソッドはルートを配列として指定することを要求する、という点です。文字列が与えられた場合は、さげが として扱われます。
最初の引数は、次のいずれかを取り得ます。
• 配列〺 さげが を生成するために ぴはげはふぴづ〨〩 が呼び出されます。 例えば、['site/index']、['post/index', 'page' => 2]。 ルートの指定方法の詳細については ぴはげはふぴづ〨〩 を参照してください。
• @ で始まる文字列〺 これはエイリアスとして扱われ、 エイリアスに対応する文字列が返されます。
• 空文字列〺 現在リクエストされている さげが が返されます。
• 通常の文字列〺 その通りのものとして扱われます。
$scheme 〨文字列または true〩 が指定された場合は、ホスト情報 〨べどどぜぷづぢ
ぜさひぬきちのちでづひ〺〺〤とはびぴぉのては から取得されます〩 を伴う絶対 さげが が返されます。 $url が既に絶対 さげが であった場合には、スキームが指定されたものに置き換えられます。
下記にいくつかの用例を挙げます。
// /index.php?r=site%2Findex
echo Url::to(['site/index']);// /index.php?r=site%2Findex&src=ref1#nameecho Url::to(['site/index', 'src' => 'ref1', '#' => 'name']);// /index.php?r=post%2Fedit&id=100
エイリアス "@postEdit" が "post/edit"と定義されていると仮定
echo Url::to(['@postEdit', 'id' => 100]);// 現在リクエストされている URL
echo Url::to();// /images/logo.gif
echo Url::to('@web/images/logo.gif');〱〶〮〴〮 さげが ヘルパ〶〵〱// images/logo.gif
echo Url::to('images/logo.gif');// https://www.example.com/images/logo.gif
echo Url::to('@web/images/logo.gif', true);// https://www.example.com/images/logo.gif
echo Url::to('@web/images/logo.gif', 'https');バージョン 〲〮〰〮〳 以降では、べどどぜとづぬばづひびぜさひぬ〺〺っふひひづのぴ〨〩 を使って、現
在リクエストされているルートと ぇぅご パラメータに基づいて さげが を生成することが出来ます。 $params パラメータを渡して、ぇぅご パラメータの中のいくつかを修正したり削除したり、または新しい ぇぅご パラメータを追加したりすることが出来ます。 例えば、// $_GET が ['id' => 123, 'src' => 'google'] であり、現在のルートが"post/view" であると仮定// /index.php?r=post%2Fview&id=123&src=google
echo Url::current();// /index.php?r=post%2Fview&id=123
echo Url::current(['src' => null]);// /index.php?r=post%2Fview&id=100&src=google
echo Url::current(['id' => 100]);

16.4.3

URL を記憶する

さげが を記憶して、後に続く一連のリクエストの一つを処理するときに、記憶した さげが を使わなければならないという場合があります。 これは、次のようにして達成することが出来ます。
// 現在の URL を記憶する
Url::remember();// 指定された URL を記憶する。引数の形式は Url::to() を参照。
Url::remember(['product/view', 'id' => 42]);// 指定された名前で URL を記憶する。
Url::remember(['product/view', 'id' => 42], 'product');

次のリクエストで、記憶された さげが を次のようにして取得することが出来ます。
$url = Url::previous();$productUrl = Url::previous('product');

16.4.4

相対 URL かどうかチェックする

さげが が相対 さげが であること、すなわち、さげが がホスト情報の部分を持っていないことを確かめるために、次のコードを使うことが出来ます。

〶〵〲$isRelative = Url::isRelative('test/it');

ぃえぁぐごぅげ 〱〶〮 ヘルパ