意外"mysqli_real_escape_string() expects parameter 1 to be mysqli, null given in"



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

下面是示例代码,表示发生此错误的位置。

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所示。

我很清楚,将global与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(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);
}

结果如下:

1u2l14a8l846b5le667ibnio0p5

"Object 1 from previous test"

"Object 2 from previous test"

2u2l14a8l846b5le667ibnio0p5NULL <-这是对象1应该转储的位置

NULL <-这是对象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');

自定义会话保存处理程序是奇怪的野兽。他们的一只脚在用户领域,在那里事情会按照你期望的那样运行,而另一只脚在引擎的空灵世界里,那里存在着黑魔法。即:

[T] write和close处理程序在对象销毁之后被调用,因此不能使用对象…

我不清楚究竟哪个会话功能失败,但我怀疑是_sess_write。如果你在tep_db_connect的顶部接debug_print_backtrace,就会澄清。

尽管如此,我建议做的是将所有会话函数放在一个类中,然后在该类的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);

作为参考,自定义会话处理程序和ADOdb的类似问题。

您正在使用动态变量名称

$$linktep_db_connect中默认名为db_link的变量

$db_link不存在,所以它返回null

试试这个

  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);
  }

相关内容

最新更新