Всего понемногу

Originally published at ostretsov.ru. You can comment here or there.

Глобальный .gitignore_global у меня выглядит так (раньше его не было вообще):

.idea

Теперь не нужно в кажом проекте добавлять в исключения директорию с конфигурациями среды разработки. Спасибо ребятам из 37signals: благодаря их .gitignore обратил на это внимание.

Вышла недавно 2ая версия книги progit. Помимо стандартных основ есть новая глава по работе с github’ом. Наверное, узнаю что-то новенькое.

Интересный бесплатный сервис генерации скриншотов сайта в разных браузерах: http://www.browserstack.com.

Небольшое открытие, спасающее красоту кода:

<service id="service_name" class="Doctrine\ORM\EntityRepository" factory-service="doctrine" factory-method="getRepository">
    <argument>Vendor\AcmeBundle\Entity\FooBar</argument>
    <call method="setTranslator">
        <argument type="service" id="translator" />
    </call>
    <call method="setFormFactory">
        <argument type="service" id="form.factory" />
    </call>
    <call method="setJmsSerializer">
        <argument type="service" id="jms_serializer" />
    </call>
    <call method="setEventDispatcher">
        <argument type="service" id="event_dispatcher" />
    </call>
</service>

Благодаря factory-service можно создать сервис, например, репозитория и здесь же инжектировать дополнительные необходимые сервисы.

По ходу прочтения “Symfony best practices”

Originally published at ostretsov.ru. You can comment here or there.

Здесь кое-какие замечания по ходу чтения Symfony best practices. Я уже читал этот мануал по диагонали. На этот раз решил пройтись по нему внимательнее: от корки до корки.

Один генеральный (AppBundle) бандл на весь проект
Это очень удобно, если проект на неделю-две, но большие проекты, которые поддерживаешь годами хочется разбить на логические бандлы. Просто так удобнее ориентироваться в коде спустя какое-то время. В текущем проекте пока только 284 класса, разнесенных на 6 логических бандлов. Представляю какой бы это был огород, если бы все классы лежали в AppBundle.

4 глава, бизнес-логика
Понравилось замечание по именованию сервисов. Я до сих пор использую имена вроде sp_event.request_form.builder.field_collection_builder. В гайдбуке рекомендуют не извращаться и придумывать лаконичные имена. С этим полностью согласен. Писать подобные вызовы сервисов слишком ugly:

$this->getContainer()->get('sp_event.request_form.builder.field_collection_builder')->...;

Использование Yaml’а для определения сервисов. Да, он более читаем и короток. Мне больше по душе XML. Разницы с точки зрения производительности нет, поэтому это больше вопрос вкуса. В следующем проекте попробую Yaml.

Полезно было вспомнить вот про этот проект: https://github.com/fabpot/PHP-CS-Fixer. Это про приведение кода проекта к PSR-стандарту оформления. За несколько секунд на выходе получаем красивый код. Дешево и красиво.

Странно, что в гайдбуке инициализируют массив по-старому: array(), хотя PHP 5.4 вышел более двух лет назад.

Упомянут был хороший md2html парсер.

Глава 7, формы
Это мой любимый компонент. Всегда использовал проверку

if ($form->isValid()) {
    // do sth...
}

Для красоты оформления и читаемости кода рекомендуют еще предварить условие $form->isSubmitted() проверкой. Ок, согласен, красивый код – один из моих приоритетов при разработке.

Для трансляций рекомендуют использовать XLIFF формат. Мне он кажется менее удобным, чем YAML, но действительно для профессиональных переводчиков поддерживается немало редакторов, работающих именно с XLIFF. Еще надо бы попробовать JMSTranslationBundle в каком-нибудь проекте. Действительно удобный бандл?

Показалось разумным выносить трансляции в глобальную область видимости (app/Resources/translations).

Узнал кое-что про подбор паролей с помощью радужных таблиц. Если используется соль (salt) для усложнения конечного хеша пароля, то взломать такой пароль кроме как брут-форсом невозможно (возможно конечно, но неоправдано дорого).

