开发者

SimpleXML weird typecasting behavior

开发者 https://www.devze.com 2023-03-15 23:19 出处:网络
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 SimpleXM

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.

Ok开发者_开发知识库ay, that's something that I can live with, the script was programmed by somebody who probably didn't know that he needs to typecast everything from SimpleXML, but this still seems a bit odd to me. Does anybody know how is this happening? PHP's ceil function acceps float as an argument, so I'd expect the value gets typecasted to float, but in this case, it's int. (you might want to run the code)

<?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.

0

精彩评论

暂无评论...
验证码 换一张
取 消