将数组绑定到包含带有 WHERE ... IN(?) 的 SQL 的 CodeIgniter query() 中的占位符

发布于 2024-10-20 10:53:37 字数 1065 浏览 0 评论 0原文

我正在尝试将数组传递给具有查询的模型。我不确定如何正确传递数组,或者是否必须以某种方式操作数组。

我有这个数组:

Array
(
    [0] => 1
    [1] => 2
)

我有一个带有此行的控制器:

$ratings = $this->login_model->get_ratings($mechanicIds);   // get the mechanic ratings

我有这个模型:

function get_ratings($mechanicId)
{
    $sql = "select m.mechanic_id, 
                   m.mechanic_name, 
                   m.city, 
                   m.state, 
                   count(mr.rating_id) as num_ratings, 
                   round(avg(mr.rating_id),2) avg_rating
            from mechanic m, mechanic_rating mr, rating r
            where m.mechanic_id in (?)
                and m.mechanic_id = mr.mechanic_id
                and mr.rating_id = r.rating_id";
        
    $query = $this->db->query($sql, $mechanicId);
            
    if ($query->num_rows() > 0) {
        return $query->result_array();
    } else {
        return false;
    }
}

它实际上返回结果,但问题是它只返回结果 1 行,而它应该返回 2 行,因为我的数组中有 2 个结果。有人知道我做错了什么吗?

I'm trying to pass an array to a model which has a query. I'm not sure how to correctly pass the array or if I have to manipulate the array somehow.

I have this array:

Array
(
    [0] => 1
    [1] => 2
)

I have a controller with this line:

$ratings = $this->login_model->get_ratings($mechanicIds);   // get the mechanic ratings

I have this model:

function get_ratings($mechanicId)
{
    $sql = "select m.mechanic_id, 
                   m.mechanic_name, 
                   m.city, 
                   m.state, 
                   count(mr.rating_id) as num_ratings, 
                   round(avg(mr.rating_id),2) avg_rating
            from mechanic m, mechanic_rating mr, rating r
            where m.mechanic_id in (?)
                and m.mechanic_id = mr.mechanic_id
                and mr.rating_id = r.rating_id";
        
    $query = $this->db->query($sql, $mechanicId);
            
    if ($query->num_rows() > 0) {
        return $query->result_array();
    } else {
        return false;
    }
}

It actually returns results, but the problem is it only returns the results 1 row when it should be returning 2 since there are 2 results in my array. Anyone know what I'm doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

古镇旧梦 2024-10-27 10:53:37

我发现这个问题很有帮助。

下面是我使用的代码。

包含此的控制器:

                $mIds_size = count($mIds);
                $i = 1;

                foreach($mIds as $row)
                {
                    if($i == $mIds_size)
                    {
                        $mechanicIds .= $row;
                    }
                    else
                    {
                        $mechanicIds .= $row.', ';
                    }
                    $i++;
                }

                $ratings = $this->login_model->get_ratings($mechanicIds);   // get the mechanic ratings 

包含此的模型:

    function get_ratings($mechanicId)
    {

        $this->db->escape($mechanicId);

        $sql = "select m.mechanic_id, 
                       m.mechanic_name, 
                       m.city, 
                       m.state, 
                       count(mr.rating_id) as num_ratings, 
                       round(avg(mr.rating_id),2) avg_rating
                from mechanic m, mechanic_rating mr, rating r
                where m.mechanic_id in ($mechanicId)
                and m.mechanic_id = mr.mechanic_id
                and mr.rating_id = r.rating_id
                group by mechanic_id";

        $query = $this->db->query($sql, $mechanicId);

        if($query->num_rows() > 0)
        {
            return $query->result_array();
        }
        else
        {
            return false;
        }
    }

I found this question which helped.

Below is the code I used.

Controller that contains this:

                $mIds_size = count($mIds);
                $i = 1;

                foreach($mIds as $row)
                {
                    if($i == $mIds_size)
                    {
                        $mechanicIds .= $row;
                    }
                    else
                    {
                        $mechanicIds .= $row.', ';
                    }
                    $i++;
                }

                $ratings = $this->login_model->get_ratings($mechanicIds);   // get the mechanic ratings 

