読者です 読者をやめる 読者になる 読者になる

ITの隊長のブログ

ITの隊長のブログです。いや、まだ隊長と呼べるほどには至っていないけど、日々がんばります。CakePHPとPlayFrameworkを使って仕事しています。最近はAngular2をさわりはじめたお(^ω^ = ^ω^)

【CakePHP】Behaviorの使い方をおさらい

CakePHP PHP

スポンサードリンク

いい加減にしてもらおうか!!!

当時、私は就業中に頭のなかでそう叫んだ。

なんか小説みたいな出だしですが、メモしていないことってだいたい記憶の中から消えてしまいます。

私はこのブログをよくメモ代わりに使っていますが、ここに載っていないことって優先事項順で技術系なことは消えていってしまいます。

で、CakePHPのBehaviorですよ。使い方ですよ。

もうググッて5〜6回目だと思います(こういうことは覚えているんだよね。。。)。いい加減覚えようと思いますのでメモ

Behavior(CakePHP)とは?

たまにはドキュメントを読んでみましょうかね。

http://book.cakephp.org/2.0/ja/models/behaviors.html

モデルのビヘイビアは、CakePHP のモデルに定義された機能のうちいくつかをまとめるひとつの方法です。 これを利用すると、継承を必要とせずに、典型的な挙動を示すロジックを分割し再利用することができます。 例としてはツリー (tree) 構造の生成があります。ビヘイビアはモデルを拡張するシンプルな、 それでいて強力な方法を提供し、単純なクラス変数を定義することで、モデルに機能を追加することができます。 これによりビヘイビアがモデルから(ビヘイビアがモデリングしたり異なるモデル同士が必要とすると推定できる) あらゆる余分な(要件定義に含まれないかもしれない)重みを取り除くことができます。

要はModel用のComponentって感じですかね。いままでModel側に記述することはあんまりなかったけど、「Model fat」って考え方を知って今はModelに多く記述するようになりました。なので、Behaviorもよく使うとね。

こう使う

~/app/Model/Behavior/ディレクトリにクラスを配置してください。

<?php

/**
 * Date Util コンポーネント
 */
class DateUtilBehavior extends ModelBehavior {

  /**
   * yyyy-mm-dd を入力して、yyyyを返す
   * 
   * @param Model $model
   * @param type $date
   */
  public function getYear(Model $model, $date) {
    return date('Y', strtotime($date));
  }
}

名前は任意 + Behavior . phpって感じですね。

また、継承でModelBehaviorも忘れないで。

Behavior内のメソッドの第一引数は呼び元のModelのObjectが自動で入ります。呼び元では記述しなくて良いですが、Behaviorのメソッドには記述しなければなりませんので、注意です。今回ハマりました。よくハマると思います。

呼び出し方

使用したいModelでこう記述します。

<?php

/**
 * 日報詳細
 */
class DailyDetail extends AppModel {

  public $name = 'DailyDetail';
  public $actsAs = array('DateUtil'); // 呼び出すBehaviorの名前を記述

  /**
    * 過去日付は取得しない
    */
  public function findNotPastDate() {
    // いろいろ省略
    $this->getYear('2015/01/01');
    // いろいろ省略
  }
}

まず$actsAsというメンバー変数に使用したいBehaviorの名前を記述します。この時は名前にあるBehaviorは必要ないので、削除してください。

で、使用したい箇所で$this->getYear('2015/01/01')と記述すれば、使用することができます。

Behaviorを2つ用意して、その中に同じ名前のメソッドがあった時の挙動

ふと思ったこと。BehaviorってComponentみたいに明示的に使用するBehaviorを選択できないよね?

だとすると、違うBehaviorで同じ名前のメソッドを使う場合、どうなるのかな?

<?php

class DailyDetail extends AppModel {

  public $actsAs = array('DateUtil', 'DateUtil2'); // どっちのBehaviorもgetYear()を持っている。

  public function test() {
    $this->getYear('2015/01/01'); // どのBehaviorのgetYear() ?
  }
}

試してみた

上に書いたソースで試すと。動いた!

が、どうやらDateUtil2Behaviorは呼ばれていない。

Behaviorの呼び出しの記述の順を逆にしてみる

<?php
 public $actsAs = array('DateUtil2', 'DateUtil');

こんな感じ。

すると。。。おお! DateUtil2Behaviorメソッドが呼ばれました。

結論

同じメソッド名は用意しないほうがいい。

これ回避する方法あるかな。namespaceとか使うといけるのかな?よくわかっていないけど。

まとめ

もうこれでいいでしょう。覚えたかな。俺よ。