如何在 CodeIgniter 3 中获取下一个和上一个 ID?

How to get next and previous id on CodeIgniter3?

我有以下数据库。

+----+------+
| id | name |
+----+------+
|  1 | aaaa |
|  2 | bbbb |
|  4 | dddd |
|  7 | gggg |
+----+------+

如您所见,身份证少了一颗牙。

因此您无法通过简单地在当前 ID 上加或减 1 来获得有效的上一个或下一个 ID

在SQL中,为了得到一个有效的来回ID,我会这样写。

SELECT
  (SELECT id FROM topics WHERE id < tmp.id ORDER BY id DESC LIMIT 1) AS prev_id,
  (SELECT id FROM topics WHERE id > tmp.id ORDER BY id ASC LIMIT 1) AS next_id
FROM
  topics AS tmp
WHERE
  id = 1
;

+---------+---------+
| prev_id | next_id |
+---------+---------+
| NULL    |       2 |
+---------+---------+

id = 2

+---------+---------+
| prev_id | next_id |
+---------+---------+
|       1 |       4 |
+---------+---------+

id = 4

+---------+---------+
| prev_id | next_id |
+---------+---------+
|       2 |       7 |
+---------+---------+

id = 7

+---------+---------+
| prev_id | next_id |
+---------+---------+
|       4 | NULL    |
+---------+---------+

id = 999

empty set

我想通过CodeIgniter3风格的方式获取这种记录检索。 我怎样才能把它写成 codeigniter3 活动记录?

@sajushko

感谢您的回复。 我已确认它按我的预期工作。

但是我想知道的是如何在CodeIgniter3的ActiveRecord中写,而不是SQL语句

具体是这样的

    public function getBothIds($id)
    {
        $tableName = "topics";
        $columnName = "id";
        $asColumnNamePrev = "prev_" . $columnName;
        $asColumnNameNext = "next_" . $columnName;

        $query = $this->db
                      ->select_min($columnName, $asColumnNamePrev) // how to write where inside of select_min?
                      ->select_max($columnName, $asColumnNameNext) // how to write where inside of select_max?
                      ->where($columnName, $id)
                      ->get($tableName)
                      ->row();
        return $query;
    }

由于将 SQL 语句直接写入业务逻辑是 SQL 注入的原因,我们希望使用包装函数来编写它们。

这可能会如您所愿

CREATE TABLE `topics` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(250),
    PRIMARY KEY (`id`)
);  

INSERT INTO `topics` VALUES (1, 'aaaa');
INSERT INTO `topics` VALUES (2, 'bbbb');
INSERT INTO `topics` VALUES (4, 'dddd');
INSERT INTO `topics` VALUES (7, 'gggg');

SELECT
    (SELECT MAX(`id`) FROM `topics` WHERE id < `tmpTopics`.`id`) AS `prev_id`,
    (SELECT MIN(`id`) FROM `topics` WHERE id > `tmpTopics`.`id`) AS `next_id`
FROM
    `topics` AS `tmpTopics`
WHERE
    `id` = 1;

这里是SQLFiddle例子http://sqlfiddle.com/#!9/83968c/8

好吧,我想出了如何将它写成 codeigniter3 风格,就像这样。

请让我知道任何其他比我更酷的代码。

    /**
     * Get Prev And Next Id
     *
     * @param  integer|string $id e.g. 1
     * @return stdClass|null
     */
    public function getNeighborIds($id)
    {
       /**
        * SELECT
        *     (SELECT MAX(`id`) FROM `topics` WHERE `id` < `tmp`.`id`) AS `prev_id`,
        *     (SELECT MIN(`id`) FROM `topics` WHERE `id` > `tmp`.`id`) AS `next_id`
        * FROM
        *     `topics` AS `tmp`
        * WHERE
        *     `id` = 10;
        */

        $tableName = $this->tableName;
        $columnName = $this->primaryKey;
        $asColumnNamePrev = "prev_" . $columnName;
        $asColumnNameNext = "next_" . $columnName;

        $queryMin = '(SELECT MAX(' . $columnName . ') FROM ' . $tableName . ' WHERE ' . $columnName . ' < ' . 'tmp.' . $columnName . ') AS ' . $asColumnNamePrev;
        $queryMax = '(SELECT MIN(' . $columnName . ') FROM ' . $tableName . ' WHERE ' . $columnName . ' > ' . 'tmp.' . $columnName . ') AS ' . $asColumnNameNext;

        $query = $this->db
                      ->select($queryMin)
                      ->select($queryMax)
                      ->where($columnName, $id)
                      ->get($tableName . ' AS tmp')
                      ->row();
        return $query; // e.g. $query->prev_id "8" $query->next_id "11"
    }