Skip to content
Advertisement

How to get next and previous id on CodeIgniter3?

I have the following DB.

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

As you can see, the ID is missing a tooth.

so you cannot get a valid previous or next ID by simply adding or subtracting 1 to the current ID

In SQL, to get a valid back and forth ID, I would write the following.

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

I want to get this kind of record retrieval in the way by CodeIgniter3 styles. How can I write it as codeigniter3 active record?

@sajushko

Thanks for the reply. I have confirmed that it works as I intended.

But what I want to know is how to write it in ActiveRecord of CodeIgniter3 instead of SQL statements.

Specifically, it’s something like this.

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

Since writing SQL statements directly into business logic is a cause of SQL injection, we want to write them using a wrapper function.

Advertisement

Answer

well, I figured out how to write it as codeigniter3 style, like this.

Please let me know any other code more cool than I.

    /**
     * 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"
    }
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement