Недавно в нашей компании было решено попробовать фреймворк phalcon c целью в перспективе кое-что отрефакторить и в новом коде использовать именно его. Причины банальны — скорость работы, симпатичный orm.
Но вот в процессе тестирования фреймворка у меня в голове все чаще и чаще стал всплывать термин «Принцип наименьшего удивления». И именно потому, что я все больше и больше удивлялся.
Возьмем стандартную ситуацию. Табличка
И… пользователь не создается. Если посмотреть ошибки для модели увидим такую: «comment is required». WTF скажете вы и будете правы:) Баг? скажете вы и будете не правы.
Смотрим Issue 440 от 22 февраля прошлого года и видим, что это фича.
Причины этой фичи — модели часто создаются и сохраняются после отправки пользователем данных из формы, многие функции, которые программист _может_ использовать для валидации (strip_tags, filter_var) при подаче им NULL на выходе выдают пустую строку. Поэтому программист гипотетически может получить случай, когда поле comment не будет отправлено через форму
Удивительно? По мне так очень.
Решения, кстати, приводятся. Но из-за этой странности приходится переопределять стандартную валидацию.
Ну и еще один пример из той же области:
Шаблоны в проекте могут лежать в нескольких местах, например отдельно шаблоны для каждого модуля, отдельно базовый шаблон проекта.
Что делать, если хотим в шаблоне модуля сделать
New feature request на это был отправлен 15 декабря прошлого года
В качестве частичного решения можно указать в качестве пути к шаблонам папку с модулями и потом указывать в контроллерах полный путь к шаблону от папки с модулями (
Вот, кстати, еще одно удивление — стандартный View не умеет рендерить шаблоны по пути, только по имени контроллера/действия (
Я настолько привык к синтаксису insert/update Doctrine DBAL, что и подумать не мог, что можно сделать как-то по другому. Оказывается можно.
Синтаксис phalcon DBAL и Doctrine DBAL:
и
и
По мне, так однозначно синтаксис Doctrine DBAL удобнее за счет унификации.
Я отправил pull request с концептом в phalcon incubator. Может быть добавят когда-нибудь:)
В целом, несмотря на некоторые неудобства, от идеи использовать phalcon не отказываемся, продолжаем тестировать.
Но вот в процессе тестирования фреймворка у меня в голове все чаще и чаще стал всплывать термин «Принцип наименьшего удивления». И именно потому, что я все больше и больше удивлялся.
ORM и пустые строки
Возьмем стандартную ситуацию. Табличка
Users (id int, name varchar, comment varchar not null default '')
. Создадим модель User для работы с этой табличкой и попробуем создать нового пользователя:$user = new User();
$user->id = 1;
$user->name = 'Robot';
$user->comment= '';
$user->save();
И… пользователь не создается. Если посмотреть ошибки для модели увидим такую: «comment is required». WTF скажете вы и будете правы:) Баг? скажете вы и будете не правы.
Смотрим Issue 440 от 22 февраля прошлого года и видим, что это фича.
Причины этой фичи — модели часто создаются и сохраняются после отправки пользователем данных из формы, многие функции, которые программист _может_ использовать для валидации (strip_tags, filter_var) при подаче им NULL на выходе выдают пустую строку. Поэтому программист гипотетически может получить случай, когда поле comment не будет отправлено через форму
($_POST['comment']==null)
, но программист использовал $user->comment = strip_tags($_POST['comment']);
и получил вместо null значение '' в поле comment.Удивительно? По мне так очень.
Решения, кстати, приводятся. Но из-за этой странности приходится переопределять стандартную валидацию.
Ну и еще один пример из той же области:
$user = User::findFirst("name='robot'");
$user->name='robot2';
$user->save();//!!!!!!WTF?
Папки для views
Шаблоны в проекте могут лежать в нескольких местах, например отдельно шаблоны для каждого модуля, отдельно базовый шаблон проекта.
Что делать, если хотим в шаблоне модуля сделать
{% extends base.twig %}
? Правильно, добавить в настройках view дополнительную папку для поиска базового шаблона. Но View::setViewsDir
принимает в качестве параметра только одну директорию!New feature request на это был отправлен 15 декабря прошлого года
В качестве частичного решения можно указать в качестве пути к шаблонам папку с модулями и потом указывать в контроллерах полный путь к шаблону от папки с модулями (
$this->view->pick("clients/views/index");
). Или отключить автоматический вызов рендеринга при настройке приложения ($application->useImplicitView(false);
), в качестве View использовать Phalcon\Mvc\View\Simple
и рендерить шаблоны вручную print $this->view->render('clients/views/client_view', []);
Вот, кстати, еще одно удивление — стандартный View не умеет рендерить шаблоны по пути, только по имени контроллера/действия (
$this->view->render('controller', 'view', []);
), поэтому в данном случае нужно использовать Simple.Странный синтаксис insert/update DBAL
Я настолько привык к синтаксису insert/update Doctrine DBAL, что и подумать не мог, что можно сделать как-то по другому. Оказывается можно.
Синтаксис phalcon DBAL и Doctrine DBAL:
$success = $connection->insert(
"robots",
array("Astro Boy", 1952),
array("name", "year")
);
и
$success = $connection->insert(
"robots",
array(
'name' => "Astro Boy",
"year" => 1952
)
);
$success = $connection->update(
"robots",
array("name"),
array("New Astro Boy"),
"id = 101"
);
и
$success = $connection->update(
"robots",
array("name" => "New Astro Boy"),
array("id" => "101")
);
По мне, так однозначно синтаксис Doctrine DBAL удобнее за счет унификации.
Я отправил pull request с концептом в phalcon incubator. Может быть добавят когда-нибудь:)
В целом, несмотря на некоторые неудобства, от идеи использовать phalcon не отказываемся, продолжаем тестировать.