Pull to refresh

Разработка сайтов на Diem CMS: преимущества, философия, примеры и подводные камни

Reading time12 min
Views2.6K
Продолжение истории про замечательную инициативу группы французских web-разработчиков под названием Diem CMS.

В этой статье вас ждут


— несколько примеров того, как Diem может облегчить жизнь вебмастеру
— подводные камни, с которыми вы можете столкнуться, и их возможные решения
— немного философских рассуждений о том, чем Diem принципиально отличается (в лучшую сторону) от соратников
— интересные факты, связанные с топиком
— а также скриншоты и примеры кода
Статься получилась объемная и содержательная.

Практика


Предисловие
За последние два месяца я написал 6 сайтов на этой CMS от 5-страничных до 2000-страничных, два сайта расположены на виртуальном хостинге, два на VPS-сервере. Памяти везде по 128Мб.
Деготь
Ох уж эта практика, которая показала, что использование Diem на обычных виртуальных хостингах на данный момент ничего хорошего не сулит…
Во первых, ограничение памяти меньше положенных 48Мб может вызвать Fatal error: Allowed memory size of X bytes exhausted, при обслуживании страниц используется около 8Мб, но при системных вызовах (как обновление конфигурации, поисковое сканирование Zend_Search_Lucene ) памяти используется много больше (не исключено, что разработчики кое-где забывали о контроле заполнения памяти при выполнении длинных циклов)
Во вторых, при отсутствии APC кэширования со стандартными настройками ./configure, Diem отрабатывает страницу около двух секунд (это при 200мс на аналогичной конфигурации, но с APC)… прим. это моя догадка, дело в том, что на виртуальном хостинге скрипт работает 2000мс, а на VPS 200мс, и там и там установлен APC, но на виртуальном хостинге нет системной поддержки POSIX shared memory. Думаю дело в этом, хотя не исключены и другие варианты.
В процессе настройки APC с различной конфигурацией мне помог разобраться что к чему этот документ:
image глубокий обзор и исследование APC-кэширования от facebook
Мед
Из приятного: несмотря за кажущуюся тяжеловесность системы, на самом дешевом VPS от reg.ru у меня сейчас спокойно уживаются пять сайтов, памяти всем хватает, страницы отдаются через 200мс после запроса. Этим фактом я вполне доволен, учитывая что Diem таит в себе гораздо больше плюсов, чем минусов, о которых я еще расскажу, не в этом, так в следующих постах.
Радует и маленькое, но отзывчивое сообщество. Судя по скорости ответов, разработчики посещают сообщество каждый день и охотно отвечают, а не посылают в гугл. (Прувлинки: 1,2)

В лучших традициях Symfony, Diem подкреплен качественной и понятной документацией, в которую входят:
— неделя Diem
погружение в разработку за 7 дней, на практике за 2 часа можно проделать все шаги недельного курса
— how-to советы для распространенных задач
— и подробное пошаговое описание всех возможностей CMS

Помимо этого имеются форум и гугл-грруппа, где можно спросить совета у сообщества.
Все это находиться на офф.сайте diem-project.org

Ах, да. Совсем забыл, тем кто не силен в английском будет полезен diem-project.ru — частично переведенный клон diem-project.org, его создатель Владислав Лежнев вышел на связь после последнего поста, мы с ним немного поговорили о Diem и в общем-то сошлись во мнениях, что эта CMS достойна внимания и ее стоит использовать.

image Интересный факт: большая часть проекта была написана одним человеком в период с 23.08.2009 по 31.01.2010 после чего в проекте появилось еще около 5 разработчиков.

Философия


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

В итоге структура контента следующая: шаблоны -> зоны -> страницы -> виджеты

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

Например, раньше у меня часто вставала необходимость поменять местами некоторые блоки в сайдбаре (места блоков были захардкожены в шаблоне), делалось это конечно быстро и просто, но ручкам и в коде. А здесь минусы: долгое время изменения для заказчика, вероятность внести ошибку при правке. Сейчас же клиент сам может переставлять блоки местами, когда ему заблагорассудиться.

Привожу примеры управления содержимым страницы:


На этом рисунке мы видим, что страница разбита на зоны и виджеты (блоки), и что их можно перетаскивать.


На этом рисунке мы видим, открытую медиа-галерею, окно редактирования виджета «breadcrumbs» и панель виджетов, доступных для добавления на страницу.

Пробуем написать собственный модуль


Приведу пример из жизни последнего проекта: необходимо создать базу данных отелей с разделением по странам и естественно возможностью администрирования. Как по вашему сколько это займет времени? Посмотрим…

