4

I'm using custom PHP wrapper for for mysqli. The class is designed to use prepared statements if bind parameters are passed to the a fetchResultSet function otherwise, as is my understanding, it saves a call to the database and uses the query function (perhaps I'm wrong saving a call and the rest of this question can be answered by simply using prepared statements even with no parameters to bind).

Once the query has been executed a fetchResult function passes back one of two objects ResultSetObjectResult or ResultSetObjectStmt both of witch implement a ResultSetObject interface. (The ResultSetObjectStmt object wraps an stmt object while the ResultSetObjectResult wraps a result object.)

Both classes return an associative array when a row is requested either though calling fetch_assoc on a result or calling bind_result on an stmt object (basically).

What I've noticed is that if a prepared statement is executed then the data returned are properly casted to integers, real numbers and strings depending on their types in the database; but when a result is returned and fetch_assoc is called on that result then all of the data are casted as strings. I realize this is mentioned in the documentation for fetch_assoc. I'm curious if there is another function or something I can do to have mysql properly cast the results.

[EDIT] I should mention that this is only an issue because json_encode places data in quotes depending on their types.

[EDIT AGAIN] I like to know if there is anyway to properly cast the data returned from a result without resorting to guess work using functions like is_numeric or by making an additional call to the database for the schema of the table. Using prepared statements exclusively when fetching data works, but I'd really love to save that additional prepare call to the database.

Andrew Winter
  • 1,116
  • 1
  • 8
  • 27

2 Answers2

2

I don't know what wrapper your using but you could have a function like...

while ($row = $query->fetch_assoc()) {
    $row = auto_cast($row);
}

function auto_cast($row) {
    foreach ($row as $key => $value) {
        if (ctype_digit($value)) {
            $row[$key] = (int) $value;
        }
        elseif (is_numeric($value)) {
            $row[$key] = (float) $value;
        }
        else {
            $row[$key] = (string) $value;
        }
    }
    return $row;
}
fire
  • 21,383
  • 17
  • 79
  • 114
  • The wrapper is custom. I thought about doing casting this way but I'm concerned that values that should be strings but contain only digits would be cast as integers or floats when strings are the appropriate data type. Is there any way to cast based on the database type without making an additional query to the database for the table schema? – Andrew Winter Dec 09 '10 at 09:49
  • Thanks for the info. I didn't know about ctype_digit... 5 years of PHP and things still sneek by me. – Andrew Winter Dec 09 '10 at 11:01
1

I will try to help here. When usign prepared statement, the PHP knows what is the column type and depending on that stores data in different types: string, integer, bool, etc. When using fetch_assoc it does not know this info. You could create a function that is getting the fields/columns MySQL data using mysqli_fetch_fields and use their type. Based on that you could typecast them. Hope that will help.

Fior information about different column types see here http://www.php.net/manual/en/mysqli.constants.php

MYSQLI_TYPE_LONG - Field is defined as INT an so on.

Yasen Zhelev
  • 4,045
  • 3
  • 31
  • 56