Model which contains this:

    function get_ratings($mechanicId)
    {

        $this->db->escape($mechanicId);

        $sql = "select m.mechanic_id, 
                       m.mechanic_name, 
                       m.city, 
                       m.state, 
                       count(mr.rating_id) as num_ratings, 
                       round(avg(mr.rating_id),2) avg_rating
                from mechanic m, mechanic_rating mr, rating r
                where m.mechanic_id in ($mechanicId)
                and m.mechanic_id = mr.mechanic_id
                and mr.rating_id = r.rating_id
                group by mechanic_id";

        $query = $this->db->query($sql, $mechanicId);

        if($query->num_rows() > 0)
        {
            return $query->result_array();
        }
        else
        {
            return false;
        }
    }
嗼ふ静 2024-10-27 10:53:37

将此行更改

$query = $this->db->query($sql, $mechanicId);

为:

$query = $this->db->query($sql, array(implode(', ',$mechanicId)));

按照手册

Change this line:

$query = $this->db->query($sql, $mechanicId);

to this:

$query = $this->db->query($sql, array(implode(', ',$mechanicId)));

as per the manual

亚希 2024-10-27 10:53:37

要将数组传递到 IN 条件的原始查询(不是使用辅助方法构建)中,请使用 ? 占位符而不用括号括起来。

将数组绑定到占位符时,必须在数组内部声明数组。换句话说,query() 方法的“parameters”(第二个)参数需要一个与 SQL 字符串中的每个 ? 相关的数组。由于第一个 ? 绑定到数组,因此 $mechanicIds 数组必须声明为“parameters”参数的第一个元素。我已经测试了此建议在我有权访问的 CodeIgniter3 实例中成功运行。

$sql = "SELECT m.mechanic_id, 
               m.mechanic_name, 
               m.city, 
               m.state, 
               COUNT(mr.rating_id)         AS num_ratings, 
               ROUND(AVG(mr.rating_id), 2) AS avg_rating
        FROM mechanic        AS m,
             mechanic_rating AS mr,
             rating          AS r
        WHERE m.mechanic_id IN ?                            /* <--- here */
          AND m.mechanic_id = mr.mechanic_id
          AND mr.rating_id = r.rating_id";

$query = $this->db->query($sql, [$mechanicIds]);

DB_driver.php 核心文件在 compile_binds() 中包含这部分代码,它对数组中的每个值进行转义,并在返回 sql 字符串之前将逗号连接的字符串括在括号中。

...
do
{
    $c--;
    $escaped_value = $this->escape($binds[$c]);
    if (is_array($escaped_value))
    {
        $escaped_value = '('.implode(',', $escaped_value).')';
    }
    $sql = substr_replace($sql, $escaped_value, $matches[0][$c][1], $ml);
}
while ($c !== 0);
...

To pass an array into a raw query (not built with helper methods) for an IN condition, use the ? placeholder without wrapping in parentheses.

When binding the array to the placeholder, you must declare your array inside of an array. In other words, the "parameters" (2nd) argument of query() method expects an array which relates to each ? in the SQL string. Because the first ? is bound to an array, the $mechanicIds array must be declared as the first element of the "parameters" argument. I have tested this advice to work successfully in a CodeIgniter3 instance that I have access to.

$sql = "SELECT m.mechanic_id, 
               m.mechanic_name, 
               m.city, 
               m.state, 
               COUNT(mr.rating_id)         AS num_ratings, 
               ROUND(AVG(mr.rating_id), 2) AS avg_rating
        FROM mechanic        AS m,
             mechanic_rating AS mr,
             rating          AS r
        WHERE m.mechanic_id IN ?                            /* <--- here */
          AND m.mechanic_id = mr.mechanic_id
          AND mr.rating_id = r.rating_id";

$query = $this->db->query($sql, [$mechanicIds]);

The DB_driver.php core file contains this portion of code in compile_binds() which escapes each value in the array and wraps the comma-joined string in parentheses before returning the sql string.

...
do
{
    $c--;
    $escaped_value = $this->escape($binds[$c]);
    if (is_array($escaped_value))
    {
        $escaped_value = '('.implode(',', $escaped_value).')';
    }
    $sql = substr_replace($sql, $escaped_value, $matches[0][$c][1], $ml);
}
while ($c !== 0);
...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文