Глава 9, security
Я не сторонник использования ACL в виде готового решения от Sensio. Если он нужен, то я делаю свой на базе воутеров. Пока что это было оправдано даже в очень сложных проектах со сложной иерархией ролей (например, было 5 acl_* таблиц; для каждого пользователя создавался граф привелегий и кешировался в Redis; наличие привелегии проверялось в воутере). Недавно (месяца 3 назад) вышел замечательный Expression-компонент и он изумительно скрещивается с Security компонентом (и ParamConverter’ом конечно же) для проверки привелегии в аннотации подобным образом:

/**
* @Route("/{id}/edit", name="admin_post_edit")
* @Security("is_granted('edit', post)")
*/
public function editAction(Post $post)
{
    // sth

Красиво. Лаконично. От этого невозможно отказаться.

Глава 10, assets
Да, надо след проект заточить на Grunt/gulp. Ради интереса :).

От себя бы еще добавил обязательность регулярной проверки бандлов в продакшене:

bin/console security:check

Раздаю заказы

Одному из моих заказчиков сделали сайт для его частного аэропорта. Дизайн приятный, но бэкграунд у проекта крайне слабый, из-за чего сайт периодически взламывали. Обратились ко мне. Через час ленивого ковыряния сайта я и сам его взломал, вытащив учетку администратора через SQL injection. Логин и пароль администратора хранились в открытом виде. Посмотрел код: код проекта абсолютно неподдерживаемый, нетестируемый и т.д. Решили перенести бекграунд на новые рельсы. Я люблю Symfony, поэтому ищу исполнителя на этом фреймворке (у самого есть другой интересный заказ на данный момент). Я оценил максимальный объем работы в 2 рабочие недели (10 рабочих дней по 8 часов).

Интересный подход к тимбилдингу от Atlassian

Originally published at ostretsov.ru. You can comment here or there.

Интересные слайды. Все, кроме алкоголя. Считаю, что культура инженера состоит еще и из рачительного отношения к своему здоровью. Достаточно изучить внимательно собственную кровь после употребления алкоголя, чтобы понять какие проблемы возникают у мозга от слипшихся эритроцитов. Сразу могу предложить позитивное решение взамен алкогольному – командные спортивные игры.

How to access to macro dynamically in Twig template?

Originally published at ostretsov.ru. You can comment here or there.

You may access to macro dynamically in Twig but this solution is risky. This method will’t ever be in best practice guidebook. But… It works.

Every Twig template is compiled to common PHP file and every macro converted to public method. For example, this foo macro:

{% import _self as _util %}

{% macro some_method(param) %}
    {{ param }}
{% endmacro %}

is compiled to something like this:

    // line 10
    public function getsome_method($_param = null)
    {
        $context = $this->env->mergeGlobals(array(
            "param" => $_param,
        ));

        $blocks = array();

        ob_start();
        // ...

As you may know it is possible to access public method with attribute Twig-function. So, solution will be like this:

{% set macro_name = 'some_method' %}
{{ attribute(_util, 'get' ~ macro_name, [param]) }}

Немного о текущем

Originally published at ostretsov.ru. You can comment here or there.

Поучаствовать на московском марафоне я не смог – заболел под конец тренировок ленью. Последние три-четыре недели погрузился с головой в работу и совсем не занимался бегом. Оправдаться в своих глазах хочу на предстоящем сочинском полумарафоне (3 ноября). 21 км для меня уже не дистанция. Тем не менее буду понемногу тренироваться.

С середины августа занимаюсь английским по скайпу. Предподаватель(ница) из Украины – вынуждена была бежать в Луганск из зоны боевых действий. Университет и лицей, в которых она преподавала закрыты. Судьба её подруг и друзей, которые не могут работать через интернет бедственная.

На последнем уроке английского работали с текстом о выигравшей лотерею женщине. Если бы я выигал 1 500 000 GBP, то купил бы пару гостиниц в разных европейских (вот такой у меня патриотизм) странах на берегу моря. И занимался бы все свободное время медитацией, спортом, учил бы языки и набирался мудрости. Очень сомневаюсь, что я бы как и прежде программировал.

Read the rest of this entry »