1

我已经看到了这方面的一些变化,但主要是它们交换整行而不是该行中的一个值,而不是动态交换。

这是问题:

我有三行,每行包含以下单元格(id、title、content、display_order、visible)。id 是 auto_increment。标题和内容是手动输入的,可见是一个切换。display_order 在每行创建时设置并自动设置为最高整数并设置在堆栈的底部。

我这样设置,以便如果要手动删除这些记录中的任何一个,我可以自动重新排序堆栈(如果有 4 条记录,我删除 #2,新订单重置为 1,2,3 而不是 1 ,3,4)。

每行都有一组向上和向下箭头按钮,它们调用 move.php 并查询 id(id)、display_order(pos) 和 direction(dir)。

在 move.php 中,它使用条件来确定是向上还是向下移动记录,具体取决于方向变量的设置。

我需要编写什么 PHP 代码来获取这三个变量(id、pos、dir)并交换表格单元格 display_order 中的值:这是一个可视化表示

最初的:

id   title   pos   
-----------------
 1   slide1   1
 2   slide2   2
 3   slide3   3

在我单击记录 ID #3 的 UP 按钮后:

id   title   pos   
-----------------
 1   slide1   1
 2   slide2   3
 3   slide3   2

请注意,ID 和 POS 并不总是相同的整数

使用 davidethell 的建议,我创建了这个:

这是我创建的,但我得到的只是 echo $newPos 而不是回到 admin.php:

require ("connection.php");
    $id = $_GET['id'];
    $pos = $_GET['pos'];
    $dir = $_GET['dir'];

    if ($dir == 'up') {
        $newPos = $pos-1;
    } else {
        $newPos = $pos+1;
    }

    $fromRow = "SELECT * FROM pages WHERE display_order = ".$pos."";
    $toRow = "SELECT * FROM pages WHERE display_order = ".$newPos."";

    $reord = mysqli_query($conn, "UPDATE pages SET display_order = " . $toRow['display_order'] . " WHERE id = " . $fromRow['id']."; UPDATE pages SET display_order = " . $fromRow['display_order'] . " WHERE id = " . $toRow['id']);

    if ($reord){
        header("Location: admin.php");
    }else{
        echo $newPos;
    }

我遇到的问题是它只呼应 $newPos

更新代码:

require ("connection.php");

    $fromArray = array();
    $toArray = array();

    $id = $_GET['id'];
    $pos = $_GET['pos'];
    $dir = $_GET['dir'];

    if ($dir == 'up') {
        $newPos = $pos-1;
    } else {
        $newPos = $pos+1;
    }

    $fromRow = mysql_query("SELECT * FROM pages WHERE display_order = ".$pos."");

    $toRow = mysql_query("SELECT * FROM pages WHERE display_order = ".$newPos."");


    $reord = mysqli_query($conn, "UPDATE pages SET display_order = " . $toRow['display_order'] . " WHERE id = " . $fromRow['id']);
    $reord = mysqli_query($conn, "UPDATE pages SET display_order = " . $fromRow['display_order'] . " WHERE id = " . $toRow['id']);

    if ($reord){
        header("Location: admin.php");
    }else{
        echo $newPos;
    }

结果:回显 $newPos 而不是返回到 admin.php

4

3 回答 3

3

您可以使用此查询:

UPDATE
  yourtable INNER JOIN (
    SELECT
      MAX(yourtable.pos) pos_prec,
      curr.pos pos_curr
    FROM
      yourtable INNER JOIN
      (SELECT pos FROM yourtable WHERE id=3) curr
      ON yourtable.pos<curr.pos
    GROUP BY
      curr.pos) cp ON yourtable.pos IN (cp.pos_prec, cp.pos_curr)
SET
  pos = CASE WHEN pos=cp.pos_curr
             THEN pos_prec ELSE pos_curr END

有点复杂,但它会将 ID=3 的位置的值与前一项的位置的值交换,即使有间隙。

在此处查看小提琴。

编辑

如果没有间隙,您可以简单地使用它来移动 ID#3 UP:

UPDATE
  yourtable INNER JOIN (SELECT pos FROM yourtable WHERE id=3) curr
  ON yourtable.pos IN (curr.pos, curr.pos-1)
SET
  yourtable.pos = CASE WHEN yourtable.pos=curr.pos
                       THEN curr.pos-1 ELSE curr.pos END;

并且只需使用 +1 而不是 -1 向下移动(如果需要,可以将 UP 和 DOWN 组合在一个查询中)。

PHP 代码

这是使用 PHP 和 mysqli,并假设给出的位置:

<?php
$mysqli = new mysqli("localhost", "username", "password", "test");

$pos = 3;
$dir = 'down';

if ($dir == 'up') { $newPos = $pos-1; } else { $newPos = $pos+1; }

if ($stmt = $mysqli->prepare("
  UPDATE
    yourtable
  SET
    pos = CASE WHEN yourtable.pos=?
               THEN ?
               ELSE ? END
  WHERE
    pos IN (?, ?)
    AND (SELECT * FROM (
         SELECT COUNT(*) FROM yourtable WHERE pos IN (?,?)) s )=2;"))
{

    $stmt->bind_param("iiiiiii", $pos, $newPos, $pos, $pos, $newPos, $pos, $newPos); 
    $stmt->execute();
    printf("%d Row affected.\n", $stmt->affected_rows);

    $stmt->close();
}
$mysqli->close();
?>

(我还添加了一个检查,如果尝试向上移动第一个位置,或者向下移动最后一个位置,它将什么都不做)。

于 2013-04-08T19:21:20.333 回答
1

假设每行数据都有一个 $row 对象,只需执行以下操作:

if ($dir == 'up') {
    $fromRow = $row2;
    $toRow = $row1;
}
else {
    $fromRow = $row1;
    $toRow = $row2;
}
$sql = "UPDATE mytable SET pos = " . $toRow['pos'] . " WHERE id = " . $fromRow['id'];
// now execute your SQL however you want in your framework
$sql = "UPDATE mytable SET pos = " . $fromRow['pos'] . " WHERE id = " . $toRow['id'];
// now execute your SQL however you want in your framework

将其放入某种函数或类中以使其可重用。

编辑:根据您的编辑,您似乎没有在查询中获取足够的信息。他们应该是:

$fromRow = mysql_query("SELECT * FROM pages WHERE display_order = ".$pos."");

$toRow = mysql_query("SELECT * FROM pages WHERE display_order = ".$newPos."");

您只选择了 id 字段,但随后您尝试使用 display_order 字段。

于 2013-04-08T19:07:00.600 回答
0

我不会给你写 PHP 代码。但我会给你SQL:

假设如果幻灯片的位置应该升高 1,则 $delta 为 +1,如果幻灯片的位置应降低 1,则为 -1。$id 是幻灯片的 id。哦,让我们假设该表称为 slides_table。

您将需要 2 个查询:

update slides_table set pos = pos + $delta where id = $id;
update slides_table set pos = pos - $delta where pos = (select pos from slides_table where id=$id) and id != $id
于 2013-04-08T19:08:49.857 回答