PHP - случайный случай поведения

Я действительно сталкиваюсь с большой проблемой с несколькими веб-сайтами (фактически 3) на основе Prestashop. Проблема в том, что PHP или Prestashop случайным образом округляет цены до ближайшего целого числа и не систематический.

В большинстве случаев он работает отлично, как и должно быть, но иногда (может потребоваться несколько недель или месяцев между двумя проблемами), цена округляется. Моя опция круглого режима правильно настроена для отображения двух десятичных знаков.

Проблема может возникать при редактировании цены продукта в бэк-офисе или при клике на этапе проверки.

Я попытался воспроизвести проблему, поэтому я создал базовый тест: я извлекаю информацию о тележке, и я показываю ее цену. Я обновлял страницу много раз, и я видел, что цена закруглялась несколько раз. Самое интересное, что ни контекст, ни код не изменились между началом и окончанием теста.

Я искал помощь в Google, и ни у кого не было этой проблемы...

Кто-нибудь сталкивался с этой проблемой? Считаете ли вы, что это проблема с PHP или Prestashop? Заранее благодарим за помощь.

Вот код круглой функции Prestashop использует:

round($value, 2, PHP_ROUND_HALF_UP);

Для информации, версия PHP 5.4.39.

Ответ 1

Более двух лет спустя мы выяснили проблему. Это связано с тем, что php5-fpm не обрабатывает локали на поток, а на процесс. Это действительно ясно в документации PHP:

Внимание Информация о локали поддерживается для каждого процесса, а не для потока. Если вы используете PHP на API с многопоточным сервером, например IIS, HHVM или Apache в Windows, вы можете столкнуться с внезапными изменениями в настройках локали, пока работает script, хотя сам script никогда не вызывал setlocale(). Это происходит из-за других скриптов, выполняющихся в разных потоках одного и того же процесса одновременно, изменяя язык всей системы с помощью setlocale().

Поскольку разделитель десятичных чисел изменился, PHP не распознал десятичные числа и не усекал мои номера.

Ответ 2

Возможно, есть проблема, если в цене есть тысячный разделитель, например 12,300.20?

Пожалуйста, помните следующее:

Примечание. PHP по умолчанию не обрабатывает строки типа "12,300.2". См. Преобразование из строк.

Смотрите: http://php.net/round

Ответ 3

Я почти уверен в том, как числа с плавающей точкой хранятся в вашем компьютере или что-то в этом направлении, что может указывать на вас в правильном направлении.

http://php.net/manual/en/language.types.float.php

Проверьте это также, объяснив, почему числа с плавающей запятой не всегда равны, когда вы думаете, что должны. http://docstore.mik.ua/orelly/webprog/pcook/ch02_03.htm#phpckbk-CHP-2-SECT-3

Ответ 4

Могут возникнуть проблемы с локалями. В немецком, например, разделители тысяч и десятичные точки - это наоборот. Если вы не очень тщательно относитесь к тем, вы можете сохранить неправильные значения в некоторой степени персистентности или сломать некоторое значение, когда бросаете его в float. Помните - когда вычисление со строками (например: "2.55" ) php будет их применять для float, обработка немецких чисел ( "2,55" ) приведет к неправильному числу с плавающей запятой.

(float) "2.55" = 2.55
(float) "2,55" = 2

Проблема может быть устранена путем правильной настройки локалей.

Если вы можете сказать неверный результат от действительного автоматически, вам может потребоваться зарегистрировать debug_backtrace в этот момент, чтобы оценить поток программ в этом случае.