树行为:如何通过某个字段快速重新排序现有数据?

时间:2011-03-18 11:00:43

标签: cakephp tree behavior

我有一个带有作为树的类别模型的cakephp应用程序。我通过csv文件导入了~100个类别。

我希望能够按名称快速重新排序所有类别,以便正确排序我的索引视图。

我尝试了reorder method from the Tree behavior

$this->Category->reorder(array(
'id' => null,
'field' => 'Category.name',
'order' => 'ASC'
));

但它没有做任何事情。我在这里错过了什么吗?

谢谢:)

3 个答案:

答案 0 :(得分:4)

我刚刚对此进行了研究并得出结论,不可能在generatetreelist()方法中对结果进行排序 - 至少没有简单的方法,如果没有循环并手动移动每个节点。解决这个问题的最好方法是使用普通的find方法,将第一个参数作为'threaded',然后就像任何查询一样应用SQL排序。我的分类模型中有这个方法:

public function getThreaded($conditions = array()) {
    return $this->find('threaded', array(
        'order' => 'Category.name ASC',
        'contain' => false
    ));
}

这会返回一个按字母排序的所有父类别的数组,其中'children'键包含该类别中所有子类的另一个数组,也按字母顺序排列!我使用contain => false来减少返回的数据(thread返回有关每个节点的父节点的数据,我们不需要知道),如果需要,可以改变它以包含额外的数据。

我知道这与generatetreelist()不是100%相同,但是当你控制输出时,它肯定更整洁,更灵活。如果你真的需要模仿generatetreelist()的行为,你可以像这样从上面循环遍历数组:

$treeArray = array();
foreach($category as $parent) {
    $treeArray[] = $parent['Category']['name'];
    if(!empty($parent['children']) {
        foreach($parent['children'] as $childCategory) {
            $treeArray[] = ' - '.$childCategory['Category']['name'];
        }
    }
}

希望这有帮助。

答案 1 :(得分:4)

只是提醒一下:树行为中的reorder()方法仅修改MPTT logic后面的树的字段(是此行为使用的树的类型)。它不会使该模型中的所有find()神奇地传递您的reorder()方法定义的顺序。您仍然需要在order选项中传递find()参数才能实际使用更新后的左右值。

假设您正在使用TreeBehavior使用的默认列名:lft用于左侧字段,rght用于右侧字段。运行一次问题中给出的reorder()方法后,要将模型中的有序数据传递给View,您可以使用以下内容:

$this->Category->find('all', array(
    'order' => array(
        'Category.lft' => 'ASC'
    )
));

当然,如果您想使用find之外的其他内容,请替换'all'类型。

Category.lft排序实际上会显示您从左到右进行深度优先搜索所获得的顺序 - 不是数据库定义的任意顺序,如果您没有{{1 }}参数,或者如果您在order选项中使用了一个简单的'order' => 'Category.name',它将忽略树结构。

P.S。:我知道这个问题是2年了,但是由于没有其他人解释find 实际的作用,我觉得这很有用。

答案 2 :(得分:1)

如果您使用TreeLi助手将generateTreeList的结果转换为UL / LI列表,则可以使用jQuery插件TinySort对树进行排序(http://tinysort.sjeiti.com/)。