Страница 1 из 1

Изменение порядка отображения

Добавлено: 2011.03.08, 02:39
zbd
Приветствую!

Каким образом в Yii реализован механизм изменения последовательности записей при отображении. Например, древо каталога, необходимо один из элементов поднять/опустить вверх относительно родителя.

Re: Изменение порядка отображения

Добавлено: 2011.03.08, 04:14
mitaichik
Чисто Yii такого не делает.
Это надо реализовывать самостоятельно (я про дерево). А для сортировки - делай поле position и присваивай ему нужное значение, в defaultScopes модели пиши order => position
Есть расширение nestedSets - возможно там есть готовое, я им не пользовался.

Re: Изменение порядка отображения

Добавлено: 2011.03.08, 15:16
zbd
mitaichik писал(а):А для сортировки - делай поле position и присваивай ему нужное значение, в defaultScopes модели пиши order => position
  • В модели мы переопределяем метод defaultScopes(). А что дальше, каким образом мне указать поле (parent) в рамках которого происходит сортировка?
  • Как мне указать, что бы при создании поле увеличивалось на единицу, т.е. становился последним в последовательности?
  • Как реализована валидация порядка сортировки, что бы не получилось, что то типа 1, 2, 5, 6?
  • Какие методы реализут поднять и опустить позицию?
Всё это можно реализовать и самому, но если весь этот набор присутствует, изобретать велик не хочется :D .

Re: Изменение порядка отображения

Добавлено: 2011.04.05, 11:40
ikarushka
Присоеденяюсь к вопросам zbn.
Раз никто не ответил - по-видимому, придется изобретать велик?

Re: Изменение порядка отображения

Добавлено: 2011.04.05, 12:03
slavcodev
Я например не очень понял вопросов и не отвечал, попробую предположить что имелось виду
1)

Код: Выделить всё

public function defaultScope()
{
  return array(
    'order'=>'parent DESC',
  );
} 
2) При вставке записи, я не ищу какое там последнее число (лишний запрос), я ставлю COUNT, можно использовать MAX, т.е все средствами Mysql
3) А для чего? Чем плоха такая последовательность?
4) Собственные.

Re: Изменение порядка отображения

Добавлено: 2011.04.05, 13:38
ikarushka
mc-bear Спасибо за ответ. Вобщем-то все и прояснил.
На счет валидации последовательности. Если делать возможность для пользователя поднять и опустить позицию, скажем с помощью drag'n'drop, то важно, мне кажется, чтобы не было случаев 1, 3, 4 или 1, 3, 3.

При добавлении новой записи, лучше все-тки использовать MAX, тогда избежишь случаев 1,3,3

Про валидации последовательности у меня еще такой вопрос. Понятно, что ее надо будет отслеживать при удалении записи и после удаления переписывать значения поля position для каждой записи. Можно удалять категори, подкатегории, товары и тд и тп. Для каждой сущность свой контроллер, следовательно свой actionDelete. Как сделать так, чтобы не писать каждый раз в различных actionDelete код этой проверки.

Я старый быдлокодер и только въезжаю в ООП и у меня пока постоянные затыки на элементарных местах.

Re: Изменение порядка отображения

Добавлено: 2011.04.05, 13:45
slavcodev
в моделях есть событие onAfterDelete(), ищи в мануале.

Re: Изменение порядка отображения

Добавлено: 2011.04.05, 13:50
slavcodev
если нужно перемещать последовательность, тогда поле где хранить идишку следующей модели
тогда при перетаскивании нужно будет только поменять эти идишки у трех моделей

Re: Изменение порядка отображения

Добавлено: 2011.04.05, 14:03
ikarushka
onAfterDelete() - понял, копаю
Поясни последнее. Айдишки то зачем менять? Они постояны - меняем только position. Или ты про перетаскивание субкатегории из одной категории в другую? Это кстати, тоже надо посоображать как делать.

Re: Изменение порядка отображения

Добавлено: 2011.04.05, 14:22
slavcodev
не ИД модели менять! именно position, только в него уже нужно ставить ИД предстоящей модели.

Re: Изменение порядка отображения

Добавлено: 2011.04.05, 15:40
ikarushka
Нет не могу понять. Нарисовал себе схемы - все равно не понимаю зачем надо "связывать" id и position. id никогда не меняется, а значение position может быть любым. Если будет время и желание - объясни подробнее.
С событиями вроде разобрался - мощная вещь. Спасибо

