动态mysqli准备语句失败

时间:2013-02-12 07:35:19

标签: php join mysqli prepared-statement

我正在尝试为我的mysqli连接编写一个非常小的抽象层,并遇到了一个问题。 由于我正在维护旧的代码,我需要从查询中获取一个关联数组,因为这是代码设置的方式,因此一旦这样工作,我的工作就会减少...... 此功能适用于所有类型的查询(不仅仅是选择)......

我写的函数是这样的:

function connectDB($query,$v=array()) {
    $mysqli = new mysqli(HOST,USER,PW,DATABASE);

    if($res=$mysqli->prepare($query)) {
            //dynamically bind all $v
            if($v) {
            $values=array($v[0]);
            for($i=1; $i<count($v); $i++) {
                ${'bind'.$i}=$v[$i];
                $values[]=&${'bind'.$i};
            }
            call_user_func_array(array($res,'bind_param'),$values);
        }
        $res->execute();

        //bind all table rows to result
        if(strtolower(substr($query,0,6))=="select") {
            $fields=array();
            $meta=$res->result_metadata();
            while($field=$meta->fetch_field()) { 
                ${$field->name}=null;
                $fields[$field->name]=&${$field->name};
            }
            call_user_func_array(array($res,"bind_result"),$fields);

            //return associative array
            $results = array();
            $i=0;
            while($res->fetch()) {
                $results[$i]=array();
                foreach($fields as $k => $v) $results[$i][$k] = $v;
                $i++;
            }
        }
        else {
            $results=$mysqli->affected_rows;
            if($mysqli->affected_rows<1) $results=$mysqli->info;
        }

        $res->close();
    }
    $mysqli->close();

    return $results;
}

所以如果我打电话:

$MySqlres=connectDB("select * from `modx_events` events  limit 1");
var_dump($MySqlres);

我得到一个很好的关联数组,其中包含我的选择内容。

现在不幸的是,以下mysql查询将返回NULL作为其所有数组键的值:

$MySqlres=connectDB("select *, events.`id` as `ID`,venues.`name` as `venueName`,
venues.`suburb` as `venueSuburb`,venues.`advertiser` as `venueAdvertiser`
from `modx_events` events left join `modx_venues` venues on events.`venue`=venues.`id`
where events.`id`!='e' order by events.`start_date` asc, venues.`name` limit 1");

(相同的查询运行纯SQL并返回正确的值) 知道这可能是什么?我的关联数组函数是否失败?我实施查询的方式有问题吗?

ps:PDO不是一个选项而且没有安装mysqlnd ...... :(

添加问题

  • 这是为了保留关联数组返回的过多开销吗?我应该选择$res->fetch_object()吗?

2 个答案:

答案 0 :(得分:0)

Mysqli在动态预处理语句方面非常差,这使得小型抽象层创建成为一场噩梦 我强烈建议您切换到PDO或删除预准备语句,并根据手动处理的占位符创建常规查询(首选)。

作为姑息补丁,您可以尝试使用get_result()函数,该函数将返回一个常规结果变量,您可以通过fetch_assoc()常规方式遍历该变量。 但它只适用于mysqlnd版本。

另请注意,为每个查询创建mysqli对象是一个很大的禁忌 创建一次,然后使用global $mysqli;

在查询函数中分配它
  

这是太多的开销

我不明白你在说什么开销

答案 1 :(得分:0)

我刚修好了这个功能。 也许这对其他人来说很有意思:

function connectDB($mysqli,$query,$v=array()) {

    if($mysqli->connect_errno) {
        return array('error'=>'Connect failed: '.$mysqli->connect_error); //error handling here
        exit();
    }

    if(substr_count($query,"?")!=strlen($v[0])) {
        return array('error'=>'placeholders and replacements are not equal! placeholders:'.substr_count($query,"?").' replacements:'.strlen($v[0]).' ('.$v[0].')'); //error handling here...
        exit();
    }

    if($res=$mysqli->prepare($query)) {
            //dynamically bind all $v
            if($v) {
            $values=array($v[0]);
            for($i=1; $i<count($v); $i++) {
                ${'bind'.$i}=$v[$i];
                $values[]=&${'bind'.$i};
            }
            call_user_func_array(array($res,'bind_param'),$values);
        }
        $res->execute();

        //bind all table rows to result
        if(strtolower(substr($query,0,6))=="select") {
            $field=$fields=$tempRow=array();
            $meta=$res->result_metadata();
            while($field=$meta->fetch_field()) {
                $fieldName=$field->name;
                $fields[]=&$tempRow[$fieldName];
            }
            $meta->free_result();
            call_user_func_array(array($res,"bind_result"),$fields);

            //return associative array
            $results=array();
            $i=0;
            while($res->fetch()) {
                $results[$i]=array();
                foreach($tempRow as $k=>$v) $results[$i][$k] = $v;
                $i++;
            }
            $res->free_result();

        }
        else { //return infos about the query
            $results["affectedRows"]=$mysqli->affected_rows;
            $results["info"]=$mysqli->info;
            $results["insertID"]=$mysqli->insert_id;
        }

        $res->close();
    }

    return $results;
}

欢呼声