Pull to refresh

Comments 22

Чертовски много лишних телодвижений.
Это вы о конкретно этом примере или о Zend-фреймворке в целом?
После symfony 1.4 я вообще не могу понять курс современных фреймворков: что zf2, что sf2 — столько всего приходится писать руками, что, порой, задумываешься: «а надо ли вообще всё это?»
Суть статьи — показать пример разработки готового модуля, а не написать полноценный блог.
Как опытный разработчик, вы должны понимать, что с ростом функциональности системы и объема кода она (система) становиться неуправляемой. При должной структуризации кода этот момент откладывается (почти) на неопределенное время, вполне возможно до конца актуальности самой системы.

Простой блог как в статье, на чистом PHP, где код написан в хардкорном стиле «здесь и сейчас» можно вложится в несколько экранов, но сопровождение кода в гораздо сложных проектах будет излишне дорого для бизнеса.

Курс современных фреймворков состоит в понижении сопряжения компонентов, из чего следует минимизация сложности, снижение количества ошибок, уже далее простота разработки и сопровождения ПО.
Поэтому ответ на ваш (может быть риторический) вопрос: да, надо. Но прежде всего нужно помнить: для каждой задачи должен быть осознанно применен свой инструмент.
Чего? Вы комментарий мой точно читали? А про symfony 1 что-нибудь слышали? Каким боком моё высказывание коррелирует с тем, что я не признаю и не понимаю назначение фреймворков?
Я где-то говорил о том, что кода слишком много? Я просто свято верю в то, что кодогенерация решает проблемы (особенно, крупных проектов).
В симфони 1.4 то, что вы написали на несколько экранов заключается в следующих действиях:
— описать (декларативно) схему модели
— сгенерировать модели, формы, фильтры, админку, роуты и sql несколькими консольными тасками
При этом, получившийся продукт не будет ни в чём уступать Вашему (в плане кастомизации или абстрактности), но ручного ввода текста (довольно подверженного ошибкам, к слову) будет в несколько раз меньше.
Вообще, если бы Вы внимательно прочли мой вопрос, то могли бы его свести к «где скаффолдинг? Неужели, этот код не мог сгенерировать компьютер?»
а что, в sf1 сильно лучше скаффолдинг чем стоковая кодогенерация через SensioGeneratorBundle и sonata admin во второй симфони?
Понятия не имею, если честно: дальше чтения мануалов, подобных этому (с 20 экранами кода, вместо 20 строк) с сф2 у меня не зашло. Но спасибо, что дали направление — обязательно поизучаю эти бандлы.
Вас интересовал курс современных фреймворков — я описал свое мнение. Прямых утверждений касательно ваших взглядов в моем комментарии нет, к чему негатив?
Кодогенерация как и в первых версия была, так и во вторых есть. Если вас интересует тема скаффолдинга в ZF2, увы, статья не про это.
А Ваш продукт на симфони 1.4 будет все же уступать аналогичному на sf2, как и продукт на zf1 будет уступать продукту на zf2 по причинам описанных мною выше.
Соглашусь, пост читать тяжеловато, хотя тема интересная и полезная. Попробуйте куски кода убрать в раскрывающийся блок, тогда пост по размеру уменьшится на 30-50%. Так же читать просто порядок действий не очень интересно, можно сравнить, как это делается в других фреймворках и ваше субъективное мнение о том, что тут происходит и можно было бы это как то улучшить или вообще не использовать.
Вообще, цель статьи не в том, чтобы сравнить Zend с другими фреймворками, а в том, чтобы дать разработчикам, начинающим работать с фреймворком, ответы на вопросы: что такое ServiceManager, как работать с формами, БД и т.п. Соглашусь, читать лучше на свежую голову, но текста примерно с такой структурой мне не хватало когда я начал свое знакомство с этим фреймворком.
1) Зачем в каждом экшене делать
 $objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
?
В зенд же есть хуки перед вызовом экшена?

2) Почему в мире php не принято следовать REST? Ведь очень некрасиво выглядят эти постоянные проверки на то, что запрос POST?

3)
$blogpost->setCreated(time());

Разве это нельзя сделать в хуках доктрины prePersist?

4)
$blogpost->setUserId(0);

что это за магия?

5)
$id = (int) $this->params()->fromRoute('id', 0);
    if (!$id) {
        $this->flashMessenger()->addErrorMessage('Blogpost id doesn\'t set');
        return $this->redirect()->toRoute('blog');
    }

    $objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');

    $post = $objectManager
        ->getRepository('\MyBlog\Entity\BlogPost')
        ->findOneBy(array('id' => $id));

    if (!$post) {
        $this->flashMessenger()->addErrorMessage(sprintf('Blogpost with id %s doesn\'t exists', $id));
        return $this->redirect()->toRoute('blog');
    }


можно переписать как
    $objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');

    $post = $objectManager
        ->getRepository('\MyBlog\Entity\BlogPost')
        ->findOneBy(array('id' => $id));

    if (!$post) {
        $this->flashMessenger()->addErrorMessage(sprintf('Blogpost with id %s doesn\'t exists', $id));
        return $this->redirect()->toRoute('blog');
    }


Проверка на существование id не имеет особого смысла, обычно это просто 404 страница. Юзер не должен руками править урл.

6) EntityManager не кидает эксепшн, просто возвращает null. docs.doctrine-project.org/en/2.0.x/reference/working-with-objects.html#querying, если не найдена запись.

7)
$posts = $objectManager
        ->getRepository('\MyBlog\Entity\BlogPost')
        ->findBy(array('state' => 1), array('created' => 'DESC'));