Re: Изменение порядка отображения

Добавлено: 2011.04.05, 15:57
ikarushka
Просто я думаю делать как то вот так: http://habrahabr.ru/blogs/jquery/70837/#comment_2031446. Другой способ пока не вырисовывается

Re: Изменение порядка отображения

Добавлено: 2011.05.15, 21:08
georgedrive
из ядра одной движки

к примеру опустить по списку вниз если сортировка ASC (от меньшего к большему)

находим запись с весом (поле weight отвечает за позицию в сортировке и по умолчанию равно id) большим чем запись , т.е. выбрать все записи с большим весом сортируя по ASC и выбрать из этого первую строчку. Далее просто меняем значения местами у исходной записи и полученной

Все просто и легко:

рабочий код

// поднимает по списку вверх
function rc_down($id,$field = 'weight'){
if ($this->desc != 'desc') {
// вес нужно уменьшить
$this->rc_swap_weight_asc($id,$field);
} else {
// вес нужно увеличить
$this->rc_swap_weight_desc($id,$field);
}
}

// опускает по списку вниз
function rc_up($id,$field = 'weight'){
if ($this->desc != 'desc') {
// вес нужно увеличить
$this->rc_swap_weight_desc($id,$field);
} else {
// вес нужно уменьшить
$this->rc_swap_weight_asc($id,$field);
}
}


// if desc == desc
// Обменивает вес указанного элемента с элементом имеющего наибольший вес среди
// элементов с меньшим весом
function rc_swap_weight_desc($id, $field) {
//echo 'rc_swap_weight_desc';
//die();
$cur_line = $this->rc_get_record($id);
$query = "
SELECT
*
FROM
".$this->doc_type."
WHERE
`$field` < ".$cur_line['weight']."
and
(rasdel='".$this->rasdel."') ".($cur_line['parent']!=''?" and (parent='".$cur_line['parent']."')":'')."
ORDER BY
`$field` DESC
LIMIT 1
";
$res = mysql_query($query) or die("up: ".mysql_error());
if (mysql_num_rows($res)>0) {
$row = mysql_fetch_array($res);
$query = "update ".$this->doc_type." set `$field`=".$row[$field]." where id=".$cur_line["id"];
$res = mysql_query($query) or die("смена веса вышестоящей строки: ".mysql_error());
$query2 = "update ".$this->doc_type." set `$field`=".$cur_line[$field]." where id=".$row["id"];
$res = mysql_query($query2) or die("смена веса текущей строки: ".mysql_error());
}
}

// if desc == asc
// Обменивает вес указанного элемента с элементом имеющего наименьший вес среди
// элементов с большим весом
function rc_swap_weight_asc($id, $field) {
//echo 'rc_swap_weight_asc';
$cur_line = $this->rc_get_record($id);
//$query = "select * from ".$this->doc_type." where `$field` > ".$cur_line[$field]." and ((rasdel='".$this->rasdel."') and (parent='".$cur_line['parent']."')) order by $field asc limit 1";
$query = "
SELECT
*
FROM
".$this->doc_type."
WHERE
`$field` > ".$cur_line['weight']."
and
(rasdel='".$this->rasdel."') ".($cur_line['parent']!=''?" and (parent='".$cur_line['parent']."')":'')."
ORDER BY
`$field` ASC
LIMIT 1
";
//echo $query;
//die();
$res = mysql_query($query) or die("up: ".mysql_error());
if (mysql_num_rows($res)>0) {
$row = mysql_fetch_array($res);
$query = "update ".$this->doc_type." set `$field`=".$row[$field]." where id=".$cur_line["id"];
$query2 = "update ".$this->doc_type." set `$field`=".$cur_line[$field]." where id=".$row["id"];
$res = mysql_query($query) or die("смена веса вышестоящей строки: ".mysql_error());
$res = mysql_query($query2) or die("смена веса текущей строки: ".mysql_error());
}
}

Re: Изменение порядка отображения

Добавлено: 2011.05.16, 00:01
coder
Ну, проблемы особо-то и нет. В grid-view можно добавлять свои кнопки и навешивать события. Потом в контроллере добавить действие move. А дальше дело техники - выбирать предыдущий/следующий объект по order и менять этот order местами. Ну, а пересчет сортировки (например при удалении), как говорилось выше, навешивать на стандартные события.