简体   繁体   中英

CodeIgniter Active Record Return Mysql data types instead of just strings

I am using codeIgniter version 2.0.3. I was wondering if there is a simple way to return data with the correct data type. For example for schema:

+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| term  | varchar(255) | NO   |     | NULL    |                |
| level | int(11)      | NO   |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+

active record result_array returns:

array(4) {
  [0]=>
  array(3) {
    ["id"]=>
    string(1) "1"
    ["term"]=>
    string(11) "Mesoamerica"
    ["level"]=>
    string(1) "1"
  }
  [1]=>
  array(3) {
    ["id"]=>
    string(1) "2"
    ["term"]=>
    string(6) "Mexico"
    ["level"]=>
    string(1) "1"
  }
  [2]=>
  array(3) {
    ["id"]=>
    string(1) "3"
    ["term"]=>
    string(10) "indigenous"
    ["level"]=>
    string(1) "2"
  }
  [3]=>
  array(3) {
    ["id"]=>
    string(1) "4"
    ["term"]=>
    string(5) "ruins"
    ["level"]=>
    string(1) "2"
  }
}

The idea is to have the types come through on the result sets. ID should be INTEGER , and level should be INTEGER . I normally just typecast the data that I need to use. I did not see any way to push this on codeIgniter in the documentation, but am hoping that there is an easy way to do this. I have seen ways to do this in PDO but does codeIgniter provide some sort of convenience to do this for me?

Here's a helper I made:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
 * cast_fields
 *
 * Casts string values provided from database into
 * the appropriate datatype of possible.
 */
if ( ! function_exists('cast_fields'))
{
    function cast_fields($fields, $results)
    {
        for($i=0; $i<count($fields); $i++) {
            $name = $fields[ $i ]->name;
            $type = $fields[ $i ]->type;
            $int_types = array(
                'int',
                'tinyint',
                'smallint',
                'mediumint',
                'bigint'
            );
            if(in_array($type, $int_types)) {
                for($j=0; $j<count($results); $j++) {
                    $casted = intval( $results[ $j ]->{ $name } );
                    $results[ $j ]->{ $name } = $casted;
                }
            }
        }
        return $results;
    }

}

/* End of file field_data_helper.php */
/* Location: ./application/helpers/field_data_helper.php */

So far it only works for integers. You could expand on it to support other datatypes.

How to use it:

// Get rows from database.
$query = $this->db->get_where( $this->table, $criteria, $limit, $offset );
$results = $query->result();

// Cast data to the correct datatypes.
$fields = $this->db->field_data( $this->table );
$this->load->helper('field_data_helper');
$results = cast_fields($fields, $results);

I took this unfortunate approach: I just changed the /system/database/DB_Result.php file

Line 85 in method custom_result_object looks like this:

$object->$key = $value; 

change it to this:

if(is_numeric($value)) $object->$key = (int)$value;
else $object->$key = $value;

then add this method anywhere:

/**
* Scans a rowset to cast valid ints as integers instead of strings
*/
private function recast($row)
{
    foreach($row as $key => $value)
    {
        if(is_object($row)) {
            if(is_numeric($value)) $row->{$key} = (int)$value;
        } else {
            if(is_numeric($value)) $row[$key] = (int)$value;
        }

    }

    return $row;
} 

then in result_object() find

$this->result_object[] = $row;

and above that line, add

$row = $this->recast($row);

then in result_array() find

$this->result_array[] = $row;

and above that line, add

$row = $this->recast($row);

then in custom_row_object() , find

$this->current_row = $n;

and above that line, add

$n = $this->recast($n);

then in row_object() , find

$this->current_row = $n;

and above that line, add

$n = $this->recast($n);

then in row_array() , find

$this->current_row = $n;

and above that line, add

$n = $this->recast($n);

And of course the recast function can be modified and updated to your parsing needs, right now its just casting integers where need be without the use of regular expressions. This approach lets date timestamps remain date timestamps untouched, but anything thats supposed to be a numerical value, gets parsed. Some additional checking for Floats and such can also take place.

I just needed to do this for API functions, because json_encode was casting all my integers as hard strings, id:"1" instead of ints id:1 and needed a solution that would reflect across the whole site.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM