Because MYSQL's "SELECT" selects integers and floats as strings, and I need every response I get (from JS) to be in a correct data model -
private function cast_number(&$mixed) {
if(is_array($mixed)) {
foreach ($mixed as $key => $val)
if (is_numeric($val))
$mixed[$key] = (double)$val;
else if (is_array($val) || is_object($val))
$mixed[$key] = $this->cast_number($val);
} else if(is_object($mixed)) {
foreach ($mixed as $key => $val)
if (is_numeric($val))
$mixed->$key = (double)$val;
else if (is_array($val) || is_object($val))
$mixed->$key = $this->cast_number($val);
}
return $mixed;
}
Because coercion used to be faster than casting, I ran this code to calculate timings on PHP 7 :
function getTime($start) {
return round((microtime(true) - $start) * 1000000) / 1000;
}
function mockData($length) {
$data = [];
$i = -1;
while ($i++ < $length) {
$data[$i] = strval(rand(1, 10000) / 100);
}
return $data;
}
$data = mockData(100000);
// Let's check that they are string before
echo gettype($data[0]) . '<br><br>';
$start = microtime(true);
$convertedData = [];
foreach ($data as $key => $value) {
$convertedData[$key] = (double) $value;
}
echo '(double) cast took ' . getTime($start) . ' ms.<br>';
$start = microtime(true);
$convertedData = [];
foreach ($data as $key => $value) {
$convertedData[$key] = 0 + $value;
}
echo 'Coercion took ' . getTime($start) . ' ms.<br>';
And my results are :
(double) cast took 27.508 ms.
Coercion took 28.789 ms.
CONCLUSION
Since using floatval
(a third way to achieve string to double conversion) is even longer, you can't do better than that with PHP. What you're trying to achieve is a scripting operation, it shouldn't be used as a normal back-end operation for a web application.
But if you still want to do that, you can higher your memory_limit
inside your php.ini
file, as long as you don't use the -1
workaround.
UPDATE
I forgot one possible optimization, you should pass your variable by reference to at least execute immediate assignation :
$start = microtime(true);
foreach ($data as $key => $value) {
$data[$key] = (double) $value;
}
echo getTime($start) . ' ms.<br>';
=> 34.018 ms.
$start = microtime(true);
foreach ($data as &$value) {
$value = (double) $value;
}
echo getTime($start) . ' ms.<br>';
=> 17.081 ms.
And apparently using coercion with by reference gives even better results :
$start = microtime(true);
foreach ($data as &$value) {
$value = 0 + $value;
}
echo getTime($start) . ' ms.<br>';
=> 13.1 ms.