Description
Problem:
The conversion rates in the Goal Plugin are floats but always integer valued (1,0%, 2,0%, …) on a server located in Germany.
Reason:
In PHP the automatic float-to-string conversion is based on the value of setlocale(LC_NUMERIC)
. In English speaking countries a dot is used as the decimal separator while in some countries, e.g. Germany, a comma is used.
Example, where this issue is critical:
setlocale(LC_NUMERIC, "en_US");
$query = "INSERT INTO `values` SET `value` = $PI, `key` = 'PI'";
echo $query;
// output: INSERT INTO `values` SET `value` = 3.1415926535898, `key` = 'PI'
setlocale(LC_NUMERIC, "de_DE");
$query = "INSERT INTO `values` SET `value` = $PI, `key` = 'PI'";
// output: INSERT INTO `values` SET `value` = 3,1415926535898, `key` = 'PI'
This is harmful as the SQL query becomes invalid in the latter example.
Fix
Probably not a good solution, but for me the following change in piwik/core/Db.php
solved the problem:
public static function query($sql, $parameters = array())
{
setlocale(LC_NUMERIC, 'en_US'); // this line is a quick fix for this issue
try {
self::logSql(__FUNCTION__, $sql, $parameters);
return self::get()->query($sql, $parameters);
} catch (Exception $ex) {
self::logExtraInfoIfDeadlock($ex);
throw $ex;
}
}
Here are two posts about the setlocale issue:
http://mark-story.com/posts/view/php-floats-localization-and-landmines
http://blog.azure.km.ua/2012/12/php-typecasting-float-to-string-trap.html