Phalcon - молодой PHP-фреймворк, выполненный в виде PHP-расширения. Он работает намного быстрее из-за того, что все основные операции выполняются на системном уровне. Однако, из-за того, что он молодой, иногда встречаются странные вещи. Вот об одном таком баге я сегодня расскажу.
Предыстория
Летом мы в команде начали разрабатывать проект на Phalcon 2. В этом проекте установка даты рождения пользователя реализована следующим образом: в браузере работает плагин календаря, который в результате вписывал в поле ввода дату в формате ДД.ММ.ГГГГ
.
После отправки формы контроллер отправляет дату в вышеуказанном формате в специальный метод в модели, который превращает строковую дату в timestamp.
1 |
|
Работает этот код хорошо на следующей конфигурации на PHP5.4 и Phalcon 2.0.3. Однако на PHP5.6 и Phalcon 2.0.13 начинаются проблемы. В результате выполнения функции setBirthday()
, в поле birthday
записывалось значение false
.
В первый раз это произошло у моего коллеги на Fedora с PHP5.6 и Phalcon 2.0.13. Я пытался помочь ему разобраться, но, честно сказать, списывал это на локальные баги окружения, потому что у меня все работало хорошо (Windows 10, OpenServer5.2.2, PHP5.6 и Phalcon 2.0.3). На production сервере все тоже работало хорошо (Phalcon 2.0.3).
Интересная особенность, правда? На 2.0.3 работает нормально, а на 2.0.13 нет. Но об этом далее.
Выявление проблемы
Когда проблема проявилась у меня на машине (PHP5.6, Phalcon 2.0.13) я все-таки решил разобраться в ней. И вот что получилось.
1 |
|
Расставил отладочные выводы на каждый чих и посмотрел, что происходит в процессе выполнения функции:
1 |
|
Таким образом, видно, что идет вложенный вызов функции. Контроллер вызывает setBirthday()
, она начинает выполняться, потом доходит до установки значения в свойство $this->birthday = $res;
и функция начинает выполняться заново, принимает уже числовое значение из strtotime, а потом не может это числовое значение опять привести к числу, потому что strtotime
требует строку. Очевидно, что идет какая-то магия, вызов магического метода setBirthday()
.
Документация Phalcon
В документации Phalcon 3 уже есть блок, описывающий работу магических методов в модели. Но в Phalcon 2 его еще не было.
Не так давно в версии 2.0.11 был закрыт issue, который решает проблему с getters & setters. Таким образом, с версии 2.0.11 они начинают нормально работать, и поэтому на версии 2.0.13 проявлялся баг.
Ну а решение есть в документации: свойства, которые мы меняем через getters/setters должны быть protected
.