Mysqli 抽象,从准备好的语句中获取数组

发布于 2024-08-14 05:38:04 字数 1353 浏览 5 评论 0原文

最近,我在一个曾经工作得很好的库中偶然发现了一个错误,如果我能找出它在哪里,我就该死了。

代码示例如下,我对其中的调试内容表示歉意,但我正在努力使其正常工作。

问题是 $temp 是一个具有正确键(列名)的数组,但所有值都是 NULL。

我认为问题出在这

call_user_func_array(array($query, 'bind_result'), $params);

一点上,但我无法真正理解它。

public function fetchRows(){
    error_reporting(E_ALL+E_NOTICE);
    $args = func_get_args();
    $sql = array_shift($args);
    traceVar($sql, "Query");
    $colTypes = array_shift($args);
    if (!$query = $this->prepare($sql, $colTypes)) {
        die('Please check your sql statement : unable to prepare');
    }
    if (count($args)){
        traceVar($args,'Binding params with');
        call_user_func_array(array($query,'bindParam'), $args);
    }

    $query->execute();

    $meta = $query->result_metadata();
    while ($field = $meta->fetch_field()) {
        $params[] = &$row[$field->name];
    }
    traceVar($params,'Binding results with');
    call_user_func_array(array($query, 'bind_result'), $params);

    while ($query->fetch()) {
        traceVar($row,'After fetch');
        $temp = array();
        foreach($row as $key => $val) {
            $temp[$key] = $val;
        } 
        $result[] = $temp;
    }

    $meta->free();
    $query->close(); 
    //self::close_db_conn(); 
    return $result;
}

Lately I've stumbled upon an error in a lib that used to work just fine, and I'll be damned if I can figure out where it is.

The code sample is below, and I apologize for the debug stuff that's inside it, but I'm trying to get it to work.

The problem is that $temp is an array with correct key (the name of the columns) but all the values are NULL.

I think the problem lies in the

call_user_func_array(array($query, 'bind_result'), $params);

bit, but can't really wrap my head around it.

public function fetchRows(){
    error_reporting(E_ALL+E_NOTICE);
    $args = func_get_args();
    $sql = array_shift($args);
    traceVar($sql, "Query");
    $colTypes = array_shift($args);
    if (!$query = $this->prepare($sql, $colTypes)) {
        die('Please check your sql statement : unable to prepare');
    }
    if (count($args)){
        traceVar($args,'Binding params with');
        call_user_func_array(array($query,'bindParam'), $args);
    }

    $query->execute();

    $meta = $query->result_metadata();
    while ($field = $meta->fetch_field()) {
        $params[] = &$row[$field->name];
    }
    traceVar($params,'Binding results with');
    call_user_func_array(array($query, 'bind_result'), $params);

    while ($query->fetch()) {
        traceVar($row,'After fetch');
        $temp = array();
        foreach($row as $key => $val) {
            $temp[$key] = $val;
        } 
        $result[] = $temp;
    }

    $meta->free();
    $query->close(); 
    //self::close_db_conn(); 
    return $result;
}

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

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

发布评论

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

评论(2

牵你手 2024-08-21 05:38:04

如果我们可以在启动时选择服务器,我们可以使用 php-mysqlnd 模块来代替 PHP 的 php-mysql 模块。 (或者你们中的一些人可能已经在使用它,运行“phpinfo();”并搜索“mysqlnd”):

public function fetchRows(){
    ...
    $query->execute();

    $res = $query->get_result();
    while (($row = $res->fetch_assoc()))
        $result[] = $row;
    return $result;
    }
}

这对我来说似乎更简单。

If we could choose the server at start, we could use php-mysqlnd module instead of php-mysql module for PHP. (Or some of you maybe already using it, run "phpinfo();" and search for "mysqlnd") :

public function fetchRows(){
    ...
    $query->execute();

    $res = $query->get_result();
    while (($row = $res->fetch_assoc()))
        $result[] = $row;
    return $result;
    }
}

That seems simpler to me.

吖咩 2024-08-21 05:38:04

您提供的代码对我有用。

call_user_func_array(...)函数只是使用给定数组调用 $query 对象上的 bindParambind_result 方法,就像您提供了一样数组的每个元素作为方法参数。

