PageRenderTime 41ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/docs/guide-ja/concept-behaviors.md

https://gitlab.com/brucealdridge/yii2
Markdown | 332 lines | 240 code | 92 blank | 0 comment | 0 complexity | f5f0a2d07874a260e8ffac61ef2661c4 MD5 | raw file
  1. ビヘイビア
  2. =========
  3. ビヘイビアは [[yii\base\Behavior]] あるいはその子クラスのインスタンスですビヘイビアは
  4. [ミックスイン](http://en.wikipedia.org/wiki/Mixin) としても知られ、既存の [[yii\base\Component|component]] クラスの
  5. 機能をクラスの継承を変更せずに拡張することができますコンポーネントにビヘイビアをアタッチするとその
  6. コンポーネントにはビヘイビアのメソッドとプロパティが "注入" されそれらのメソッドとプロパティは
  7. コンポーネントクラス自体に定義されているかのようにアクセスできるようになりますまたビヘイビアは
  8. コンポーネントによってトリガされた [イベント](concept-events.md) に応答することができるので
  9. ビヘイビアでコンポーネントの通常のコード実行をカスタマイズすることができます
  10. ビヘイビアの定義 <span id="defining-behaviors"></span>
  11. ------------------
  12. ビヘイビアを定義するには [[yii\base\Behavior]] あるいは子クラスを継承するクラスを作成しますたとえば:
  13. ```php
  14. namespace app\components;
  15. use yii\base\Behavior;
  16. class MyBehavior extends Behavior
  17. {
  18. public $prop1;
  19. private $_prop2;
  20. public function getProp2()
  21. {
  22. return $this->_prop2;
  23. }
  24. public function setProp2($value)
  25. {
  26. $this->_prop2 = $value;
  27. }
  28. public function foo()
  29. {
  30. // ...
  31. }
  32. }
  33. ```
  34. 上のコードは `app\components\MyBehavior` という2つのプロパティ -- `prop1` `prop2` --
  35. `foo()` メソッドを持つビヘイビアクラスを定義します`prop2` プロパティは `getProp2()` getter メソッドと `setProp2()` setter メソッドで定義されることに着目してください
  36. [[yii\base\Behavior]] [[yii\base\Object]] を継承しているのでgetter setter による [プロパティ](concept-properties.md) 定義をサポートします
  37. このクラスはビヘイビアなのでコンポーネントにアタッチされるとそのコンポーネントは `prop1` `prop2` プロパティそれと `foo()` メソッドを持つようになります
  38. > Tip: ビヘイビア内から[[yii\base\Behavior::owner]] プロパティを介してビヘイビアをアタッチしたコンポーネントにアクセスすることができます
  39. コンポーネントイベントのハンドリング
  40. ------------------
  41. ビヘイビアがアタッチされたコンポーネントがトリガするイベントに応答する必要がある場合は
  42. [[yii\base\Behavior::events()]] メソッドをオーバーライドしましょうたとえば:
  43. ```php
  44. namespace app\components;
  45. use yii\db\ActiveRecord;
  46. use yii\base\Behavior;
  47. class MyBehavior extends Behavior
  48. {
  49. // ...
  50. public function events()
  51. {
  52. return [
  53. ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
  54. ];
  55. }
  56. public function beforeValidate($event)
  57. {
  58. // ...
  59. }
  60. }
  61. ```
  62. [[yii\base\Behavior::events()]] メソッドはイベントとそれに対応するハンドラのリストを返します
  63. 上の例では [[yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE|EVENT_BEFORE_VALIDATE]] イベントがあること
  64. そのハンドラ定義である `beforeValidate()` を宣言していますイベントハンドラを指定するときは以下の表記方法が使えます:
  65. * ビヘイビアクラスのメソッド名を参照する文字列 (上の例など)
  66. * オブジェクトまたはクラス名と文字列のメソッド名 (括弧なし) `[$object, 'methodName']`
  67. * 無名関数
  68. イベントハンドラのシグネチャは次のようにしてください`$event` はイベントのパラメータを参照しますイベントの詳細については
  69. [イベント](concept-events.md) セクションを参照してください
  70. ```php
  71. function ($event) {
  72. }
  73. ```
  74. ビヘイビアのアタッチ <span id="attaching-behaviors"></span>
  75. -------------------
  76. [[yii\base\Component|コンポーネント]] へのビヘイビアのアタッチは静的にも動的にも可能です実際は前者のほうがより一般的ですが
  77. ビヘイビアを静的にアタッチするにはビヘイビアをアタッチしたいコンポーネントクラスの [[yii\base\Component::behaviors()|behaviors()]] メソッドをオーバーライドします
  78. [[yii\base\Component::behaviors()|behaviors()]] メソッドはビヘイビアの [構成](concept-configurations.md) のリストを返さなければなりません
  79. 各ビヘイビアの構成内容はビヘイビアのクラス名でも構成情報配列でもかまいません
  80. ```php
  81. namespace app\models;
  82. use yii\db\ActiveRecord;
  83. use app\components\MyBehavior;
  84. class User extends ActiveRecord
  85. {
  86. public function behaviors()
  87. {
  88. return [
  89. // 無名ビヘイビア ビヘイビアクラス名のみ
  90. MyBehavior::className(),
  91. // 名前付きビヘイビア ビヘイビアクラス名のみ
  92. 'myBehavior2' => MyBehavior::className(),
  93. // 無名ビヘイビア 構成情報配列
  94. [
  95. 'class' => MyBehavior::className(),
  96. 'prop1' => 'value1',
  97. 'prop2' => 'value2',
  98. ],
  99. // 名前付きビヘイビア 構成情報配列
  100. 'myBehavior4' => [
  101. 'class' => MyBehavior::className(),
  102. 'prop1' => 'value1',
  103. 'prop2' => 'value2',
  104. ]
  105. ];
  106. }
  107. }
  108. ```
  109. ビヘイビア構成に対応する配列のキーを指定することによってビヘイビアに名前を関連付けることができますこの場合ビヘイビアは *名前付きビヘイビア* と呼ばれます上の例では2つの名前付きビヘイビア
  110. `myBehavior2` `myBehavior4` がありますビヘイビアが名前と関連付けられていない場合は *無名ビヘイビア* と呼ばれます
  111. ビヘイビアを動的にアタッチするにはビヘイビアをアタッチしようとしているコンポーネントの [[yii\base\Component::attachBehavior()]] メソッドを呼びます:
  112. ```php
  113. use app\components\MyBehavior;
  114. // ビヘイビアオブジェクトをアタッチ
  115. $component->attachBehavior('myBehavior1', new MyBehavior);
  116. // ビヘイビアクラスをアタッチ
  117. $component->attachBehavior('myBehavior2', MyBehavior::className());
  118. // 構成情報配列をアタッチ
  119. $component->attachBehavior('myBehavior3', [
  120. 'class' => MyBehavior::className(),
  121. 'prop1' => 'value1',
  122. 'prop2' => 'value2',
  123. ]);
  124. ```
  125. [[yii\base\Component::attachBehaviors()]] メソッドを使うといちどに複数のビヘイビアをアタッチできます:
  126. ```php
  127. $component->attachBehaviors([
  128. 'myBehavior1' => new MyBehavior, // 名前付きビヘイビア
  129. MyBehavior::className(), // 無名ビヘイビア
  130. ]);
  131. ```
  132. 次のように [構成情報](concept-configurations.md) を通じてビヘイビアをアタッチすることもできます:
  133. ```php
  134. [
  135. 'as myBehavior2' => MyBehavior::className(),
  136. 'as myBehavior3' => [
  137. 'class' => MyBehavior::className(),
  138. 'prop1' => 'value1',
  139. 'prop2' => 'value2',
  140. ],
  141. ]
  142. ```
  143. 詳しくは [構成情報](concept-configurations.md#configuration-format) セクションを参照してください
  144. ビヘイビアの使用 <span id="using-behaviors"></span>
  145. ---------------
  146. ビヘイビアを使用するにはまず上記の方法に従って [[yii\base\Component|コンポーネント]] にアタッチしますビヘイビアがコンポーネントにアタッチされればその使用方法はシンプルです
  147. あなたはアタッチされているコンポーネントを介してビヘイビアの *パブリック* メンバ変数または getter setter によって定義されたプロパティにアクセスすることができます:
  148. ```php
  149. // "prop1" はビヘイビアクラス内で定義されたプロパティ
  150. echo $component->prop1;
  151. $component->prop1 = $value;
  152. ```
  153. また同様にビヘイビアの *パブリック* メソッドも呼ぶことができます:
  154. ```php
  155. // foo() はビヘイビアクラス内で定義されたパブリックメソッド
  156. $component->foo();
  157. ```
  158. ご覧のように `$component` `prop1` `foo()` を定義していないにもかかわらず
  159. アタッチされたビヘイビアによってそれらをコンポーネント定義の一部であるかのように使うことができるのです
  160. もし2つのビヘイビアが同じプロパティやメソッドを定義しかつ両方とも同じコンポーネントにアタッチされている場合は
  161. プロパティやメソッドのアクセス時に*最初に* コンポーネントにアタッチされたビヘイビアが優先されます
  162. ビヘイビアはコンポーネントにアタッチされるとき名前と関連付けられているかもしれませんその場合
  163. その名前を使用してビヘイビアオブジェクトにアクセスすることができます:
  164. ```php
  165. $behavior = $component->getBehavior('myBehavior');
  166. ```
  167. またコンポーネントにアタッチされた全てのビヘイビアを取得することもできます:
  168. ```php
  169. $behaviors = $component->getBehaviors();
  170. ```
  171. ビヘイビアのデタッチ <span id="detaching-behaviors"></span>
  172. -------------------
  173. ビヘイビアをデタッチするにはビヘイビアに付けられた名前とともに [[yii\base\Component::detachBehavior()]] を呼び出します:
  174. ```php
  175. $component->detachBehavior('myBehavior1');
  176. ```
  177. *全ての* ビヘイビアをデタッチすることもできます:
  178. ```php
  179. $component->detachBehaviors();
  180. ```
  181. `TimestampBehavior` の利用 <span id="using-timestamp-behavior"></span>
  182. -------------------------
  183. しめくくりに[[yii\behaviors\TimestampBehavior]] を見てみましょうこのビヘイビアは
  184. 保存時 (つまり挿入や更新) [[yii\db\ActiveRecord|アクティブレコード]] モデルの
  185. タイムスタンプ属性の自動更新をサポートします
  186. まず使用しようと考えている [[yii\db\ActiveRecord|アクティブレコード]] クラスにこのビヘイビアをアタッチします:
  187. ```php
  188. namespace app\models\User;
  189. use yii\db\ActiveRecord;
  190. use yii\behaviors\TimestampBehavior;
  191. class User extends ActiveRecord
  192. {
  193. // ...
  194. public function behaviors()
  195. {
  196. return [
  197. [
  198. 'class' => TimestampBehavior::className(),
  199. 'attributes' => [
  200. ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
  201. ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
  202. ],
  203. ],
  204. ];
  205. }
  206. }
  207. ```
  208. 上のビヘイビア構成はレコードが:
  209. * 挿入されるときビヘイビアは現在のタイムスタンプを `created_at` `updated_at` 属性に割り当てます
  210. * 更新されるときビヘイビアは現在のタイムスタンプを `updated_at` 属性に割り当てます
  211. 所定の位置にそのコードを使用するともし `User` オブジェクトを設けそれを保存しようとしたらそこで
  212. `created_at` `updated_at` が自動的に現在のタイムスタンプで埋められます
  213. ```php
  214. $user = new User;
  215. $user->email = 'test@example.com';
  216. $user->save();
  217. echo $user->created_at; // 現在のタイムスタンプが表示される
  218. ```
  219. [[yii\behaviors\TimestampBehavior|TimestampBehavior]] 指定された属性に現在のタイムスタンプを割り当てて
  220. それをデータベースに保存する便利なメソッド [[yii\behaviors\TimestampBehavior::touch()|touch()]] を提供します
  221. ```php
  222. $user->touch('login_time');
  223. ```
  224. ビヘイビアとトレイトの比較 <span id="comparison-with-traits"></span>
  225. ----------------------
  226. ビヘイビアは主となるクラスにそのプロパティやメソッドを注入するという点で [トレイト](http://www.php.net/traits)
  227. に似ていますがこれらは多くの面で異なります以下に説明するようにそれらは互いに長所と短所を持っています
  228. それらは代替手段というよりもむしろ相互補完関係のようなものです
  229. ### ビヘイビアを使う理由 <span id="pros-for-behaviors"></span>
  230. ビヘイビアは通常のクラスのように継承をサポートしていますいっぽうトレイトは
  231. 言語サポートされたコピー&ペーストとみなすことができますトレイトは継承をサポートしません
  232. ビヘイビアはコンポーネントクラスの変更を必要とせずコンポーネントに動的にアタッチまたはデタッチすることが可能ですトレイトを使用するにはトレイトを使ってクラスのコードを書き換える必要があります
  233. ビヘイビアは構成可能ですがトレイトは不可能です
  234. ビヘイビアはイベントに応答することでコンポーネントのコード実行をカスタマイズできます
  235. 同じコンポーネントにアタッチされた異なるビヘイビア間で名前の競合がある場合その競合は自動的に
  236. 先にコンポーネントにアタッチされたものを優先することで解消されます
  237. 別のトレイトが起こした名前競合の場合影響を受けるプロパティやメソッドの名前変更による手動での解決が必要です
  238. ### トレイトを使う理由 <span id="pros-for-traits"></span>
  239. ビヘイビアは時間もメモリも食うオブジェクトなのでトレイトはビヘイビアよりはるかに効率的です
  240. トレイトは言語構造であるためIDE との相性に優れています