Шаг 1.
Первым делом проектируем базу данных (с помощью Doctrine и YAML файлов делать это одно удовольствие):
Hotel:<br/>  actAs: [ DmSortable, DmGallery ]<br/>  columns:<br/>    name: { type: string(255), notnull: true }<br/>    country_id: { type: integer }<br/>    url: { type: string(255) }<br/>    text: { type: clob, extra: ckeditor }<br/>    is_active: { type: boolean, notnull: true, default: true }<br/>    rating: { type: float }<br/>    status: { type: integer(4), default:  0 }<br/>    votes: { type: integer }<br/>  relations:<br/>    Products: { foreignAlias: Hotels, class: Product, refClass: ProductHotel }<br/>    Country: { foreignAlias: Hotels }<br/> <br/>Country:<br/>  columns:<br/>    name: { type: string(255), notnull: true }<br/>    slug: { type: string(255), notnull: true } <br/>


Вроде бы все что нам нужно указали: таблица отелей, таблица стран, связь между ними. В этом коде кроется несколько Diem-обозначений, которые глобально для всего проекта задают поведение таблицы, а именно: is_active, DmSortable, DmGallery и extra: ckeditor.
Смысл is_active кроется в том, что теперь diem знает что для списков отелей существуют «активные» и «неактивные» объекты. При управлении мы будем иметь возможность управлять активностью via ajax, а при просмотре на странице будут выводиться только активные записи.
extra: ckeditor добавляет при редактировании WISIWYG.
DmSortable — дает возможность вручную сортировать список отелей
DmGallery — дает возможность прикреплять к каждому отелю неограниченное число фотографий. Все файлы хранятся и управляются в Diem с помощью компонента Media, т.е. вам не нужно писать собственные обработчики загрузки картинок, обрезки под размер различными методами, более того в шаблонах вы сможете указывать любые размеры изображений, Diem сгенерирует картинку нужного размера на лету.

Шаг 2.
Теперь нам нужно указать системе как мы хотим организовать записи в модули и компоненты: делается это опять же с помощью YAML в соответствующем файле конфигурации.

"Каталог":<br/> <br/>  hotel:<br/>    model: Hotel<br/>    page: true<br/>    name: 'Отель|Отели'<br/>    admin: true<br/>    components:<br/>      searchForm:<br/>        name: 'Форма поиска'<br/>      searchResults:<br/>        name: 'Результаты поиска'<br/>      show:<br/> <br/>  country:<br/>    model: Country<br/>    name: 'Страна|Страны'<br/>    admin: true <br/>


Что мы сделали: сказали что записи-отели будут страницами, у отелей и стран должен быть админ-интерфейс, и для фронтэнда нам нужны будут блоки: просмтотра отеля, формы поиска отеля и результатов формы поиска. Помимо этого ключевые слова list и show в названии компонентов фронтенда позволяют автоматически сгенерировать выборку списка или единого объекта (не нужно писать запросы к БД), осталось только заверстать.

После описания схемы БД и схемы модулей выполняем в консоли:
symfony doctrine:generate-migrations-diff
symfony doctrine:migrate
symfony dm:setup


Получаем на выходе сгененированные ORM модели, фильтры и формы Doctrine, админ модули управления отелями и странами со всем необходимым набором действий и шаблонов.




Неплохо для 20 минут потраченного времени и около напечатанных 200 символов. Я как человек ленивый был восхищен возможностями генерации стандартного функционала, а как человек, любящий мощный и качественный функционал, я был просто шокирован, ну к примеру форма фильтра помимо своего непосредственного назначения: фильтрации по определенным полям, позволяет еще и производить полнотекстовый поиск по всему содержанию модуля.

«И это еще не все!» (с)
В подарок вы получаете сгенерированные шаблоны для фронтенда, которые становятся доступными для перетаскивания в любую зону страницы. К сожалению читать мысли, верстать и создавать дизайн Diem не умеет — поэтому эту работу придется делать самому, но и здесь нас ждут приятные сюрпризы. Т.к. статья уже раздулась, я просто приведу пример для блока «список отелей»:

<?php<br/> <br/>echo _open('div.product_list');<br/> <br/>echo _open('ul.smartcolumns');<br/> <br/>foreach($hotels as $hotel)<br/>{<br/>    $url = _link($hotel)->getHref();<br/>    $data = 'infotext';<br/> <br/>    ?><br/>    <li style="cursor:pointer;" onclick="window.location = '<?php echo $url ?>';"><div class="block hotel"><br/>        <a href="<?php echo $url ?>"><br/>            <?php if ($hotel->getNbMedias()) echo _media($hotel->getFirstMedia())->width(100) ?><br/>        </a><br/>        <div class="txt"><br/>            <a href="<?php echo $url ?>"><b class="name"><?php echo $hotel->name ?></b></a><br /><br/>            <div class="txt2"><?php echo $hotel->rating ?></div><br/>            <?php echo $data ?><br /><br/>        </div><br/>    </div></li><br/>    <?php<br/>}<br/> <br/>echo _close('ul');<br/> <br/>echo _close('div');<br/> <br/>use_javascript('/js/smartcolumns.js'); <br/>


И пример экшена для автозаполнения формы поиска:
<?php
 
/**
 * Отель actions
 */

class hotelActions extends myFrontModuleActions
{
 
    public function executeAutocomplete(dmWebRequest $request)
    {
        $query = $request->getParameter('query', 0);
        if ($query)
        {
            $limit = 10;
            $q = RequestFilter::sanitizeString($query);
 
            $query = Doctrine_Query::create()
                ->select('h.id, h.name')
                ->from('Hotel h')
                ->where("LOWER( name ) REGEXP '^{$q}.*|[^ -][ -]{$q}[^)]*$' ")
                ->orderBy('h.rating DESC, h.name ASC')
                ->limit($limit);
 
            $res = $query->execute();
 
            if (count($res))
            {
                $json = array(
                    'suggestions' => array(),
                    'data' => array(),
                );
 
                foreach ($res as $key => $val)
                {
                    $json['suggestions'][] = $val->name;
                    $json['data'][] = $val->id;
                }
 
                $this->getResponse()->setContentType('application/json');
                return $this->renderText(json_encode($json));
            }
        }
 
        return sfView::NONE;
    }
 
}


На верстку и экшены для всего описанного функционала ушло около двух часов.

Подводные камни


В двух словах укажу какие трудности вас могут поджидать при разработке (система все-таки сырая и опенсорсная)

1. Рускоязычные файлы при загрузке не переименовываются, при генерации url-конечно идет преобразование в url-допустимые символы, но у меня возникли проблемы с тем, что некоторые файлы после загрузки просто исчезали. Точнее в файловой системе и в БД они оставались, но Diem их не видела. Думаю причина здесь может быть в использовании устаревших функций вместо mb_string_functions. Хотя французы должны были сталкиваться с UTF-8 строки… Вобщем копаться особо не стал, лечиться преобразованием имени файла к допустимым для url символам, например a-z0-9_-

2. Потребление памяти при каждом обращении к медиа-галерее увеличивается с ростом файлов, что не допустимо для крупных проектов. Для базы отелей с 500Мб изображений медиатека отказывалась открываться.
Углубившись в код я нашел вызов синхронизации при каждом обращении к объекту медиатеки, делается это для того чтобы информация о структуре папок и файлов хранилища в БД была актуальна (вдруг мы загрузим по фтп файлик).
Вещь ресурсоемкая и не очень нужная, т.к. файлы предполагается загружать только через интерфейс админки, закомментарим строчку вызова синхронизации и успокоимся.

3. Diem минифицирует и объединяет все CSS и JavaScript файлы для ускорения рендерига страниц. Причем javascript включается в конце страницы, как нас учили задроты специалисты из Yahoo. Если вы хотите использовать в шаблонах javascript и использоваться скажем jQuery, то необходимо чтобы jquery библиотека была подключена в заголовке страницы. Для этого в config/dm/config.yml нужно указать какие javascript файлы следует включить в заголовке. Там же можно указать использование Google CDN для загрузки jquery — библиотек.

Итоги


1. Теперь вы знаете, что такое Diem CMS, какие преимущества в разработке вы получаете, используя данную CMS и как отличается парадигма управления контентом от других CMS.
2. Знаете, что использовать Diem можно на VPS или выделенных серверах, а на виртуальных хостингах лучше не пробовать. (Хотя, эксперимента ради, думаю всем будет интересно узнать сколько миллисекунд занимает генерация страницы на вашем хостинге)
3. Вы познакомились с примером разработки собственного модуля и, надеюсь, убедились, что с Diem делать это набитой рукой можно легко и быстро.
4. Вы узнали какие трудности могут возникнуть и как их преодолевать.

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

P.S.: кто заметит ошибку, не сможет промолчать и напишет в личку — буду благодарен и сразу же исправлю.
Tags:
Hubs:
Total votes 43: ↑29 and ↓14+15
Comments32

Articles