ru en

Refreshing Nested Set Tree Indexes in Symfony

Tree

Once I used Nestedset behavior for Doctrine, Symfony in a project, and faced issue with broken indexes. (You can read how Nested Set works here). This happened because low-level MySQL query executed during migration, and because of this Doctrine events responsible for refreshing indexes was not executed. To fix that a Symfony Command was written, which refreshes indexes. This is just example. Better way is to move this code to the service and add one more migration which will refresh indexes. Here is just simple example how this issue can be solved.

Argument of the command is an entity to refresh.

Загрузка файлов в Symfony

Загрузка файлов в Symfony идейно ничем не отличается от других php-платформ, но все же имеет свои особенности вследствие наличия дополнительных инструментов, предоставляемых фреймворком.

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

В этой заметке попытаемся показать возможные пути решения поставленной задачи, как с помощью готовых решений (VichUploaderBundle, IphpFileStoreBundle), так и с помощью собственной реализации (в контроллерах Symfony и админ классах SonataAdminBundle).

Value Object'ы у Symfony формах

DecompositionSymfony разработчики часто задаются вопросом, как заставить Symfony формы работать с value-object'ами. Давайте, для примера, представим тип Money как объект с двумя полями $amount и $currency:

class Money
{
    private $amount;
    private $currency;

    public function __construct($amount, $currency)
    {
        $this->amount = $amount;
        $this->currency = $currency;
    }

    public function getAmount() // ...
    public function getCurrency() // ...
}

Можете ли вы создать form type для этого класса без методов setAmount() и setCurrency()? В этой заметке вы научитесь этому.

Удалить дефолтный блок sonata.admin.block.admin_list у SonataAdminBundle

При использовании SonataAdminBundle и SonataBlockBundle захотелось удалить дефолтный блок. 

Толку от него мало, он просто дублирует функционал бокового меню на дашборде.

При установке SonataBlockBundle, если мы просто напишем у конфигурации:

sonata_block:
    default_contexts: [sonata_page_bundle]
    blocks: []

(в будущем будем добавлять свои блоки, но для начала просто ставим пустой массив), то отловим ошибку.

Symfony Blog Bundle

HarentiusBlogBundle - бандл для  блога/простого портала (Или сложного, если с  наследованием бандлов и расширением). Движок этого сайта.

В качестве бэкенда используется SonataAdminBundle. Реализовано:

1. Админка (WYSIWYG, ckeditor), загрузка картинок, аудио, плеер.

2. Теги, категории, архивы, облако тегов

3. Статистика

4. RSS-feed (требует доработки)

5. "Умное" кэширование всего и вся, контент отдается очень быстро

Для "успокоения души" осталось:

1. Тесты

ru en

Symfony Widgets Bundle

Widgets Bundle - a bundle for easy widgets management. (Supports only widgets which require only client-side code for displaying). Includes both client side (for displaying) and admin side (adds admin classes and has a SonataAdminBundle dependency) functionality.

Can be used (for example) for adding counters, banners, advertising network codes (google adsense, etc).

Was created during this blog has been developing.

ru en

Caching Symfony controller

During developing this blog I invented one more bicycle for Caching Symfony controller. But first of all lets see how did this task arose.

For example, I have a list of categories, archives and tags on a sidebar. It is relatively easy to get last one (one query), but much harder to get list of categories and archives. For getting categories, we need to select trees (categories can be nested) and using subqueries inside queries get number of articles in every category (result is a little bit monster). For getting the archives list, we need iterate over all articles and gather list of years/months. All this actions isn't very sophisticated, but it is better to avoid them.

Локализация числовых/денежных данных

При разработке более-менее крупного проекта возникает проблема с локализацией числовых/денежных данных. В этой заметке расскажу о мучениях при использовании Symfony framework, Sonata Admin Bundle и клиентской части. Но сначала о сути проблемы, так как на первый взгляд она не очень очевидная.

Итак, допустим у нас есть проект, который на стороне сервера (php/шаблонизатор) рендерит числовые/денежные данные. Они должны отображаться в соответствии с установленной локаллю. Пользователь может вводить данные (в своем представлении). При этом данные могут обрабатываться еще и на клиентской части (javascript). К примеру, в большинстве стран Европы, кроме Великобритании и Ирландии десятичный разделитель запятая, в Великобритании и Ирландии - точка. Естественно, что пользователь с Германии будет вводить данные с раздилителем - запятою.

Кастомизация формы входа (на примере FOSUserBundle)

Самый проcтой способ кастомизации формы входа FOSUserBundle - использовать механизм наследования бандлов. (С предположением, что в будущем придется модифицировать не только форму входа). Покажем пример такой кастомизации с использованием bootstrap.

Фикстуры. AliceBundle

В предыдущей заметке мы познакомились с фикстурами в Symfony framework, а также с DoctrineFixturesBundle. Хотелось бы сделать обзор еще одного полезного бандла для работы с фикстурами - AliceBundle (обертка вокруг компонента alice).

Фикстуры. DoctrineFixturesBundle

Фикстуры (англ. fixtures) - очень полезный инструмент для разработки. По сути, это просто набор тестовых данных, которые используются в dev-режиме. Для prod режима обычно не используются (для прода обычно используют Data Migrations).

Для работы с фикстурами в Symfony существует несколько удобных бандлов. Первый, базовый - DoctrineFixturesBundle, которому и посвящена эта заметка.

Configuration

При создании бандла,  который будет использоваться как библиотека (и не только), полезно будет его конфигурировать.

Конечно, можно все вынести в параметры, обойтись таким образом без конфигурации, но это будет некошерно. =)

Правильная практика описывать конфигурацию в config.yml, а часть необходимых параметров выносить в parameters.yml: