Home » Php » php – Make mysql_fetch_assoc automatically detect return data types?

php – Make mysql_fetch_assoc automatically detect return data types?

Posted by: admin July 12, 2020 Leave a comment

Questions:

When using mysql_fetch_assoc in PHP, how can I make it return the correct data types? Right now it appears to convert everything to strings, I’d prefer if it left the Ints as Ints, and somehow designated the Date/Time as either Object or somehow different than strings.

The reason for this is that I am using PHP as a backend to a Flex application, and Flex has some features such as automatically detecting return types, which don’t work that well if everything comes in as a string.

How to&Answers:

I think a good strategy here is to programatically determine the datatype of each column in a table, and cast the returned results accordingly. This will allow you to interact with your database in a more consistent and simple manner while still giving you the control you need to have your variables storing the correct datatype.

One possible solution: You could use mysql_fetch_field() to get an object that holds meta-data about the table column and then cast your string back to the desired type.

//run query and get field information about the row in the table
$meta = mysql_fetch_field($result, $i);

//get the field type of the current column
$fieldType = $meta->type

A full example can be found here: http://us2.php.net/manual/en/function.mysql-fetch-field.php

Since PHP is loosely typed, you should have a relatively easy time with this.

If you are using OO (object-oriented) techniques, you could create a class with this functionality in the setter() methods so you don’t have to have duplicate code.

Answer:

Just contributing a small improvement to mastermind202’s answer to handle more data types. Thanks mastermind for doing the heavy lifting!

function cast_query_results($rs) {
    $fields = mysqli_fetch_fields($rs);
    $data = array();
    $types = array();
    foreach($fields as $field) {
        switch($field->type) {
            case MYSQLI_TYPE_NULL:
                $types[$field->name] = 'null';
                break;
            case MYSQLI_TYPE_BIT:
                $types[$field->name] = 'boolean';
                break;
            case MYSQLI_TYPE_TINY:
            case MYSQLI_TYPE_SHORT:
            case MYSQLI_TYPE_LONG:
            case MYSQLI_TYPE_INT24:
            case MYSQLI_TYPE_LONGLONG:
                $types[$field->name] = 'int';
                break;
            case MYSQLI_TYPE_FLOAT:
            case MYSQLI_TYPE_DOUBLE:
                $types[$field->name] = 'float';
                break;
            default:
                $types[$field->name] = 'string';
                break;
        }
    }
    while($row=mysqli_fetch_assoc($rs)) array_push($data,$row);
    for($i=0;$i<count($data);$i++) {
        foreach($types as $name => $type) {
            settype($data[$i][$name], $type);
        }
    }
    return $data;
}   

Example usage:

$db = mysqli_connect(...);
$rs = mysqli_query($db, "SELECT ...");
$results = cast_query_results($rs);

Returns an associative array of rows with properly typed fields

Answer:

You could build a mysql-specific layer around mdb2 that automatically detects field types using the SHOW COLUMNS command, but that would kind of defeat the purpose of using mdb2.

Keep in mind, also, that mysql suports integers well outside of PHP’s range, (UNSIGNED BIGINT is 64 bits; PHP supports, at best, 64 bit signed ints, and less on 32 bit platforms) so automatically casting may be undesirable in some contexts. In those cases, you really want to keep the large ints in their string form, and manipulate them with bcmath

Answer:

I wanted to share a function I wrote for this same problem. Pass the query result $rs and get a assoc array of the casted data as the return:

function cast_query_results($rs) {
    $fields = mysqli_fetch_fields($rs);
    $data = array();
    $types = array();
    foreach($fields as $field) {
        switch($field->type) {
            case 3:
                $types[$field->name] = 'int';
                break;
            case 4:
                $types[$field->name] = 'float';
                break;
            default:
                $types[$field->name] = 'string';
                break;
        }
    }
    while($row=mysqli_fetch_assoc($rs)) array_push($data,$row);
    for($i=0;$i<count($data);$i++) {
        foreach($types as $name => $type) {
            settype($data[$i][$name], $type);
        }
    }
    return $data;
}

Example usage:

$dbconn = mysqli_connect('localhost','user','passwd','tablename');
$rs = mysqli_query($dbconn, "SELECT * FROM Matches");
$matches = cast_query_results($rs);
// $matches is now a assoc array of rows properly casted to ints/floats/strings