Что за магическая 1?
1) Зачем в каждом экшене делать?.. В зенд же есть хуки перед вызовом экшена?
3) Разве это нельзя сделать в хуках доктрины prePersist?


Не готов ответить на вопросы, попробую изучить его и переделать этот кусок.

2) Почему в мире php не принято следовать REST? Ведь очень некрасиво выглядят эти постоянные проверки на то, что запрос POST?

Наверняка это возможно, изучу этот вопрос и переделаю этот кусок кода.

4) что это за магия?

Пока в проекте нет работы с пользователями, по этому тут хардкодится ноль, в третьей части я прикручу юзеров и эта строчка будет заменена на айдишник текущего пользователя.

7) Что за магическая 1?

Это статус. 0 — не опубликовано, 1 — опубликовано. У вас есть предложение как убрать эту магическую константу?
4) можно было пока вообще не думать о юзере, а добавить его в дальнейшем потому, что магический ноль смущает.
7)
//class BlogPost
const PUBLISHED = 1;
const NOT_PUBLISHED = 0;

...

$posts = $objectManager
        ->getRepository('\MyBlog\Entity\BlogPost')
        ->findBy(array('state' => BlogPost::PUBLISHED), array('created' => 'DESC'));


Вообще, тут неплохо было бы вынести это в класс-репозиторий для BlogPost, чтобы было вроде:
$posts = $objectManager
        ->getRepository('\MyBlog\Entity\BlogPost')
        ->findPublished();
Привет старым друпалерам :)

Проблема в том, что неудобно (а в Twig-шаблонах, которые мы будем использовать позже, и вовсе невозможно) вызывать PHP-код для вывода сообщений. По этому мы напишем небольшой View-плагин, который сможет одной строчкой выводить на экран все сообщения.


не знаю как в zf, а в symfony2 в твиге очень даже возможно вывести сообщения без дополнительных плагинов:
{% for flashMessage in app.session.flashbag.get('notice') %} <div class="flash-notice"> {{ flashMessage }} </div> {% endfor %}

symfony.com/doc/2.1/book/controller.html#flash-messages
Привет, Антон :)

Проверил, вот такая конструкция в Твиг шаблоне работает:
{% for flashMessage in flashMessenger().getMessages() %}
  <div class="flash-notice"> {{ flashMessage }} </div>
{% endfor %}


Но вариант с view-плагином мне все же нравится больше:
{{ showMessages() }}
Нервным не читать
У себя в проектах в скелет страницы вставляю шаблон
    <span id="top-of-container">
        {% if flash_error %}
            {% include 'snippets/alert.danger.html.twig' %}
        {% endif %}
        {% if flash_warning %}
            {% include 'snippets/alert.warning.html.twig' %}
        {% endif %}
        {% if flash_success %}
            {% include 'snippets/alert.success.html.twig' %}
        {% endif %}
        {% if flash_console %}
            <script type="text/javascript">
                {% for flash in flash_console %}
                console.info({{ flash|json_encode|raw }});
                {% endfor %}
            </script>
        {% endif %}
    </span>


знаю что *овнокод, но работает и ладно.

В коде достаточно сделать так:
ТО_ЧТО_УХОДИТ_В_ШАБЛОН_ТВИГА['flash_error'] = 'F*CK';

или так:
ТО_ЧТО_УХОДИТ_В_ШАБЛОН_ТВИГА['flash_error'][] = 'F*CK';


$blogpost->setCreated(time());
Для этого есть Timestampable из DoctrineExtensions.

Конфиги в виде многомерного массива подбешивают, ну есть же yaml/xml, не удобно ведь такие конфиги использовать…
Николай, я правильно из вашего комментария понял, что в Zend'е при помощи классов Zend\Config\Reader можно не только читать настройки своих кастомных модулей, но и прикрутить как замену application.config.php, *global.php, *local.php и конфигов модулей?
zend-developer-tools можно и нужно использовать на проде, если нет нормального мониторинга (пинбы например).

Для этого достаточно сделать другую среду(набор конфигов, в котором будет zdt) и в public создать еще один скрипт, на который завернуть поддомен с http-авторизацией или доступ по офисному(домашнему) ip (ex. Zend\Mvc\Application::init(require_once 'config/app/dev.config.php')->run();)
Не используйте плз вызовы классов через глобальное пространство имен ($form = new \MyBlog\Form\BlogPostForm())

Сделайте импорт перед объявлением кода класса (use MyBlog\Form\BlogPostForm) и уже в коде класса используйте плз $form = new BlogPostForm().
<?php

print $this->showMessages();

print '<h1>' . $post['title'] . '</h1>';

print '<div>' . $post['text'] . '</div>';

Что это? То есть либо twig, либо такая жесть?)

<?= $this->showMessage(); ?>

<h1><?= $post['title']; ?></h1>

<div><?= $post['text']; ?></div>

Поправьте плз, это же люди читают…
Не понимаю, что это у автора. Жесткая нехватка времени или лютое нежелание ответить кому-либо в лс? Раз 5 писал в ЛС, но человек не слышит.

Пока делал, наступил на грабли. В коде нужно кое-что поправить:

Когда мы создаем форму мы создаем поле с name = security:
Кроме того, я добавил к форме Csrf-токен (поле security), который должен защитить форму от подделки.
. В представлении нужном, это поле не выводится.

В итоге страница перезагружалась, но форма не отправлялась, так как не проходила валидацию. Сообщение об ошибке удалось получить только после танцев с бубнами. В итоге поправил view, добавив:
echo $this->formRow($form->get('security'));

Теперь все работает так, как нужно.
Sign up to leave a comment.

Articles