Skip to content

Instantly share code, notes, and snippets.

@geon
Created September 2, 2011 16:51
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save geon/1189139 to your computer and use it in GitHub Desktop.
Save geon/1189139 to your computer and use it in GitHub Desktop.
Get actual integers from MySQL with CakePHP.

Get actual integers from MySQL with CakePHP

With this AppModel, any integer column from the database will be casted to a proper int, any time you read it from the database.

Why would I want that?

Because it's awesome to send data to the client as JSON.

json_encode() does a great job of encoding your associative arrays in PHP to JSON. But where Javascript (and hence JSON) is picky about types, PHP is more lax. That means you might end up with JSON full of "1234" instead of 1234.

On the serverside, it won't matter, most of the time, since PHP silently cast strings to integers for you. It becomes slightly more annoying when you actually want to use this data on the client, since you will probably need to convert your numeric strings to actual integers manually.

-- "But won't this be awfully slow?", I hear you asking.

You use PHP. You don't care.

<?php
class AppModel extends Model {
function afterFind($results){
if(!isset($results[0])){
// $results is a single object.
$results = $this->realAfterFind($results);
}else{
// $results is a list of objects.
foreach($results as &$result)
$result = $this->realAfterFind($result);
}
return $results;
}
function realAfterFind($object){
// Cast all values in integer columns to actual integers.
$columnTypes = $this->getColumnTypes();
if(isset($object[$this->name]))
foreach($object[$this->name] as $columnName => &$value)
if($columnTypes[$columnName] === 'integer')
$value = (int) $value;
return $object;
}
}
@eymen-elkum
Copy link

Thanks

@mdemblani
Copy link

The code would throw an error if the field to be checked is a virtualField.
It would be better if a check is performed first to see if the column exists in the $columnTypes array as follows:

function realAfterFind($object) {
    // Cast all values in integer columns to actual integers.
    $columnTypes = $this->getColumnTypes();
    if (isset($object[$this->name])) {
        foreach ($object[$this->name] as $columnName => &$value) {
        if (isset($columnTypes[$columnName]) && $columnTypes[$columnName] === 'integer')
            $value = (int) $value;
        }
    }

    return $object;
}

Plus further more, the afterFind function needs one more parameter called $primary, this would also throw errors.

@jodinathan
Copy link

jodinathan commented Jun 23, 2016

Hi,

I changed your code a little bit so it can work with sublevels of the find method.

    public function afterFind($results, $primary=false){
    $results = $this->realAfterFind($results);

    return $results;
}
public function realAfterFind($object){
    if (isset($object[0]))
        foreach($object as &$result)
            $result = $this->realAfterFind($result);
    else {
        if (isset($object[$this->name]))
            $arr = &$object[$this->name];
        else
            $arr = &$object;

        foreach($arr as $columnName => &$value){
            if (is_numeric($value))
                $value = (int) $value;
            else if (is_array($value))
                $value = $this->realAfterFind($value);
        }
    }

    return $object;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment