Система блоков в CMS LiveStreet


LiveStreet — замечательная и любимая на хабре система. Однако если пробежаться глазами по сайтам, созданным с ее помощью несложно заметить, что большинство из них наследует две колонки стандартных шаблонов.
Но ведь LS может похвастаться простой, но от этого не менее функциональной системой блоков. Почему владельцы сайтов не используют ее? Возможно, дело в отсутствующей документации.
Это я сегодня с Вашей помощью и попробую исправить.


Начнем



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


и так:
    <div class="container">
        <div class="header">
        </div>
        <div class="content">
            <div class="leftside">
            </div>
            <div class="maincontent"></div>
        </div>
        <div class="sub-content">
        </div>
        <div class="footer"></div>
    </div>


Класс блока

Начнем с того, что создадим классы для наших блоков, которые должны наследовать системный класс Block и реализовывать метод Exec().
Заглянув в класс Block Вы увидите, что он только принимает параметры блока через свой конструктор и записывает их в свойство $aParams, а так же дает нам возможность вызывать методы модулей через свою обертку __call();

Здесь я приведу код для одного из центральных блоков. Пусть он будет выводить Ваши последние топики.

<?php
 
BlockLast extends Block
{
    public function Exec()
    {
        $oUser   = $this->User_GetUserCurrent();
        if($oUser) {
                $aTopics = $this->Topics_GetLastTopicsByUserId($oUser->getId()60*60*24);
                //Для того, чтобы не допустить конфликта создаем локальный объект представления
                $oViewer = $this->Viewer_GetLocalViewer();
                $sTopicsLast  = $oViewer->Fetch('block.topics_last.tpl');
                //Передаем данные уже в глобальный объект вида 
                $this->Viewer_Assign('sTopicsLast', $sTopicsLast);
        }
    }
}


Конфигурация

Моя любимая часть. С помощью стандартного конфига LiveStreet мы сможем максимально гибко настроить вывод наших блоков. Приведу пример:

   //Блок созданный нами в предыдущем пункте
    $config['block']['rule_topic'] = array(
            'path' => array(
                '___path.root.web___/blog/*$',
            ),
            'action'  => array(
                'index' => array('blog'),
                'new'
            ),
            'blocks'  => array(
                'central' =>  array(
                    'last'=>array('priority'=>100'params' => array())
                )            
            ),
            'clear' => false,
    );
 
    //Еще один блок, который мы опишем позже
    $config['block']['rule_user'] = array(
        'path' => array(
            '___path.root.web___/profile/*$',
            '___path.root.web___/settings/*$'
        ),
        'action' => array(),
        'blocks' => array(
            'upper' => array(
            'block.user.tpl'
            )        
        )
    );


Как видите конфигурация блоков — довольно тривиальное занятие. Названия параметров говорят сами за себя, поэтому долго разбираться в них не придется.

  • path — ключ содержит массив шаблонов. При соответствии текущего адреса страницы шаблону — блок выводится.
    Несколько заметок:
    1. Правила, описанные в path проверяются только в случае, если ключ action конфигурации не передан, или в нем не нашлось текущего Action'a.
    2. Символ "*" при подготовке шаблона заменяется на "[\w\-]+". Символ прямого слеша "/" экранируется.
      На что заменяется "___path.root.web___" я думаю Вы догадались. Больше никаких действий с шаблоном до проверки не производится.

  • action — список Action'ов, при выполнении которых блок будет добавляться.
    На примере первого блока так же видно, что элементы массива могут сами являться массивом, уточняющим, к каким именно Event'ам выбранного Action'a применимо правило.
    Замечу, что в случае, если Вы не передадите ключ action в массиве конфигурации, то PHP выдаст пару Notice.
    Поэтому если все поведение блока Вы определили с помощью ключа path, то можете просто передать пустой массив.

  • blocks — определяет блоки для вывода.
    Хочу обратить Ваше внимание на то, что передать в массиве blocks можно не только имя класса блока, но и шаблон блока *.tpl. Что полезно. если Вам просто нужно разместить несколько строк текста (в приведенной выше конфигурации мы определяем, что наш блок last принадлежит к группе блоков central, а группа upper будет содержать блок заданный файлом шаблона block.user.tpl).
    Дополнительно можно задать приоритет вывода блока и параметры вызова(именно эти параметры будут переданны в конструктор блока и записаны в свойство $aParams).
  • clear — при установке ключа в true все уже добавленные в текущую группу (в нашем случае central) блоки будут оттуда удалены.


Шаблон

Самый простой шаг. Система автоматически будет искать шаблон для нашего блока по адресу _путь_до_шаблона_/block._имя_блока_.tpl

Для блока topics в шаблон мы передали переменную $sTopicsLast. Просто выведем ее в нем

<div class="block last-topics">
    <div class="topics">
        {$sTopicsLast}
    </div>
</div>


Для второго блока, определенного в конфигурации тоже создадим простенький шаблон в файле block.user.tpl

<div class="hello-user">
   Привет, {$oUserCurrent->getLogin()} 
</div>


Остается только добавить в шаблон, который я приводил в начале статьи, вывод наших блоков. И опять пример с созданным нами блоком

        <div class="container">
            <div class="header">
               <div class="upper">
                   {include file blocks.tpl sGroup = 'upper'}
               </div>
            </div>
            <div class="content">
                <div class="leftside">
                    {include file sidebar.tpl}
                </div>
                <div class="maincontent"></div>
            </div>
            <div class="sub-content">
                {include file blocks.tpl sGroup = 'central'}
            </div>
            <div class="footer"></div>
        </div>


И наконец файл blocks.tpl

{if isset($aBlocks.$sGroup)}
    {foreach from=$aBlocks.$sGroup item=aBlock}
        {if $aBlock.type=='block'}
            {insert name="block" block=$aBlock.name params=$aBlock.params}
        {/if}
        {if $aBlock.type=='template'}
             {include file=$aBlock.name params=$aBlock.params}
        {/if}
     {/foreach}
{/if}


На этом все! Как видите схема одновременно простая и гибкая.

Спасибо за внимание!
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 7

    +1
    Большое спасибо, очень в тему помогло.
      0
      Отдельно бы отметил, что использовать блоки стоит для разных вспомогательных информационных единиц (баннеры, всякая информация идущая слева и справа от контента) и не использовать для создания сайта в целом.
      • НЛО прилетело и опубликовало эту надпись здесь
          +2
          Я сам сторонник ZF Coding Standart и не использую Венгерскую нотацию, но когда я пишу на\под LiveStreet я использую его «стандарты» кодирования.
          Во-первых, потому что мне их подсказвыает IDE.
          А во-вторых, потому что разноперые стили в одном проекте это еще хуже.
          0
          Вот как раз с блокамии-то больше всего проблем возникает, судя по тема на форуме и «наследованию» блоков из стандартных шаблонов, что говорит совсем не о простоте работы с ними…
            0
            Зря, недооценивают блоки. А проблемы не с блоками, а с восприятием. Все привыкли к модульной системе, от того и все проблемы. Гибче надо мыслить, архитектурно.
              0
              ИМХО, если LS-блоки назвать немного иначе — виджет — т.е. так, как эту сущность обычно кличут, то тогда все встанет на свои места в восприятии

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое