1 (11 Jun 2012 04:20:37 отредактировано crazy_man)

Тема: Изменение порядка отображения материала на сайте

Всем доброго. Подскажите пожалуйста тупому  smile Как грамотно сделать изменение порядка отображения материала на сайте..
Имеется админка, в которой хочу прикрутить чтоб админ мог определять в каком порядке юзер видит материал..

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

Сейчас зделано так:
листбокс: "Порядок отображения материала на сайте (после)", value в котором равно индексу материала, т.е.Код PHP

select id, name from material order by position -> <option value='"{$id}">{$name}</option>

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

list($order)=mysql_fetch_array(mysql_query("select position from material where id=".(int)$_POST[order]));
$order++;

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

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

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

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

2

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

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

Сделать это можно так:

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 походу) позиции материала.
Ну текущую я думаю как узнать объяснять  не нужно )))

А теперь сравниваем. Если новая позиция меньше текущей, то запрос будет следующим:

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:

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 ничего отнимать и прибавлять не нужно:

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)

Проверка:

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 эти запросы использовать не очень удобно smile Упростим:
Итак, мы знаем что:
Если новая позиция больше или равна текущей, то к счетчику ничего не прибавляем, т.е. 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))

Потом апдейт:

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

или так:

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

3

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

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

// $_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<br />";
} 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)
    }
}