您可能需要使用下面的代码检查出现问题的 SQL 语句。我对它进行了一些重写,以便使其完全可测试,因为原始代码取决于抽象层中的语句类。

<?php

$db_host = 'localhost';
$db_user = 'username';
$db_pass = 'password';
$db_name = 'database';

$mysqli = new mysqli($db_host, $db_user, $db_pass, $db_name);

print_r(fetchRows('SELECT something from some_table WHERE some_id = ?', 'i', 1));

function traceVar($a, $b) {
    print_r(array($b => $a));
}

function fetchRows(){
        error_reporting(E_ALL+E_NOTICE);
        $args = func_get_args();
        $sql = array_shift($args);
        traceVar($sql, "Query");

        // Keep the column types for bind_param.
        // $colTypes = array_shift($args);

        // Column types were originally passed here as a second
        // argument, and stored in the statement object, I suppose.
        if (!$query = $GLOBALS['mysqli']->prepare($sql)){ //, $colTypes)) {
                die('Please check your sql statement : unable to prepare');
        }
        if (count($args)){
                traceVar($args,'Binding params with');

                // Just a quick hack to pass references in order to
                // avoid errors.
                foreach ($args as &$v) {
                    $v = &$v;
                }

                // Replace the bindParam function of the original
                // abstraction layer.
                call_user_func_array(array($query,'bind_param'), $args); //'bindParam'), $args);
        }

        $query->execute();

        $meta = $query->result_metadata();
        while ($field = $meta->fetch_field()) {
                $params[] = &$row[$field->name];
        }
        traceVar($params,'Binding results with');
        call_user_func_array(array($query, 'bind_result'), $params);

        while ($query->fetch()) {
                traceVar($row,'After fetch');
                $temp = array();
                foreach($row as $key => $val) {
                        $temp[$key] = $val;
                } 
                $result[] = $temp;
        }

        $meta->free();
        $query->close(); 
        //self::close_db_conn(); 
        return $result;
}

The code you provided works for me.

The call_user_func_array(...) function just calls the bindParam or bind_result methods on the $query object with the given array, as if you had provided each element of the array as a method argument.

You may want to check the SQL statement you are having the problem with, with the code below. I've rewritten it a bit in order to make it fully testable, since the original code depends on the statement class in your abstraction layer.

<?php

$db_host = 'localhost';
$db_user = 'username';
$db_pass = 'password';
$db_name = 'database';

$mysqli = new mysqli($db_host, $db_user, $db_pass, $db_name);

print_r(fetchRows('SELECT something from some_table WHERE some_id = ?', 'i', 1));

function traceVar($a, $b) {
    print_r(array($b => $a));
}

function fetchRows(){
        error_reporting(E_ALL+E_NOTICE);
        $args = func_get_args();
        $sql = array_shift($args);
        traceVar($sql, "Query");

        // Keep the column types for bind_param.
        // $colTypes = array_shift($args);

        // Column types were originally passed here as a second
        // argument, and stored in the statement object, I suppose.
        if (!$query = $GLOBALS['mysqli']->prepare($sql)){ //, $colTypes)) {
                die('Please check your sql statement : unable to prepare');
        }
        if (count($args)){
                traceVar($args,'Binding params with');

                // Just a quick hack to pass references in order to
                // avoid errors.
                foreach ($args as &$v) {
                    $v = &$v;
                }

                // Replace the bindParam function of the original
                // abstraction layer.
                call_user_func_array(array($query,'bind_param'), $args); //'bindParam'), $args);
        }

        $query->execute();

        $meta = $query->result_metadata();
        while ($field = $meta->fetch_field()) {
                $params[] = &$row[$field->name];
        }
        traceVar($params,'Binding results with');
        call_user_func_array(array($query, 'bind_result'), $params);

        while ($query->fetch()) {
                traceVar($row,'After fetch');
                $temp = array();
                foreach($row as $key => $val) {
                        $temp[$key] = $val;
                } 
                $result[] = $temp;
        }

        $meta->free();
        $query->close(); 
        //self::close_db_conn(); 
        return $result;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文