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);
}