mysqli prepare()返回一个布尔值true而不是一个语句对象

mysqli prepare()返回一个布尔值true而不是一个语句对象

问题描述:

I've seen this issue all over the internet but none of the solutions for others have fixed my errors. I have the following PHP code:

  $err = false;
  $mysqli = getMysqlConnection();
  if ($stmt = $mysqli->prepare("INSERT INTO users (username, email, regtime, emailverified, type) values (?,?,?,?,?);"))
  {
      date_default_timezone_set("America/New_York");
      $dateStr = date("m-d-Y h:i:s");
      $emailverified = 0;
      $type = 0;

      $stmt->bind_param('sssii', $username, $email, $dateStr, $emailverified, $type);
      $rc = $stmt->execute();
      $err = $rc ? $err : true;

      $userId = $stmt->insert_id;    

      if ($stmt = $mysqli->prepare("INSERT INTO usercreds (user_id, username, hash) VALUES (?,?,?);") && $err === false)
      {
          //
          //right here, for some reason, $stmt is true (boolean), not an object
          //

          $stmt->bind_param('iss', $userId, $username, $hash);
          $rc = $stmt->execute();
          $err = $rc ? $err : true;
      }
      else {
        $err = true;
      }
  }

The first query runs without problems, but the second query breaks on the call to bind_params. I get the error

Fatal error: Uncaught Error: Call to a member function bind_param() on boolean

This means (and I have confirmed) that the second time I do $stmt = $mysqli->prepare(), it's returning a boolean rather than an object. Furthermore, it's returning true, which I find very strange.

I have quadruple checked my query, and it is perfectly fine and valid. Yet for some reason the second time I try to prepare a statement he prepare method returns a boolean instead of a statement object.

Another note, echoing out $mysqli->error after the second prepare() outputs nothing.

How do I resolve this issue?


Afterthought:

Part of me feels like this is because I'm using the same mysqli object twice in a row? or maybe because I'm using the same statement object twice in a row? Is there some sort of "shutting down" or "resetting" of one of these objects that needs to take place in order to execute a second query?

Another edit:

Additional proof that my second query is valid. I copied and pasted it and replaced the ?'s with values, executed it in mysql workbench, and it ran perfectly fine.

INSERT INTO usercreds (user_id, username, hash) VALUES (1234567890,'testusr','hashhashhash');

Your problem is caused by essentially wrong way of error handling. That is, beside producing errors, is making your code bloat.

Below is the only code you really need:

date_default_timezone_set("America/New_York");
// below is the only line you need for the error handling
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = getMysqlConnection();

$dateStr = date("m-d-Y h:i:s");
$emailverified = 0;
$type = 0;

$stmt = $mysqli->prepare("INSERT INTO users (username, email, regtime, emailverified, type) values (?,?,?,?,?)");
$stmt->bind_param('sssii', $username, $email, $dateStr, $emailverified, $type);
$stmt->execute();
$userId = $mysqli->insert_id;

$stmt = $mysqli->prepare("INSERT INTO usercreds (user_id, username, hash) VALUES (?,?,?)");
$stmt->bind_param('iss', $userId, $username, $hash);
$stmt->execute();

The rest is depends on what you going to do in case of error.

You are assigning the result of $mysqli->prepare(..) && $err === false to $stmt. That is a boolean expression. You want either of these variations:

if (($stmt = $mysqli->prepare(...)) && $err === false)
if ($err === false && $stmt = $mysqli->prepare(...))