ITの隊長のブログ

ITの隊長のブログです。Rubyを使って仕事しています。最近も色々やっているお(^ω^ = ^ω^)

【CakePHP】Model->bindModel()の罠(?)

スポンサードリンク

罠かどうかわかりませんが、前に一度こんなハマりがありました。

<?php

$this->loadModel('Post');
// Category Modelをbindする
$this->Post->bindModel(
  array(
    'hasOne' => array(
      'Category' => array(
        'className'  => 'Category',
        'foreignKey' => 'posts_id'
      )
    )
  )
);
// PostとCategoryのデータをGet!
$data = $this->Post->find('all');

// Postのみ。なぜ?
$data2  = $this->Post->find('all');

bindModel()は、一度実行すると設定が消える(?)フローになっているっぽい。なので、使用したい時に毎回実行しなければならない。

めんどくさいので、私はfunctionにしました。

<?php

class Post extends AppModel {
  public function bindModelCategory() {
    $this->bindModel(
      array(
        'hasOne' => array(
          'Category' => array(
            'className'  => 'Category',
            'foreignKey' => 'posts_id'
          )
        )
      )
    );
  }
}

こうすれば、一行で呼ぶことができるよね。

さて、今回のハマりポイントはこちら。アソシエーションを使ったModel->saveAll()を実行したらtrueがかえってきたけど保存ができない問題にぶち当たりました。

<?php

// データを取得
$data = $this->request->data;

// Postモデルへ保存する
$this->loadModel('Post');
$this->Post->bindModelCategory();
$flag = $this->Post->saveAll($data);
if ($flag) {
  $this->log('成功!');
} else {
  $this->log('失敗');
}

詳しくは、Postは保存できたけど、Categoryが保存できてなかった。アソシエーションがシカトされている感じ?

CakeのModel.phpを読んでいるとあたっていたようで何故かアソシエーションが効いていない。というか設定されていない。

(´・ω・`)

ますますハテナに。

というわけで、困ったときのドキュメント。

http://book.cakephp.org/2.0/ja/models/associations-linking-models-together.html#dynamic-associations

注釈 bindModel()、unbindModel() を使って、アソシエーションの追加、削除をすると 2つ目のパラメータに false をセットしない限り、次の1回の find だけに適用されます。 2つ目のパラメータに false がセットされていれば、bindMode()、unbindMode() で 設定された情報は残ります。

ジーザス(°ω° falseを渡せばすべてうまくいったのか!

なぜsaveAll()で外されるのか、まだ良くわかっていませんが、とりあえず中で初期設定を読みにいっていることがわかりましたので、さっき作った関数を改良。

<?php

class Post extends AppModel {
  public function bindModelCategory($bool = true) {
    $this->bindModel(
      array(
        'hasOne' => array(
          'Category' => array(
            'className'  => 'Category',
            'foreignKey' => 'posts_id'
          )
        )
      ),
      $bool
    );
  }
}

汎用にするために初期値はtrueにしてあげて、falseを渡してあげたら永続的にするって感じかな。

また永続にすると解除することも考えないといけないので、unbindModel()も用意してあげましょう。

これでできた! 午前が全部奪われた。。。orz