意外的" mysqli_real_escape_string()期望参数1为mysqli,在"

时间:2016-09-01 15:01:42

标签: php mysqli

我一直试图解决这个问题一段时间了。我收到了一个意想不到的错误,即" mysqli_real_escape_string()期望参数1为mysqli,在"

以下是涉及此错误发生位置的示例代码。

function tep_db_input($string, $link = 'db_link') {
    global $$link;

    return mysqli_real_escape_string($$link, $string);
}

mysqli对象正在这段代码中制作。

function tep_db_connect($server = DB_SERVER, $username = DB_SERVER_USERNAME, $password = DB_SERVER_PASSWORD, $database = DB_DATABASE, $link = 'db_link') {
    global $$link;

    if (USE_PCONNECT == 'true') {
      $server = 'p:' . $server;
    }

    $$link = mysqli_connect($server, $username, $password, $database);

    if ( !mysqli_connect_errno() ) {
      mysqli_set_charset($$link, 'utf8');
    } 

    return $$link;
}

像这样的其余mysqli函数都在同一个文件中。该文件包含在页面的开头。像这样。

// make a connection to the database... now
tep_db_connect() or die('Unable to connect to database server!');

这整个情况的一些背景知识。它是一个非常老的版本的OsCommerce网上商店,最近我们决定从PHP 5.3迁移到5.6,迫使我们使用新的mysqli_ *扩展而不是mysql_ *。 自从我收到了与对象在另一个函数中不起作用的问题有关的多个错误,而我仍然使用全局来获取它的范围。我在调用mysqli_real_escape_string()之前就已经完成了一个var_dump并获得了一个合适的mysqli对象。

目前这个版本的网站不在线,所以我通过编辑hosts文件来访问它。我不确定这是否会影响任何行为,但我认为添加到故事中的任何信息都有帮助。

function tep_db_input($string, $link = 'db_link') {
    global $$link;
    var_dump($$link);

    return mysqli_real_escape_string($$link, $string);
}

结果

object(mysqli)#1 (19) { ["affected_rows"]=> int(161) ["client_info"]=> string(79) "mysqlnd 5.0.11-dev - 20120503 - $Id: 3c688b6bbc30d36af3ac34fdd4b7b5b787fe5555 $" ["client_version"]=> int(50011) ["connect_errno"]=> int(0) ["connect_error"]=> NULL ["errno"]=> int(0) ["error"]=> string(0) "" ["error_list"]=> array(0) { } ["field_count"]=> int(2) ["host_info"]=> string(25) "Localhost via UNIX socket" ["info"]=> NULL ["insert_id"]=> int(0) ["server_info"]=> string(14) "5.5.41-MariaDB" ["server_version"]=> int(50541) ["stat"]=> string(149) "Uptime: 2338516 Threads: 8 Questions: 166189149 Slow queries: 0 Opens: 1664692 Flush tables: 2 Open tables: 400 Queries per second avg: 71.066" ["sqlstate"]=> string(5) "00000" ["protocol_version"]=> int(10) ["thread_id"]=> int(2568661) ["warning_count"]=> int(0) }

然而,我仍然得到错误,说函数中有null,这对我来说没有意义,因为var_dump显示变量中有明显的东西。

我很清楚将全局与mysqli结合使用并不是最佳做法,所以请不要试图纠正我。我只是在调用函数之前找到我的对象消失的原因。

我的问题是为什么函数没有识别该对象,但var_dump显示它是一个mysqli对象。

非常感谢您花时间阅读所有这些内容,我希望任何人都可以提供帮助。

EDIT1: 只是仔细检查@xXDarioXx给出的答案 我做了两个变量的var_dump,但形式不同。这是代码。

echo $string;
echo '<br/>';
var_dump($db_link);
echo '<br/>';
echo '<br/>';
var_dump($$link);
echo '<br/>';
echo '<br/>';

这返回了相同的mysqli对象但略有不同。这是输出。

u2l14a8l846b5le667ibnio0p5

