Автор Тема: Изменение порядка отображения материала на сайте  (Прочитано 17341 раз)

crazy_man

  • Пользователь
  • **
  • Сообщений: 68
Всем доброго. Подскажите пожалуйста тупому  :) Как грамотно сделать изменение порядка отображения материала на сайте..
 Имеется админка, в которой хочу прикрутить чтоб админ мог определять в каком порядке юзер видит материал..

 Хочу сделать листбокс в котором перечислены материалы, и при апдейте в таблицу записывался нужный order. Вся проблема в пересчете order\'ов

 Сейчас зделано так:
 листбокс: \"Порядок отображения материала на сайте (после)\", value в котором равно индексу материала, т.е.Код PHP
Код: php
    select id, name from material order by position -> 

При выборе материала из списка я конвертирую id в order и прибавляю к нему единицу:

Код: php
 
list($order)=mysql_fetch_array(mysql_query(\"select position from material where id=\".(int)$_POST[order]));
$order++;

Имено так (в листбоксе материалы расположены не по order, а по id) я сделал потому, что сейчас колока order у всех материалов = 0.

 Впринципе, на первый взгляд работать будет. Но косячно. Будут поялвятся материалы с дублирующимся значением order, а это не есть хорошо.

 Как бы избежать дублирования (одинаковых значений) в order ? Или вообще как правильно это сделать ?

Уже весь мозг себе сломал)))

nlive

  • Гость
Ухх... Прежде всего тебе нужно заполнить колонку order (сделать это можно через ROWNUM, но т.к. в MySQL нет такой ф-ции можно изобрести простой счетчик записей )

Сделать это можно так:
Код: sql
set @rownum:=0;
update services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services order by services.position) p
SET s.position = p.rownum
WHERE s.id = p.id

Так... Это сделалали. Теперь для этой задачи нам нужно знаю текущую ($oldpos) и новую ($newpos = у тебя order походу) позиции материала.
Ну текущую я думаю как узнать объяснять  не нужно )))

А теперь сравниваем. Если новая позиция меньше текущей, то запрос будет следующим:
Код: sql
set @rownum:=0;
select p.rownum, s.id, s.name, s.position from services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p WHERE (s.id = p.id and s.position = p.rownum and s.position >= 2)
где rownum = это счетчик записей

т.к. нам надо впихнуть новую запись, то новая позиция у нас будет s.position = p.rownum + 1:
Код: sql
set @rownum:=0;
update services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p SET s.position = p.rownum + 1 WHERE (s.id = p.id and s.position = p.rownum and s.position >= 2)

Если же новая позиция больше текущей, то делаем тоже самое, только к rownum ничего отнимать и прибавлять не нужно:
Код: sql
set @rownum:=0;
update services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p SET s.position = p.rownum WHERE (s.id = p.id and s.position = p.rownum+1 and s.position <= 5)

Проверка:
Код: sql
set @rownum:=0;
select p.rownum, s.id, s.name, s.position from services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p WHERE (s.id = p.id and s.position = p.rownum+1 and s.position <= 5)

Это всё хорошо, только в php эти запросы использовать не очень удобно :) Упростим:
Итак, мы знаем что:
Если новая позиция больше или равна текущей, то к счетчику ничего не прибавляем, т.е. set s.position = p.rownum + 0) [если oldpos=2, newpos=5]
Если новая позиция меньше текущей, то к позиция=счетчику+1, т.е. set s.position = p.rownum + 1) [в случае oldpos=5, newpos=2]
Также поступаем и новой записью - счеткик+1 и oldpos в таком случае будет max(s.position)

Теперь собственно сам запрос. Сначала селект
Код
set @rownum:=0;
select p.rownum, s.id, s.name, s.position from services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p WHERE (s.id = p.id  and s.position between least(2,5) and GREATEST(2,5))

Потом апдейт:
Код: sql
set @rownum:=0;
update services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p
set s.position = p.rownum + 1 WHERE (s.id = p.id and s.position between least(2,5) and GREATEST(2,5))

или так:
Код: sql
set @rownum:=0;
update services s, (SELECT @rownum:=@rownum+1 rownum, services.id FROM services WHERE services.id !=27 order by services.position) p
set s.position = p.rownum + {$pos} WHERE (s.id = p.id and s.position between least({$oldpos},{$newpos}) and GREATEST({$oldpos},{$newpos}))

nlive

  • Гость
Ещё есть вариант reorder со стрелочками, я не пробовал, но судя по коду  - он вполне жизнеспособный

Код: php
// $_GET[\'action\'] will indicate up/dn
 $action = isset($_GET[\'action\']) ? $_GET[\'action\'] : false; // condition input and set default
 // $_GET[\'id\'] is the id to move up/dn
 $id = isset($_GET[\'id\']) ? (int)$_GET[\'id\'] : false; // condition input and set default
 if(!$id){
 die(\"No id supplied\");
 }
 if($action <> \"up\" && $action <> \"dn\"){
 die(\"Invalid action selected\");
 }

 list($get_position)=mysql_fetch_array(mysql_query(\"SELECT position FROM $table_name[0] WHERE id = $id\"));
 
 if($action == \"up\"){
    // get the id and position of that and the next lower position
    $query = \"SELECT id, position FROM $table_name[0] WHERE position <= $get_position ORDER BY position DESC LIMIT 2\";
 } else {
    // get the id and position of that and the next higher position
    $query = \"SELECT id, position FROM $table_name[0] WHERE position >= $get_position ORDER BY position LIMIT 2\";
 }
 
 $result = mysql_query($query)
 // test how many rows (if less than 2, there is no locaiton to move to)
 if(mysql_num_rows($result) < 2){
    echo \"You are already at the limit
\";
 } else {
     // move up/dn one by swapping the position values
     $row1 = mysql_fetch_assoc($result); // row1
     $row2 = mysql_fetch_assoc($result); // row2
     // update row1 (with row2\'s position value)
     $query = \"UPDATE $table_name[0] SET position = {$row2[\'position\']} WHERE id = {$row1[\'id\']}\";
     $result = mysql_query($query)
     // update row2 (with row1\'s position value)
     $query = \"UPDATE $table_name[0] SET position = {$row1[\'position\']} WHERE id = {$row2[\'id\']}\";
     $result = mysql_query($query)
    }
 }