关于php:通过准备好的语句查询获取错误

Getting error with prepared statement query

我现在已经面临几天的问题了,我一直盯着它,似乎自己也找不到来源。

我已经建立了一个类来执行查询。实际的查询执行部分如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?php
public function query( $method, $table, $data, $where_text='', $where_data='' ) {
    $this->check_db_status();

    $method = strtoupper( $method );

    $fieldsArray = array();
    $valuesArray = array();
    $paramsArray = array();
    $format = '';
    $queryText = '';

    switch( $method ) {
        case 'SELECT' :
            $queryText = 'SELECT %s FROM ' . $table . ' ';
            foreach( $data as $field => $value ) {
                $fieldsArray[] = $value;
            }
        break;
        case 'UPDATE' :
            $queryText = 'UPDATE ' . $table . ' SET %s ';
            foreach( $data as $field => $value ) {
                $fieldsArray[] = $field.'=?';
                $format .= $this->get_value_type( $value );
                $paramsArray[] = $value;
            }
        break;
        case 'DELETE' :
            $queryText = 'DELETE FROM ' . $table . ' ';
        break;
        case 'INSERT' :
            $queryText = 'INSERT INTO ' . $table . ' (%s) VALUES (%s) ';
            foreach( $data as $field => $value ) {
                $fieldsArray[] = $field;
                $format .= $this->get_value_type( $value );
                $valuesArray[] = '?';
                $paramsArray[] = $value;
            }
        break;
        default :
            $this->get_error( 'Error in method switch' );
        break;
    }

    if( $where_text ) {
        $queryText .= $where_text;
        if( $where_data ) {
            foreach( $where_data as $value ) {
                $format .= $this->get_value_type( $value );
                $paramsArray[] = $value;
            }
        }
    }

    $fields = implode( ',', $fieldsArray );
    $values = implode( ',', $valuesArray );

    $query = sprintf( $queryText, $fields, $values );

    // DEBUG
    echo '[cc lang="php"]';
    echo 'query: ' . $query . '<br />
    echo '
format: ' .' . $format . '<br />';
    print_r( $paramsArray );
    echo '

';

$ stmt = $ this-> mysqli-> prepare($ query);

if($ stmt === false或$ stmt == NULL){
$ this-> get_error('准备语句时出错');
}

if($ format和$ paramsArray)
call_user_func_array('mysqli_stmt_bind_param',array_merge(array($ stmt,$ format),$ paramsArray));

if($ stmt-> execute()){
$ result = 0;
开关($ method){
案例'INSERT':
$ result =($ stmt-> insert_id)吗? $ stmt-> insert_id:true;
打破;
案例'UPDATE':
案例"删除":
$结果=($ stmt-> affected_rows)? $ stmt-> affected_rows:true;
打破;
案例'SELECT':
$ meta = $ stmt-> result_metadata();
$ fields = $ result = array();
而($ field = $ meta-> fetch_field()){
$ var = $ field-> name;
$$ var = null;
$ fields [$ var] =&$$ var;
}
call_user_func_array(array($ stmt,'bind_result'),$ fields);
$ i = 0;
while($ stmt-> fetch()){
$ result [$ i] = array();
foreach($ fields as $ k => $ v)
$ result [$ i] [$ k] = $ v;
$ i ++;
}
打破;
}
$ stmt-> close();
$ this-> query_cnt ++;

返回$ result;
}
其他{
$ this-> get_error();
}
}
?>

现在,我试图制作另一个类来将会话存储在自己的数据库中。写函数如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
public function write_session( $session_id, $session_data ) {

    $query  = $this->sql->query( 'INSERT', 'sessions', array( 'ses_id'=>$session_id, 'ses_time'=>time(), 'ses_start'=>time(), 'ses_data'=>$session_data, 'ses_check'=>$this->check ), 'ON DUPLICATE KEY UPDATE ses_time=?, ses_data=?', array(time(),$session_data));

    if($query) {
        return true;
    }
    else {
        return false;
    }
}
?>

我不断收到此错误:

1
Warning: mysqli::prepare() [mysqli.prepare]: Couldn't fetch mysqli in /.../class.db.php on line 124

第124行是带有$stmt = $this->mysqli->prepare( $query );的行。它由write_session的第一行触发。

如果放在数据库类的调试部分中以显示查询,它将给出以下输出:

1
2
3
4
5
6
7
8
9
10
11
12
query: INSERT INTO sessions (ses_id,ses_time,ses_start,ses_data,ses_check) VALUES (?,?,?,?,?) ON DUPLICATE KEY UPDATE ses_time=?, ses_data=?
format: [siissis]
Array
(
    [0] => a98696a8416fc898f2c07e05f39735dc
    [1] => 1402201705
    [2] => 1402201705
    [3] => test|s:11:"someValuess";
    [4] => 40b17cb572d9bf5eaadad99b7904e0a4889a31d0
    [5] => 1402201705
    [6] => test|s:11:"someValuess";
)

在我看来,这很好。...我在俯视什么?

编辑

会话表定义:

1
2
3
4
5
6
7
8
 sessions (
   ses_id varchar(32) NOT NULL,
   ses_time int(11) NOT NULL,
   ses_start int(11) NOT NULL,
   ses_data text NOT NULL,
   ses_check varchar(40) NOT NULL,
  PRIMARY KEY  (ses_id)
 )


在评论中提供的链接中指出,您的问题似乎是

4.您混合了对数据库对象的OOP和功能调用。

具体来说,您在此处使用mysqli对象

1
$stmt = $this->mysqli->prepare( $query );

但是然后继续在此处进行功能性mysqli调用

1
2
if( $format and $paramsArray )
    call_user_func_array( 'mysqli_stmt_bind_param', array_merge( array( $stmt, $format ), $paramsArray ) );

因此,请尝试使用相应的OOP版本替换上面的代码

1
2
3
if($format and $paramsArray) {
    $stmt->bind_param($format,$paramsArray);
}

也更换

1
call_user_func_array(array($stmt,'bind_result'),$fields);

1
$stmt->bind_param($format,$fields);

http://www.php.net//manual/en/mysqli-stmt.bind-param.php

实现__唤醒

另一种可能性是由于序列化,您的数据库连接可能已关闭。 尝试通过实现__wakup重新连接,即

1
2
3
4
public function __wakeup()
{
    $this->mysqli = new mysqli('localhost', 'my_user', 'my_password', 'my_db');
}