$ db_link object

object(mysqli)#1 (19) { ["affected_rows"]=> int(161) ["client_info"]=> string(79) "mysqlnd 5.0.11-dev - 20120503 - $Id: 3c688b6bbc30d36af3ac34fdd4b7b5b787fe5555 $" ["client_version"]=> int(50011) ["connect_errno"]=> int(0) ["connect_error"]=> NULL ["errno"]=> int(0) ["error"]=> string(0) "" ["error_list"]=> array(0) { } ["field_count"]=> int(2) ["host_info"]=> string(25) "Localhost via UNIX socket" ["info"]=> NULL ["insert_id"]=> int(0) ["server_info"]=> string(14) "5.5.41-MariaDB" ["server_version"]=> int(50541) ["stat"]=> string(149) "Uptime: 2341490 Threads: 2 Questions: 166712462 Slow queries: 0 Opens: 1668302 Flush tables: 2 Open tables: 400 Queries per second avg: 71.199" ["sqlstate"]=> string(5) "00000" ["protocol_version"]=> int(10) ["thread_id"]=> int(2583258) ["warning_count"]=> int(0) } 

$$链接对象。

object(mysqli)#1 (19) { ["affected_rows"]=> int(-1) ["client_info"]=> string(79) "mysqlnd 5.0.11-dev - 20120503 - $Id: 3c688b6bbc30d36af3ac34fdd4b7b5b787fe5555 $" ["client_version"]=> int(50011) ["connect_errno"]=> int(0) ["connect_error"]=> NULL ["errno"]=> int(0) ["error"]=> string(0) "" ["error_list"]=> array(0) { } ["field_count"]=> int(2) ["host_info"]=> string(25) "Localhost via UNIX socket" ["info"]=> NULL ["insert_id"]=> int(0) ["server_info"]=> string(14) "5.5.41-MariaDB" ["server_version"]=> int(50541) ["stat"]=> string(149) "Uptime: 2341490 Threads: 2 Questions: 166712462 Slow queries: 0 Opens: 1668302 Flush tables: 2 Open tables: 400 Queries per second avg: 71.199" ["sqlstate"]=> string(5) "00000" ["protocol_version"]=> int(10) ["thread_id"]=> int(2583258) ["warning_count"]=> int(0) } 

我尝试切换变量以查看它是否真的是动态变量的问题,但似乎后一个变量总是输出一个受影响行的对象-1这可能是另一条信息为什么对象消失变为无法使用。

EDIT2: 记录PHP抛出的错误

[01-Sep-2016 17:38:21 Europe/Amsterdam] PHP Warning:  mysqli_real_escape_string() expects parameter 1 to be mysqli, null given in /home/user/domains/domain/public_html/includes/functions/database.php on line 160
[01-Sep-2016 17:38:21 Europe/Amsterdam] PHP Warning:  mysqli_query() expects parameter 1 to be mysqli, null given in /home/user/domains/domain/public_html/includes/functions/database.php on line 53
[01-Sep-2016 17:38:21 Europe/Amsterdam] PHP Warning:  mysqli_errno() expects parameter 1 to be mysqli, null given in /home/user/domains/domain/public_html/includes/functions/database.php on line 53
[01-Sep-2016 17:38:21 Europe/Amsterdam] PHP Warning:  mysqli_error() expects parameter 1 to be mysqli, null given in /home/user/domains/domain/public_html/includes/functions/database.php on line 53

由于tep_db_query使用tep_db_input转义查询中的键,因此会抛出错误。因此,首先抛出mysqli_real_escape_string,然后抛出其他因为tep_db_input失败,因为对象“消失了”。

我做了一个小测试,看看对象开始表现得奇怪。我修改了tep_db_input函数以传递数字以进行调试。

 function tep_db_input($string, $num = 0, $link = 'db_link') {
   global $$link;

   echo '<br/>';
   echo '<br/>';
   echo $num;
   echo '<br/>';

   echo $string;
   echo '<br/>';
   var_dump($db_link);
   echo '<br/>';
   echo '<br/>';
   var_dump($$link);
   echo '<br/>';
   echo '<br/>';

   return mysqli_real_escape_string($$link, $string);
}

