codeigniter 4 mysql 查询生成器从自身获取子数据

codeigniter 4 mysql query builder get subdata from itself

[更新]

错误现在消失了,但是来自 codeigniter 4 查询构建器的数据结果都具有相同的 id 值,这与 phpmyadmin 中的不同。如果我使用 $builder 方法,它现在会给出预期的结果,但我仍然希望能够尽可能正确地充分使用查询生成器..


我有一个这样的mysqltable

id | nama | hari
-----------------
1  | AAA  | 1
2  | AAA  | 2
3  | AAA  | 3
4  | AAA  | 4
5  | AAA  | 5
6  | BBB  | 1
7  | BBB  | 2
8  | BBB  | 3

当我得到一个参数id1时,我只想得到行号1-5。当我在 phpmyadmin

中使用这个 sql 时它有效
select m.* 
from m_rute m
join (
    select m1.*
    from m_rute m1
    where m1.id = 1
) mt on mt.nama_rute = m.nama_rute

然后我尝试使用 codeigniter 4 的查询构建器“翻译”它,但是当我在邮递员上测试它时,它提供了一组数据,其中所有 id 字段都相同,这与 phpmyadmin 中的不同结果。

控制器

public function show($id = null)
{
    $db = \Config\Database::connect();
    $builder = $db->table('m_rute as m');
    $builder->select('m.*')->where('m.id', $id);
    $subquery = $builder->getCompiledSelect();

    // this works but wouldn't a fully proper query builder seem nicer?
    //////////////
    // $builder->select('m.*')
    //     ->join('('.$subquery.') as m1', 'm1.nama_rute = m.nama_rute')
    //     ;
    // $q = $builder->get();
    // $data = $q->getResultArray();

    $model = new MRuteModel();

    $model->join('('.$subquery.') as t', 't.nama_rute = m_rute.nama_rute');

    $data  = $model->findAll();

    if (!$data) {
        return $this->failNotFound('Data not found');
    }

    return $this->respond($data);
}

感谢任何帮助

解决方案 1:使用 Raw/Regular Queries

The query() function returns a database result object when “read” type queries are run which you can use to show your results. When “write” type queries are run it simply returns true or false depending on success or failure.

<?php

namespace App\Models;

use CodeIgniter\Model;

class MRuteModel extends Model
{
    public function findById(int $id)
    {
        $id = $this->db->escape($id);

        return $this->db->query("
            select m.* 
            from m_rute m
                join (
                    select m1.*
                    from m_rute m1
                    where m1.id = {$id}
                ) mt on mt.nama_rute = m.nama_rute")->getResultArray();
    }
}

解决方案 2A:使用 SQL Joins 原始查询。

join($table, $cond[, $type = ''[, $escape = null]])
   Parameters:

      $table (string) – Table name to join

      $cond (string) – The JOIN ON condition

      $type (string) – The JOIN type

      $escape (bool) – Whether to escape values and identifiers

   Returns: BaseBuilder instance (method chaining)

   Return type: BaseBuilder

Adds a JOIN clause to a query.

<?php

namespace App\Models;

use CodeIgniter\Model;

class MRuteModel extends Model
{
    public function findById(int $id)
    {
        $id = $this->db->escape($id);

        return $this->db->table('m_rute m')
            ->select("m.*")
            ->join("
            (select m1.*
                from m_rute m1
                    where m1.id = {$id}
            ) mt", 'mt.nama_rute = m.nama_rute')
            ->get()->getResultArray();
    }
}

解决方案 2B:使用 SQL Joins 和查询生成器。

getCompiledSelect()

Compiles a SELECT statement and returns it as a string.

<?php

namespace App\Models;

use CodeIgniter\Model;

class MRuteModel extends Model
{
    public function findById(int $id)
    {
        $subQuery = $this->db->table('m_rute m1')
            ->select("m1.*")
            ->where("m1.id", $id)
            ->getCompiledSelect();

        return $this->db->table('m_rute m')
            ->select("m.*")
            ->join("($subQuery) mt", 'mt.nama_rute = m.nama_rute')
            ->get()
            ->getResultArray();
    }
}

解决方案 3A:使用带闭包的 where Clause

where($key[, $value = null[, $escape = null]])
   Parameters:

      $key (mixed) – Name of field to compare, or associative array

      $value (mixed) – If a single key, compared to this value

      $escape (bool) – Whether to escape values and identifiers

   Returns: BaseBuilder instance (method chaining)

   Return type: BaseBuilder

Generates the WHERE portion of the query. Separates multiple calls with AND.

<?php

namespace App\Models;

use CodeIgniter\Model;
use CodeIgniter\Database\BaseBuilder;

class MRuteModel extends Model
{
    public function findById(int $id)
    {
        // With a closure.
        return $this->db->table('m_rute')
            ->where('nama_rute =', function (BaseBuilder $builder) use ($id) {
                return $builder->select("nama_rute")->from("m_rute")
                    ->where("id", $id);
            })
            ->get()
            ->getResultArray();
    }
}

解决方案 3B:将 where Clause 与生成器一起使用。


<?php

namespace App\Models;

use CodeIgniter\Model;

class MRuteModel extends Model
{
    public function findById(int $id)
    {
        $subQuery = $this->db->table('m_rute m1')
            ->select("m1.nama_rute")
            ->where("m1.id", $id)
            ->getCompiledSelect();

        // With a builder.
        return $this->db->table('m_rute')
            ->where("nama_rute =($subQuery)")
            ->get()
            ->getResultArray();
    }
}