Поведение дерева: как быстро изменить порядок существующих данных по определенному полю? - PullRequest
3 голосов
/ 18 марта 2011

У меня есть приложение CakePHP с моделью категории, которая действует как дерево.Я импортировал ~ 100 категорий через CSV-файл.

Я хочу иметь возможность быстро переупорядочить все категории по именам, чтобы мое представление индекса было упорядочено правильно.reorder метод из дерева поведения :

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

Но он ничего не делает.Я что-то здесь упускаю?

Спасибо:)

Ответы [ 3 ]

4 голосов
/ 25 июля 2013

Просто напоминание: метод reorder() из поведения дерева изменяет только поля left и right дерева, следуя логике MPTT (что тип дерева, используемого этим поведением). Это не заставляет все find() в этой модели волшебным образом доставлять порядок, определенный вашим reorder() методом. Вам все еще нужно передать параметр order в параметрах find(), чтобы фактически использовать обновленные левое и правое значения.

Предположим, вы используете имена столбцов по умолчанию, используемые TreeBehavior: lft для поля left и rght для поля right . После запуска метода reorder(), указанного в вопросе, для передачи упорядоченных данных из вашей Модели в View, вы должны использовать что-то вроде:

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

Конечно, заменив тип find, если вы хотите использовать что-то другое, чем 'all'.

Упорядочение по Category.lft фактически покажет вам порядок, который вы получите, выполнив поиск в глубину слева направо, а не произвольный порядок, определенный базой данных, как если бы у вас не было параметра order, или если вы использовали простой 'order' => 'Category.name' в параметрах find, который игнорировал бы древовидную структуру.

П.С .: Я знаю, что этому вопросу 2 года, но поскольку никто не объяснил, что на самом деле делает reorder() , я думаю, что это было бы полезно.

4 голосов
/ 31 мая 2011

Я только что изучил это и пришел к выводу, что невозможно упорядочить результаты в методе generatetreelist() - по крайней мере, нет простого способа без циклического перемещения и ручного перемещения каждого узла.Лучший способ добиться этого - использовать обычный метод find с первым аргументом «threadaded», тогда вы можете применять порядок SQL, как и при любом запросе.У меня есть этот метод в моей модели Category:

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

Это возвращает мне массив всех моих родительских категорий в алфавитном порядке, с ключом 'children', содержащим другой массив всех детей этой категории, в алфавитном порядке.заказать тоже!Я использую contain => false, чтобы сократить возвращаемые данные (в потоке возвращаются данные о родительском узле каждого, что нам не нужно знать), вы можете изменить его, чтобы включить дополнительные данные, если это необходимо.

Я понимаю, что это не на 100% то же самое, что generatetreelist(), но это, конечно, аккуратнее и намного гибче, когда вы контролируете выход.Если вам действительно нужно эмулировать поведение 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 голос
/ 08 октября 2013

Если вы используете помощник TreeLi для преобразования результатов generateTreeList в список UL / LI, вы можете использовать плагин TQSery jQuery для сортировки дерева (http://tinysort.sjeiti.com/).

...