这给了我以下结果。

1 u2l14a8l846b5le667ibnio0p5

&#34;来自先前测试的对象1&#34;

&#34;来自先前测试的对象2&#34;

2 u2l14a8l846b5le667ibnio0p5 NULL&lt; - 这是应该转储对象1的地方

NULL&lt; - 这是应该转储对象2的地方

执行此操作的代码如下。

function _sess_read($key) {
    $value_query = tep_db_query("select value from " . TABLE_SESSIONS . " where sesskey = '" . tep_db_input($key, 1) . "' and expiry > '" . time() . "'");
    $value = tep_db_fetch_array($value_query);

    if (isset($value['value'])) {
        return $value['value'];
    }

    return '';
}

function _sess_write($key, $val) {
    global $SESS_LIFE;

    $expiry = time() + $SESS_LIFE;
    $value = $val;
    $check_query = tep_db_query("select count(*) as total from " . TABLE_SESSIONS . " where sesskey = '" . tep_db_input($key , 2) . "'");
    $check = tep_db_fetch_array($check_query);

    if ($check['total'] > 0) {
        return tep_db_query("update " . TABLE_SESSIONS . " set expiry = '" . tep_db_input($expiry) . "', value = '" . tep_db_input($value) . "' where sesskey = '" . tep_db_input($key) . "'");
    } else {
        return tep_db_query("insert into " . TABLE_SESSIONS . " values ('" . tep_db_input($key) . "', '" . tep_db_input($expiry) . "', '" . tep_db_input($value) . "')");
    }
}

这两个在

中调用
session_set_save_handler('_sess_open', '_sess_close', '_sess_read', '_sess_write', '_sess_destroy', '_sess_gc');

3 个答案:

答案 0 :(得分:1)

自定义会话保存处理程序是奇怪的野兽。他们只有一只脚在用户的土地上,事物的行为就像你期望的那样,另一只脚在黑暗魔法所在的引擎的空灵世界中。 To wit

  

[T]他编写并关闭处理程序在对象销毁后调用,因此无法使用对象...

我不确定哪个会话功能失败了,但我怀疑它是_sess_write。如果您在debug_print_backtrace顶部的tep_db_connect汇总,那将澄清。

然而,我建议做的是将所有会话功能放在一个班级,然后在那个班级中。 open方法获取ADOdb的链接并将其存储为成员变量,然后在该类的实例上注册会话函数。这将保持对象中的链接,并防止其他全局对象的正常销毁。

class CustomSaveHandler extends \SessionHandlerInterface {
    public function open($path, $name) {
        this->db = tep_db_connect(...);
    }

    public function read($id) {
        // MySQL database calls using $this->db; you'll have to refactor how
        // you're calling your tep_ functions
    }

    // etc.
}
session_set_save_handler(new CustomSaveHandler);

供参考,similar problem with custom session handlers and ADOdb

答案 1 :(得分:0)

您正在使用动态变量名称

默认情况下,{p> $$link是名称db_link的变量tep_db_connect

$db_link不存在,因此返回null

答案 2 :(得分:0)

试试这个

  function tep_db_connect($server = DB_SERVER, $username = DB_SERVER_USERNAME, $password = DB_SERVER_PASSWORD, $database = DB_DATABASE, $link = 'db_link') {
    global ${$link};

    if (USE_PCONNECT == 'true') {
      $server = 'p:' . $server;
    }

    ${$link} = mysqli_connect($server, $username, $password, $database);

    if ( !mysqli_connect_errno() ) {
      mysqli_set_charset(${$link}, 'utf8');
    }

    return ${$link};
  }



  function tep_db_input($string, $link = 'db_link') {
    global ${$link};

    return mysqli_real_escape_string(${$link}, $string);
  }