CakePHPでTreeビヘイビアを使っているときに、条件を指定したい場合のメモです。
ソースを読む限りconditionsの指定ができないようなので、次のようにしてみました。
※未だにぼくはCakePHP1.3系を使っているので、もしかしたら2系とは異なる可能性もありますのでご注意ください。
子ノードの取得
まずカレントのlftとrghtを取得する。
$fields = array("id", "lft", "rght"); $current = $this->Hoge->read($fields, $currentId);
次に条件指定。
$conditions = array( // お好きなように・・・ // たとえばレベルの情報をもたせているなら "Hoge.level >" => 3, // 例えば1週間以内に更新されたものなら "Hoge.modified >" => date("Y-m-d H:i:s", time() - (60*60*24*7)), ); // 子ノードの取得条件 $conditions['Hoge.lft BETWEEN ? AND ?'] = array($current['Hoge']['lft'], $current['Hoge']['rght']); $results = $this->Hoge->find("all", compact("conditions"));
Treeビヘイビアの説明については↓がとても分かりやすいです。
参考:ウノウラボ by Zynga Japan: RDBで階層構造を扱うには?
上記をまとめてモデルのメソッドにすると便利ですね。
Hogeモデル
// $id にはカレントのidを指定、$optionsはfindの第2引数の配列 function getChildren($id = null, $options = array()) { if (empty($id)) { return false; } // カレントのlft,rghtを取得 $fields = array("id", "lft", "rght"); $current = $this->read($fields, $id); if (!$current) { return false; } // optionsでtypeも渡せるように if (!empty($options['type'])) { $type = $options['type']; unset($options['type']); } else { $type = "all"; } // 子ノードの取得 $options['conditions']['lft BETWEEN ? AND ?'] = array($current['Hoge']['lft'], $current['Hoge']['rght']); return $this->find($type, $options); }
こんな感じ。
親ノードの取得
Hogeモデル
function getParents($id = null, $options = array("type" => "all")) { if (empty($id)) { return false; } // カレントのlft,rghtを取得 $fields = array("id", "lft", "rght"); $current = $this->read($fields, $id); if (!$current) { return false; } // optionsでtypeも渡せるように if (!empty($options['type'])) { $type = $options['type']; unset($options['type']); } else { $type = "all"; } // 子ノードの取得 $options['conditions']['lft <'] = $current['Hoge']['lft']; $options['conditions']['rght >'] = $current['Hoge']['rght']; return $this->find($type, $options); }