Неочевидные особенности сравнения в PHP

Однажды делал постраничный вывод сообщений в форуме. Делался он следующим образом: через параметр запроса start передавалось смещение от начала темы, или all, если нужно было показать всю тему, или параметр p, если требовалось показать конкретное сообщение. При этом при передаче p переменная start бралась не из запроса, а рассчитывалась на основе смещения этого сообщения от начала темы минус несколько сообщений. При этом если оно было в начале, то start мог получиться отрицательным, и для этого случая делалась дополнительная проверка с присвоением sstart=0.
Далее у меня в коде была проверка if ($start!='all'), по которой к SQL-запросу добавлялась LIMIT-часть. Но обнаружилось, что в некоторых ситуациях LIMIT-часть не добавляется, и вся тема выводится целиком (что серьезно нагружало сервер, если тема была длинная).

Стал разбираться, в чем дело, и обнаружилось, что ошибка проявляется тогда, когда в start присваивается 0 в результате расчетов. Происходило следующее: в результате проверки в левой части сравнения оказывалась переменная типа integer, и правая часть приводилась также к integer, в результате чего из 'all' получался ноль, и условие оказывалось ложным (то есть по сути проверялось 0!=0). Избавиться от этого оказалось очень просто: заменить тип сравнения на сравнение без приведения типов, т.е. $startl!=='all', после чего все заработало.

А вывод простой: нужно всегда использовать сравнение без приведения типа (т.е. === или !===), если нет явных причин поступать иначе. Оно и выполняется быстрее, и позволяет избежать подобных ошибок (которые, кстати, могут сказаться и на безопасности.)


0