0

I have an application that reads in one of its classes:

public function __construct()
{
  global $config;
  //Establish a connection to the database and get results set
  $this->db = new Database("localhost",$config["dbuser"],$config["dbpass"],"student");
  $this->records = $this->db->query("SELECT * FROM major") or die("ERROR: ".$this->db->error);
  echo "<pre>".var_dump($this->records)."</pre>";
}

My problem is that var_dump shows that $this->records is a boolean. I've read the documentation and see that the SELECT query should return a result set. This is the only query used by the application.

The DB Class:

  class Database
  {
      private $con;

     public function __construct($server,$user,$password,$database)
     {
        $this->con = new mysqli($server,$user,$password,$database) or die ("FATAL ERR: ".mysqli_error());
     }

    public function query($qry)
   {
     if(!isset($this->con)) die("ERROR: YOU ARE TRYING TO QUERY BEFORE THE CONNECTION IS ESTABLISHED!");
     return $this->con->query($qry) or die("FATAL ERROR:".$this->con->error);
   }
}

Any ideas where I am going wrong?

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
Travis Pessetto
  • 3,260
  • 4
  • 27
  • 55
  • @YourCommonSense, does the question/bounty here still relevant? I'm not so sure what exactly the problem is. Can you please clarify? – Dekel Oct 16 '16 at 14:33
  • In case the query is not a `select` query (update/insert for example) the result of the `mysqli::query` will **not** be a result_set, but a boolean. Perhaps this what was unclear here? – Dekel Oct 16 '16 at 14:34

3 Answers3

3

That is incorrect. The assignment operator (=) has a higher precedence than the literal "or" operator. (Not to be confused with the "||" operator, which has a higher precedence than "=".)

There seems to be a bug in mysqli::query(), that causes it to return the boolean "true" in rare cases on a select statement. (Legal return values would be the boolean "false" or a mysqli_result object.)

You don't have to believe me on that assertion, you can easily try it yourself in a PHP shell:

$a = false or true;
var_dump($a);

Result:

bool (false)

That is because the above assignment is equivalent to:

($a = false) or true;
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
user7018291
  • 346
  • 1
  • 2
  • there is no assignment operator in question – Your Common Sense Oct 14 '16 at 09:21
  • As a matter of fact there is: $this->records = $this->db->query("SELECT * FROM major") or die("ERROR: ".$this->db->error); – user7018291 Oct 14 '16 at 09:23
  • 1
    his problem is earlier in the code. the function in question is not `Database::query` which you are referring to but `mysqli::query` which is called withing the former. `return $this->con->query($qry) or die()` is the problem statement – Your Common Sense Oct 14 '16 at 09:27
  • I don't see the problem with that... if the "or die(...)" is evaluated the script will terminate and the method won't return anything at all. – user7018291 Oct 14 '16 at 09:30
  • Indeed it was me who is blind. but still, there are no bugs in mysqli. so most likely the code in the OP is not a real one. – Your Common Sense Oct 14 '16 at 09:31
  • The thing is that I stumbled over this question because I seem to be having the same problem. MySQLi::query returned true on a SELECT statement and on the next query after that I got a "the mysql server has gone away". – user7018291 Oct 14 '16 at 09:34
  • That would be difficult, as it gives away internals of my company. However, I think that answer might be helpful: http://stackoverflow.com/questions/12218775/mysqliquery-returns-true-on-select-queries --- the script forks and runs four instances simultaneously, so race conditions might very well be a problem. – user7018291 Oct 14 '16 at 09:42
  • erm... Having thought about it you have been correct after all. The expression (25 or die) returns the boolean "true", not 25. Unfortunately this does not solve my problem. :/ – user7018291 Oct 14 '16 at 13:10
0

The issue in this question is not related to mysqli_query() function, but to the operator precedence.

There, the = operator has a higher precedence over OR operator, means assignment will be executed before OR (I explained this behavior in detail in the other answer, mysqli or die, does it have to die? )

The problem line is

 return $this->con->query($qry) or die("FATAL ERROR:".$this->con->error);

Here, return operator has (for the obvious reason) the lowest precedence possible. Means that first PHP will execute the logical operator and then return its result - a boolean value!

But why doesn't the script actually die due to the logical operator execution?

Because of that logical operator execution optimization explained in the answer by the link above. PHP doesn't bother to actually execute the rightmost operator. It's enough that the leftmost one is already evaluates to true, means the whole expression will return true either way.

To solve this problem, the code of the function have to be changed this way:

public function query($qry)
{
    $ret = $this->con->query($qry) or trigger_error($this->con->error);
    return $ret;
}

while the calling code should be changed to simple

$this->records = $this->db->query("SELECT * FROM major");
echo "<pre>".var_dump($this->records)."</pre>";

call, as checking for the error for the second time makes no sense - this function will never return a false-like value.

Community
  • 1
  • 1
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
-1

The answer would be in what is called Magic Methods. One of PHP's magic methods is called __debugInfo(). If this Magic Method is defined, when you call var_dumb(obj), it will output whatever the function says to output. This is normally done to hide the private and protected functions of a parent class.

kayleighsdaddy
  • 670
  • 5
  • 15