title: Unexpected "mysqli_real_escape_string() expects parameter 1 to be mysqli, null given in"
body: <p>I have been trying to solve this problem for a while now. I am getting an unexpected error namely "mysqli_real_escape_string() expects parameter 1 to be mysqli, null given in" </p>
  
  <p>Below is the sample code referring to where this error is happening.</p>
  
  <pre><code>function tep_db_input($string, $link = 'db_link') {
      global $$link;
  
      return mysqli_real_escape_string($$link, $string);
  }
  </code></pre>
  
  <p>The mysqli object is being made in this piece of code.</p>
  
  <pre><code>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;
  }
  </code></pre>
  
  <p>The rest of the mysqli functions like this are all in the same file. This file gets included at the start of the page. Like this.</p>
  
  <pre><code>// make a connection to the database... now
  tep_db_connect() or die('Unable to connect to database server!');
  </code></pre>
  
  <p>A little bit of background to this whole situation. It's an OsCommerce webshop a really old version at that, recently we have decided to migrate from PHP 5.3 to 5.6 forcing us to use the new mysqli_* extension instead of mysql_*.
  Ever since I have been getting multiple errors pertaining to the issue where the object won't work within another function, while I'm still using global  to get it wihin the scope. I've done a var_dump right before the mysqli_real_escape_string() is being called and get a proper mysqli object back.</p>
  
  <p>Currently this version of the website is not live so I'm accessing it via editing the hosts file. I'm not sure if this is influencing any behaviour but I thought any info added to the story could help.</p>
  
  <pre><code>function tep_db_input($string, $link = 'db_link') {
      global $$link;
      var_dump($$link);
  
      return mysqli_real_escape_string($$link, $string);
  }
  </code></pre>
  
  <p>Results</p>
  
  <pre><code>object(mysqli)#1 (19) { ["affected_rows"]=&gt; int(161) ["client_info"]=&gt; string(79) "mysqlnd 5.0.11-dev - 20120503 - $Id: 3c688b6bbc30d36af3ac34fdd4b7b5b787fe5555 $" ["client_version"]=&gt; int(50011) ["connect_errno"]=&gt; int(0) ["connect_error"]=&gt; NULL ["errno"]=&gt; int(0) ["error"]=&gt; string(0) "" ["error_list"]=&gt; array(0) { } ["field_count"]=&gt; int(2) ["host_info"]=&gt; string(25) "Localhost via UNIX socket" ["info"]=&gt; NULL ["insert_id"]=&gt; int(0) ["server_info"]=&gt; string(14) "5.5.41-MariaDB" ["server_version"]=&gt; int(50541) ["stat"]=&gt; 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"]=&gt; string(5) "00000" ["protocol_version"]=&gt; int(10) ["thread_id"]=&gt; int(2568661) ["warning_count"]=&gt; int(0) }
  </code></pre>
  
  <p>Yet I'm still getting the error saying there is null given in the function which makes no sense to me since there clearly is something in the variable as the var_dump shows.</p>
  
  <p>I'm well aware that using global in combination with mysqli isn't the best practice so please do not try to correct me on that. I'm simply looking for the cause why my object dissapears right before the function is called.</p>
  
  <p>My question here is why is the object not being recognized by the function yet the var_dump shows it's a mysqli object.</p>
  
  <p>Many thanks for taking the time to read through all of this and I hope anyone can be of help.</p>
  
  <p>EDIT1:
  Just to double check the answer given by @xXDarioXx
  I did two var_dumps of the variable but in different forms. Here is the code.</p>
  
  <pre><code>echo $string;
  echo '&lt;br/&gt;';
  var_dump($db_link);
  echo '&lt;br/&gt;';
  echo '&lt;br/&gt;';
  var_dump($$link);
  echo '&lt;br/&gt;';
  echo '&lt;br/&gt;';
  </code></pre>
  
  <p>This returned the same mysqli object but slightly different. Here is the output.</p>
  
  <pre><code>u2l14a8l846b5le667ibnio0p5
  </code></pre>
  
  <p>$db_link object</p>
  
  <pre><code>object(mysqli)#1 (19) { ["affected_rows"]=&gt; int(161) ["client_info"]=&gt; string(79) "mysqlnd 5.0.11-dev - 20120503 - $Id: 3c688b6bbc30d36af3ac34fdd4b7b5b787fe5555 $" ["client_version"]=&gt; int(50011) ["connect_errno"]=&gt; int(0) ["connect_error"]=&gt; NULL ["errno"]=&gt; int(0) ["error"]=&gt; string(0) "" ["error_list"]=&gt; array(0) { } ["field_count"]=&gt; int(2) ["host_info"]=&gt; string(25) "Localhost via UNIX socket" ["info"]=&gt; NULL ["insert_id"]=&gt; int(0) ["server_info"]=&gt; string(14) "5.5.41-MariaDB" ["server_version"]=&gt; int(50541) ["stat"]=&gt; 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"]=&gt; string(5) "00000" ["protocol_version"]=&gt; int(10) ["thread_id"]=&gt; int(2583258) ["warning_count"]=&gt; int(0) } 
  </code></pre>
  
  <p>$$link object.</p>
  
  <pre><code>object(mysqli)#1 (19) { ["affected_rows"]=&gt; int(-1) ["client_info"]=&gt; string(79) "mysqlnd 5.0.11-dev - 20120503 - $Id: 3c688b6bbc30d36af3ac34fdd4b7b5b787fe5555 $" ["client_version"]=&gt; int(50011) ["connect_errno"]=&gt; int(0) ["connect_error"]=&gt; NULL ["errno"]=&gt; int(0) ["error"]=&gt; string(0) "" ["error_list"]=&gt; array(0) { } ["field_count"]=&gt; int(2) ["host_info"]=&gt; string(25) "Localhost via UNIX socket" ["info"]=&gt; NULL ["insert_id"]=&gt; int(0) ["server_info"]=&gt; string(14) "5.5.41-MariaDB" ["server_version"]=&gt; int(50541) ["stat"]=&gt; 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"]=&gt; string(5) "00000" ["protocol_version"]=&gt; int(10) ["thread_id"]=&gt; int(2583258) ["warning_count"]=&gt; int(0) } 
  </code></pre>
  
  <p>I have tried switching the variables around to see if it truly was an issue with the dynamic variable but it seems the latter variable always outputs an object with affected rows -1 this might be another piece of info why the object dissapears of becomes unusable.</p>
  
  <p>EDIT2:
  Log with the errors being thrown by PHP</p>
  
  <pre><code>[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
  </code></pre>
  
  <p>Errors are being thrown here because of a tep_db_query using tep_db_input to escape a key in the query. Hence the mysqli_real_escape_string that is being thrown first and then the others because the tep_db_input fails since the object 'dissapears'.</p>
  
  <p>I have done a small test to see where exactly the object starts behaving weirdly. I modified the tep_db_input function to pass along numbers for debugging.</p>
  
  <pre><code> function tep_db_input($string, $num = 0, $link = 'db_link') {
     global $$link;
  
     echo '&lt;br/&gt;';
     echo '&lt;br/&gt;';
     echo $num;
     echo '&lt;br/&gt;';
  
     echo $string;
     echo '&lt;br/&gt;';
     var_dump($db_link);
     echo '&lt;br/&gt;';
     echo '&lt;br/&gt;';
     var_dump($$link);
     echo '&lt;br/&gt;';
     echo '&lt;br/&gt;';
  
     return mysqli_real_escape_string($$link, $string);
  }
  </code></pre>
  
  <p>This gave me the following results.</p>
  
  <p>1
  u2l14a8l846b5le667ibnio0p5</p>
  
  <p>"Object 1 from previous test"</p>
  
  <p>"Object 2 from previous test"</p>
  
  <p>2
  u2l14a8l846b5le667ibnio0p5
  NULL &lt;- This is where object 1 should be dumped</p>
  
  <p>NULL &lt;- This is where object 2 should be dumped</p>
  
  <p>The code where this is being executed is as follows.</p>
  
  <pre><code>function _sess_read($key) {
      $value_query = tep_db_query("select value from " . TABLE_SESSIONS . " where sesskey = '" . tep_db_input($key, 1) . "' and expiry &gt; '" . 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'] &gt; 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) . "')");
      }
  }
  </code></pre>
  
  <p>These two are called in </p>
  
  <pre><code>session_set_save_handler('_sess_open', '_sess_close', '_sess_read', '_sess_write', '_sess_destroy', '_sess_gc');
  </code></pre>