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

Если пробежаться глазами по сайтам, созданным с ее помощью несложно заметить, что большинство из них наследует две колонки стандартных шаблонов.
Но ведь 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>


Небольшое замечание. div.leftside будет содержать стандартные блоки групы right системы, которые выводятся в обоих стандартных шаблонах файлом sidebar.tpl.
В div.header и div.sub-content мы добавим созданные нами и размещенные в группы upper и center соответственно.


Класс блока

Начнем с того, что создадим классы для наших блоков, которые должны наследовать системный класс 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}


Вот собственно и все!
Если у Вас есть какие-то дополнения или замечания — оставляйте в комментариях или отправляйте ЛС. Буду очень рад вместе с Вами развить статью до полноценного гайда по блокам.

ЗЫ По Вашему совету топик-ссылку спрятал и разместил полный текст в этом блоге.

15 комментариев

avatar
Спасибо за информацию. Добавил в избранное
avatar
Интересно и познавательно, спасибо!
Я пытался играть с блоками в шаблоне с помощью хуков, теперь попробую этот метод.
avatar
надо испытать на шаблоне! спасибо!
  • jofe
  • 0
avatar
как исключить вывод блока при определенном эвенте определенного экшена?
avatar
Нашел решение. Если не хотим, например, выводить блок только при редактировании блога, то вписываем:

'path' => array( 
        $config['path']['root']['web'].'/blog/(?!edit)',
),

при условии, что в массиве ключа 'action' нет элемента 'blog'.
avatar
Либо в массиве 'action' перечислить action'ы в которых надо выводить блок.
avatar
Event'ы тоесть, а не action'ы
avatar
Если элемент задан регуляркой, можно его как-то указать?
avatar
Не совсем понял.
А Ваш способ, вышеприведенный не подходит?
avatar
Все подходит, это я о невозможности указать список эвентов, если они заданы регулярным выражением. Так все работает без проблем
avatar
хотелось бы боллее навичковский вариант. например для тех кто плохо знает php
avatar
я как понимаю пишем в
'action'  => array( ),
где хотим видеть данный блок
'index', 'new', /* ... где еще показывать ...*/
только вот вопрос, как запретить показ в профиле, в поиску...?
спасибо.
avatar
я прописывал даже где хочу только видеть данный блок
'action'  => array('people', 'blog' => array('add','edit')),
но показывает на всех страницах.


//Сам блок
$config['block']['rule_index_blog'] = array(
        'path' => array(),
		'action'  => array('people', 'blog' => array('add','edit')),
        
        'blocks'  => array('right' => array('block.advert.tpl'=>array('priority'=>150))),
        'clear' => false,
);
avatar
должно работать

'path' => array()
можно не писать
avatar
а скажите как регулировать вывод плагина «Категории»? что откуда брать?
спасибо
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.