Today one of our clients sent a complaint that on his shop, some prices are a little lower (1,- Kč precisely). When I started to debug, I thought this might be a rounding error. We're using SimpleXML to import products' prices and from the look of the code, everything seemed about right, but when I did dome var_dumps, some prices were really badly rounded. There is a ceil function which kept ceiling 54.6200
to 54
. I understand that I have to typecast all the SimpleXML values before using them, but this behavior seemed quite odd to me. It seems that when I ceil a floating point vlaue stored in a string node of SimpleXMLElement, the value gets typecasted to int before the ceil function.
<?php
$item = simplexml_load_string(
<<<ITEM
<Item>
<PHE>54.6200</PHE>
</Item>
ITEM
);
echo '<pre>';
echo $item->PHE.PHP_EOL; //54.6200
echo ceil($item->PHE).PHP_EOL; //54!!!
echo ceil((string)$item->PHE).PHP_EOL; //55
echo ceil((float)$item->PHE).PHP_EOL; //55
echo ceil('54.6200'); //55
echo PHP_EOL.PHP_EOL;
debug_zval_dump($item);
echo '</pre>';
Output of that zval_dump:
object(SimpleXMLElement)#1 (1) refcount(2){
["PHE"]=>
string(7) "54.6200" refcount(1)
}
PHP generally prefers to convert an object to a integer in the context of a mathematical operation. Let's say you do:
$obj = new InternalClass();
var_dump(5 + $obj);
The implementation of this operator sees an object and has to decide what to do with it. Internal objects are provided with a hook that allows them to be converted to any type (cast_object
). However, this handler receives only one target type. The engine has to decide to which type to convert the object before doing so, and unfortunately, it chooses the integer type.
Your only option is to add an explicit cast, as you do.
精彩评论