Предыстория такова: писал я скрипт, который коннектится к pop3-серверу, выдирает оттуда все аттачи с нужными названиями файлов, парсит эти файлы и заносит отпарсенные данные в бд. Все было отлично, пока я писал на линуксе (писал, естественно, на php + mysql), а вот при попытке запустить этот скрипт на свежеустановленной винде (естественно, с апачем и прочим барахлом) - пошли error’ы…
Сразу скажу - пост написан совсем не для того, чтобы учить меня юзать ORM и ActiveRecord. Всё мы знаем, всё умеем, ноэто не тот случай.
Начнем издалека, а именно с PHP. В нем есть такой хороший и нужный (кроме программеров на си) тип как boolean, у которого есть значения true и false. Все бы хорошо, но есть одна проблема - при работе с бд все значения нужно преобразовывать к типу string (ну, а как вы sql писать собираетесь)… Точнее, это не проблема, а такой факт… Проблемы начинают возникать, когда мы преобразовываем boolean -> string. Преобразование получается довольно хитрое, в результате которого мы вместо true получаем ‘1′, а вместо false - … нет, если бы мы ‘0′ получали - все было бы отлично… мы получаем ”, т.е. пустую строку.
Этой проблеме уже хер знает сколько лет. Лечить ее разработчикам, видимо, влом.
Естественно, при вставке в БД все значения квотятся. Т.е. если у нас был запрос, в котором значение для поля будет false - получим примерно следующее:
INSERT INTO table(column) VALUES('')
Если бы типом column была строка - было бы всё ок. Но у меня это было булевое поле (если быть точным - smallint(1), т.к. в MySQL нет типа Boolean). И вот в линуксе (ubuntu) на MySQL Server’е из стандартных репозиториев все работало замечательно. А в винде - начало ругаться на эту строку.
Естественно, в данном случае можно решить проблему храня в переменных PHP не true/false, а 1/0, но меня заинтересовало - а почему же на Linux’е все это дело работает.
Покопавшись в настройках сначала PHP, а потом и MySQL (после того, как в PHP’шных настроках ничего интересного не нашел) - в my.ini (конфигурационный файл MySQL) были найдены интересные строчки:
# Set the SQL mode to strict
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
После того, как я их закомментировал, все заработало нормально, но…
Подытожу - при работе с MySQL в PHP не используйте переменные типа boolean, пользуйтесь int’ами. Даже если у вас все работает с true/false - не факт, что оно заработает у вашего заказчика.





December 3rd, 2007 at 12:26
(кроме программеров на си)
Дезинформация. Начиная с c99, у сишников есть bool. На дворе скоро 2008. Исправляйся.
December 3rd, 2007 at 13:32
Тоже всегда юзал bool :)
December 3rd, 2007 at 19:51
JackYF
Буду знать, спс.
Sam
Ну вот теперь я задумываюсь периодически - что лучше юзать - bool или int. %)
December 6th, 2007 at 15:39
это не баг, нужно преобразовывать к int
December 6th, 2007 at 15:46
Ну допустим. Покажи мне тогда логику:
true: boolean -> int -> string
false: boolean -> string (причем непонятно каким образом)
December 6th, 2007 at 15:57
Начнем с того, что в MySQL есть тип BOOL, BOOLEAN, который является синонимом для TINYINT(1).
Поэтому преобразований к строке не будет. Запрос будет выглядеть следующим образом:
$sql = “INSERT INTO table(column) VALUES(’” . (int)$variable . “‘)”;
Или я что-то не так понял?
December 6th, 2007 at 16:00
$sql = “INSERT INTO table(column) VALUES(’” . (int)$variable . “‘)”;
Это уже преобразование к строке. Сначала к int’у, потом к строке. ;)
December 6th, 2007 at 16:06
Ага, точно :)
Но, ведь для типа string, false - это пустая строка и “0″. Поэтому очень даже логично преобразовывать к int.
December 6th, 2007 at 16:13
Да мне много чем PHP не нравится. В частности, нестрогой типизацией. ;) Ну вот не нравится мне такое поведение с bool’ами…
December 7th, 2007 at 00:32
@FX Poster,
а чем не нравится?
В чем проблема сделать как посоветовали: $sql = “INSERT INTO table(column) VALUES(’” . (int)$variable . “‘)”; ?
А из-за не строгой типизации PHP многие вещи программистам “прощает” и упрощает во многих случаях работу.
December 7th, 2007 at 00:43
А из-за не строгой типизации PHP многие вещи программистам “прощает” и упрощает во многих случаях работу.
Тут спорить просто не хочется. Лично я упрощений не вижу. Вижу, скажем так, не совсем логичные преобразования в очень “удачных” моментах скриптов.
Преобразовывать - я то могу, мне не сложно. Но вот такие проблемы мне не нравятся. Очень напоминает проблемы верстки:
- “А в IE6 оно неправильно показывается :(”
- “А ты height: 1%; поставь ;)”
December 7th, 2007 at 12:57
Да, спорить не будем. Но сравнение с IE не очень удачное. Это из другой оперы.
December 7th, 2007 at 13:08
Что-то я сейчас попробовал в MySQL под Виндами вставить ” в поле BOOL, всё прокатило. MySQL сделал вполне логичное преобразование ” -> 0 (ведь MySQL — тоже язык с нестрогой типизацией) http://dev.mysql.com/doc/refman/5.0/en/type-conversion.html
В преобразовании false -> ” не вижу ничего страшного и нелогичного.
December 7th, 2007 at 15:43
По умолчанию в MySQL под виндой в настройках предлагается использовать строгий режим, который, ” за bool не воспринимает. :(
December 7th, 2007 at 15:44
Bolk
Да, кстати, что с твоим сайтом?
December 7th, 2007 at 19:21
DDoS на сайт Экслера. Вот и мой лежит, попал под замес.
December 7th, 2007 at 19:22
Если бы типизация была строгая, то и ‘0′ не превращалась бы в 0. Так как это преобразование varchar и int.
December 7th, 2007 at 22:39
Если бы типизация была строгая, то и ‘0′ не превращалась бы в 0. Так как это преобразование varchar и int.
Да ладно, хер с ним :)
December 15th, 2007 at 06:12
Да мне много чем PHP не нравится. В частности, нестрогой типизацией. ;) Ну вот не нравится мне такое поведение с bool’ами…
А вы строго типизируйте сами :)
December 15th, 2007 at 06:17
1. Лучше на “ты”.
2. Да бред, блин. Вон, Юрец пишет о том же…
December 15th, 2007 at 06:32
Прочел статью Юрца, согласен бред :)
Хотя anycolor правильно заметил что для этого есть “===”… Но все равно бредово
January 30th, 2008 at 07:31
Используйте bindParam из PDO с указанием типа, и проблема отпадёт. А в PHP проблемы возникают не из-за не строгой типизации, а из-за непродуманного механизма автоприведений типа. В руби с этим делом логичней как мне кажется.
January 30th, 2008 at 22:48
В руби строгая типизация. :)
PS. А если я не PDO использовал?