Fi1osof 28 ноября 2013 0 0
Сегодня наткнулся на жесточайшую багу…

У кого развернута сборка магазина или хотя бы стоит пакет shopModx, попробуйте в консоли выполнить вот такой код:
<?php
print '<pre>';
$q = $this->modx->newQuery('ShopmodxProduct');
$q->command('update');
$q->set(array(
    'sm_price' => 154.99,    
));
 
if($q->prepare()){   
    print $q->toSQL();
}

Результат: UPDATE `modx_shopmodx_products` SET `sm_price` = 154
Не 154.99, а просто 154… Думаю, каждый понимает печальность последствий, особенно когда полно товаров с ценниками типа 0.99
Но что тут самое интересное? А то, что если просто выполнить вот так, то все будет ОК:
$o = $modx->getObject('ShopmodxProduct', $id);
$o->set('sm_price', 154.99);
$o->save();


Первое: такое переменчивое поведение связано с тем, что через разные методы используются различные механизмы формирования запросов. К примеру, при вызове xPDOObject::save() у нас вполне явный SQL формируется. А вот при использовании xPDOQuery::set() уже механизм другой. И здесь самая западня вот в этих строчках:
elseif (!in_array($fieldMeta[$key]['phptype'], $this->_quotable)) {
     $type= PDO::PARAM_INT;
}

А какие типы у нас quotable?
'string', 'password', 'date', 'datetime', 'timestamp', 'time'

Как видим, там нет ни double, ни float. В итоге все приводится к INT-типу, а это, как известно, не подразумевает дробные числа. При этом в PDO в принципе нет ничего типа FLOAT или типа того. В сети полно вопросов PDO::PARAM_FLOAT does not exist, why?.
В итоге, видится только один вариант — определить float и double как строковые. А там сама база данных пусть занимается вопросами конвертации, она это обязательно сделает. Отправил PR.

Честно говоря, бага на столько скрытая, что я даже уже почти забил… Но в последний момент чутье вывело меня к нужной строчке. *немного похвастаюсь)))*
0 комментариев
Авторизуйтесь или зарегистрируйтесь (можно через соцсети ), чтобы оставлять комментарии.