Недавно в нашей компании было решено попробовать фреймворк phalcon c целью в перспективе кое-что отрефакторить и в новом коде использовать именно его. Причины банальны — скорость работы, симпатичный orm.
Но вот в процессе тестирования фреймворка у меня в голове все чаще и чаще стал всплывать термин «Принцип наименьшего удивления». И именно потому, что я все больше и больше удивлялся.
ORM и пустые строки
Возьмем стандартную ситуацию. Табличка Users (id int, name varchar, comment varchar not null default '')
. Создадим модель User для работы с этой табличкой и попробуем создать нового пользователя:
$user = new User();
$user->id = 1;
$user->name = 'Robot';
$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 использовать PhalconMvcViewSimple
и рендерить шаблоны вручную 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 не отказываемся, продолжаем тестировать.
Автор: quantum