Шаблон для главной страницы: различия между версиями

Материал из Wiki from ADT Web Solutions
Перейти к навигации Перейти к поиску
 
(не показаны 22 промежуточные версии этого же участника)
Строка 1: Строка 1:
 
Как правило, стартовая страница сайта отличается от остальных. Как отразить эту особенность в нашем шаблоне?
 
Как правило, стартовая страница сайта отличается от остальных. Как отразить эту особенность в нашем шаблоне?
  
Вообще-то очень просто. В объекте $variables['page'] есть свойство 'is_default', которое мы можем проверить. И если оно true, то подтягиваем шаблон главной. Если нет - страницы нужного модуля. Вставим эту проверку в файл main.phtml:
+
Вообще-то очень просто. В массиве $variables есть элемент 'is-default', который мы можем проверить. И если он true, то подтягиваем шаблон главной. Если нет - страницы нужного модуля. Вставим эту проверку в файл main.phtml:
  
<syntaxhighlight lang="php" line='line'>
+
<syntaxhighlight lang="php">
 
     <main>
 
     <main>
 
<?php
 
<?php
if ($variables['page']->is_default) echo $this->render($variables, "content/home/index");
+
if ($variables['is-default']) echo $this->render($variables, "content/home/index");
 
else echo $this->render($variables, "{$variables['module']}/{$variables['method']}");
 
else echo $this->render($variables, "{$variables['module']}/{$variables['method']}");
 
?>
 
?>
 
     </main>
 
     </main>
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
В объекте $variables['page'] тоже есть такое свойство, но получить его невозможно. Оно, конечно, private. Всегда будет false.
  
 
И надо создать в папке php фрагмент шаблона content/home/index.phtml, который подключаем. Для начала пусть будет просто контентная страница:
 
И надо создать в папке php фрагмент шаблона content/home/index.phtml, который подключаем. Для начала пусть будет просто контентная страница:
  
<syntaxhighlight lang="php" line='line'>
+
<syntaxhighlight lang="php">
 +
<?php
 +
$page = $variables['page'];
 +
?>
 +
        <section>
 +
            <div class="container">
 +
                <div class="row">
 +
                    <div class="col-12">
 +
                        <h1 umi:element-id="<?= $page->id ?>" umi:field-name="h1" umi:empty="<?= $this->translate('empty_page_name') ?>"><?= $page->h1 ?></h1>
 +
                    </div>
 +
                    <div class="col-12">
 +
                        <div umi:element-id="<?= $page->id ?>" umi:field-name="content" umi:empty="<?= $this->translate('empty_page_content') ?>"><?= $page->content ?></div>
 +
                    </div>
 +
                </div>
 +
            </div>
 +
        </section>
 +
</syntaxhighlight>
 +
 
 +
== Добавление блоков ==
 +
 
 +
Обычно на главную страницу стараются запихнуть весь контент сайта. Наверно потому, что не надеются, что пользователь настолько заинтересуется, что пройдет куда-то ещё.
 +
 
 +
Продолжим эту скверную традицию. У нас есть контент главной страницы, где можно разместить информацию о компании или продукте, и новости. Явно не хватает контактов, которые лучше добавить в настройки:
 +
 
 +
[[Файл:Screenshot 5 UMI CMS - Редактирование типа данных.png|обрамить|без]]
 +
 
 +
Чтобы к этому не возвращаться, добавим все поля, которые хотели, в частности, ссылки на дерево для новостей и 404 ошибки, а также название компании. Новости уже есть, осталось в настройках выбрать нужный раздел, а вот 404 страницы нет, [[404 страница|создадим её]].
 +
 
 +
Вообще хорошим тоном является не портить шаблон данных "Настройки", а создать дочерний шаблон, куда и внести все нужные поля. Это без сомнения пригодится, если на одной системе делать несколько сайтов с разным набором настроек.
 +
 
 +
=== Разбиваем шаблон на блоки ===
 +
 
 +
Чтобы не тащить простыню кода, разделим content/home/index.phtml на фрагменты по блокам:
 +
 
 +
<syntaxhighlight lang="php">
 +
<?php
 +
echo $this->render($variables, "content/home/intro");
 +
echo $this->render($variables, "content/home/news");
 +
echo $this->render($variables, "content/home/contacts");
 +
?>
 +
</syntaxhighlight>
 +
 
 +
=== Вводный текст ===
 +
 
 +
Фрагмент content/home/intro.phtml останется аналогом контентной страницы:
 +
 
 +
<syntaxhighlight lang="php">
 
<?php
 
<?php
 
$page = $variables['page'];
 
$page = $variables['page'];
Строка 31: Строка 79:
 
         </section>
 
         </section>
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
=== Новости ===
 +
 +
Фрагмент для новостей content/home/news.phtml:
 +
 +
<syntaxhighlight lang="php">
 +
<?php
 +
$newsListSettings = $variables['settings']->newslist;
 +
if (!empty($newsListSettings)) $newsPageId = $newsListSettings[0]->id;
 +
else $newsPageId = false;
 +
$newsList = $this->macros('news', 'lastlist', [$newsPageId]);
 +
?>
 +
        <section>
 +
            <div class="container">
 +
                <div class="row">
 +
                    <div class="col-12">
 +
                        <h2>Что нового?</h2>
 +
                    </div>
 +
                    <div class="col-12">
 +
                        <ul class="list-group">
 +
<?php
 +
if (!empty($newsList['items'])):
 +
    foreach ($newsList['items'] as $item):
 +
?>
 +
                            <li class="list-group-item">
 +
                                <em><?= date("d.m.Y", $item['publish_time']) ?></em>
 +
                                <a href="<?= $item['link'] ?>"><h3 umi:element-id="<?= $item['id'] ?>" umi:field-name="name" umi:empty="<?= $this->translate('empty_page_name') ?>"><?= $item['name'] ?></h3></a>
 +
                            </li>
 +
<?php
 +
    endforeach;
 +
endif;
 +
?>
 +
                        </ul>
 +
                    </div>
 +
                </div>
 +
            </div>
 +
        </section>
 +
</syntaxhighlight>
 +
 +
=== Контакты ===
 +
 +
Фрагмент для контактов content/home/contacts.phtml:
 +
 +
<syntaxhighlight lang="php">
 +
        <section>
 +
            <div class="container">
 +
                <div class="row">
 +
                    <div class="col-12">
 +
                        <h2>Контакты</h2>
 +
                    </div>
 +
                    <div class="col-12">
 +
                        <div class="row">
 +
                            <div class="col-6">
 +
                                <h3><?= $this->translate('address') ?></h3>
 +
                            </div>
 +
                            <div class="col-6">
 +
                                <h3 umi:object-id="<?= $variables['settings']->id ?>" umi:field-name="address" umi:empty="<?= $this->translate('empty_address') ?>"><?= $variables['settings']->address ?></h3>
 +
                            </div>
 +
                        </div>
 +
                        <div class="row">
 +
                            <div class="col-6">
 +
                                <h3><?= $this->translate('phone') ?></h3>
 +
                            </div>
 +
                            <div class="col-6">
 +
                                <h3 umi:object-id="<?= $variables['settings']->id ?>" umi:field-name="phone" umi:empty="<?= $this->translate('empty_phone') ?>"><?= $variables['settings']->phone ?></h3>
 +
                            </div>
 +
                        </div>
 +
                    </div>
 +
                </div>
 +
            </div>
 +
        </section>
 +
</syntaxhighlight>
 +
 +
Не забываем пополнять файлы i18n/i18n.ru.php и i18n/i18n.en.php новыми языковыми константами, которые появляются в шаблонах нашего сайта. Также добавили разметку для Edit-in-place, и теперь можем внести адрес и телефон прямо на "морде" сайта.
 +
 +
== Организация блоков на главной странице ==
 +
 +
Хотелось бы дать возможность редактору сайта регулировать контент на главной странице, добавлять и убирать блоки, и чтобы все изменения появлялись на сайте автоматически.
 +
 +
Кто-то из новых разработчиков задал аналогичный вопрос в группе, получил много ответов, которые его не устроили по причине сложной реализации. Что он сделал после этого? У него была верстка, вся такая из разноцветных блоков. Он в "Шаблонах данных" добавил дочерний шаблон в "Раздел сайта", назвал его "Главная", и добавил туда кучу полей типа HTML-текст с кодом section1, section2 и т.д. После чего скопировал код соответствующих блоков из верстки, и вставил в эти поля. Шаблон главной у него при этом получился, видимо, такой:
 +
 +
<syntaxhighlight lang="php">
 +
<?php
 +
$page = $variables['page'];
 +
?>
 +
<?= ($page->section1)?$page->section1:'' ?>
 +
<?= ($page->section2)?$page->section2:'' ?>
 +
...
 +
</syntaxhighlight>
 +
 +
А что, так можно было??? Конечно, можно. Но некрасиво, и нельзя поменять блоки местами.
 +
 +
Мне больше нравится другой способ. Создаём в разделе главной страницы несколько подразделов, например, вот так:
 +
 +
[[Файл:Screenshot 22 UMI CMS - Структура сайта.png|обрамить|без]]
 +
 +
Псевдостатические адреса задаём intro, news и contacts соответственно. После чего шаблон главной страницы приобретает вид:
 +
 +
<syntaxhighlight lang="php">
 +
<?php
 +
/**
 +
* Главная страница:
 +
*  - Блок с вступительным текстом
 +
*  - Блок "Новости"
 +
*  - Блок "Контакты"
 +
* Для удаления блока достаточно снять
 +
* у соответствующего раздела признак "Отображать в меню"
 +
* Для добавления блока надо добавить блок в структуру
 +
* раздела и создать в папке content/home файл шаблона
 +
* с именем как в поле "Псевдостатический адрес"
 +
*
 +
*/
 +
$blocks = [];
 +
$hierarchy = umiHierarchy::getInstance();
 +
$children = $hierarchy->getChildrenTree($variables['pageId'], false, false, 1);
 +
foreach ($children as $id => $val) {
 +
    $element = $hierarchy->getElement($id);
 +
    if ($element instanceof umiHierarchyElement) {
 +
        $blocks[$id]['id'] = $element->id;
 +
        $blocks[$id]['name'] = $element->name;
 +
        $blocks[$id]['h1'] = $element->h1;
 +
        $blocks[$id]['altName'] = $element->altName;
 +
        $blocks[$id]['content'] = $element->content;
 +
    }
 +
}
 +
$resourcesDir = cmsController::getInstance()->getResourcesDirectory();
 +
 +
foreach ($blocks as $page) {
 +
    $page['settings'] = $variables['settings'];
 +
    if (isset($page['altName'])) {
 +
        if ($resourcesDir && file_exists($resourcesDir . 'php/content/home/' . $page['altName'] . '.phtml')) echo $this->render($page, 'content/home/' . $page['altName']);
 +
        else echo '<div class="alert alert-danger">Отсутствует шаблон: ', $resourcesDir, 'content/home/', $page['altName'], '.phtml</div>';
 +
    }
 +
}
 +
?>
 +
</syntaxhighlight>
 +
 +
Кода получилось немного больше, но в следующей статье исправим этот недостаток. Подключили класс umiHierarchy, выбрали все дочерние страницы, выбрали соответствующие объекты и наполнили массив $blocks. Да, еще добыли путь к корневой папке нашего шаблона, чтобы не задавать статикой. В качестве данных передаём в render() массив $page, куда добавили $variables['settings'], чтобы не потерять настройки. Вообще это лучше делать по-другому, но об этом чуть позже.
 +
 +
Теперь надо поменять немного шаблоны блоков, чтобы брать оттуда контент соответствующих подразделов.
 +
 +
=== Вступительный текст ===
 +
 +
В метод render() мы уже передаем не $variables, а элемент массива, содержащий данные подраздела. Здесь название массива по-прежнему будет $variables, но содержимое будет уже другим. Поэтому:
 +
 +
<syntaxhighlight lang="php">
 +
        <section>
 +
            <div class="container">
 +
                <div class="row">
 +
                    <div class="col-12">
 +
                        <h1 umi:element-id="<?= $variables['id'] ?>" umi:field-name="h1" umi:empty="<?= $this->translate('empty_page_name') ?>"><?= $variables['h1'] ?></h1>
 +
                    </div>
 +
                    <div class="col-12">
 +
                        <div umi:element-id="<?= $variables['id'] ?>" umi:field-name="content" umi:empty="<?= $this->translate('empty_page_content') ?>"><?= $variables['content'] ?></div>
 +
                    </div>
 +
                </div>
 +
            </div>
 +
        </section>
 +
</syntaxhighlight>
 +
 +
=== Остальные шаблоны ===
 +
 +
Все, что нам нужно из остальных подразделов - это заголовки, которые специально до этого были оставлены в виде слов. Поэтому меняем только одну строку:
 +
 +
<syntaxhighlight lang="php">
 +
                        <h2 umi:element-id="<?= $variables['id'] ?>" umi:field-name="h1" umi:empty="<?= $this->translate('empty_page_name') ?>"><?= $variables['h1'] ?></h2>
 +
</syntaxhighlight>
 +
 +
=== В чем преимущество? ===
 +
 +
Редактор сайта получает больше возможностей для изменения контента главной, можно использовать Edit-in-place для исправления заголовков блоков, можно менять блоки местами. Попробуйте и убедитесь.
 +
 +
Вообще я обычно использую 2 уровня вложенности подразделов, чтобы внутри каждого из блоков отображать список дочерних блоков. Это очень удобно для программирования современных сайтов, где есть блоки "Наши преимущества", "Наша команда" и "Отзывы наших клиентов", содержащие свои списки данных. Понятно, что кроме заголовка и контента можно добавлять картинки, пиктограммы, анонсы - всё, что только может понадобиться.
 +
 +
Но есть и недостаток - много кода в шаблоне. Хорошим тоном в UMI считается, если в шаблоне вообще не используется API. Это правильно и с точки зрения MVC. Поэтому пора перейти к [[Расширение функциональности модулей|созданию кастомных методов и функций]].

Текущая версия на 18:25, 5 ноября 2020

Как правило, стартовая страница сайта отличается от остальных. Как отразить эту особенность в нашем шаблоне?

Вообще-то очень просто. В массиве $variables есть элемент 'is-default', который мы можем проверить. И если он true, то подтягиваем шаблон главной. Если нет - страницы нужного модуля. Вставим эту проверку в файл main.phtml:

    <main>
<?php
if ($variables['is-default']) echo $this->render($variables, "content/home/index");
else echo $this->render($variables, "{$variables['module']}/{$variables['method']}");
?>
    </main>

В объекте $variables['page'] тоже есть такое свойство, но получить его невозможно. Оно, конечно, private. Всегда будет false.

И надо создать в папке php фрагмент шаблона content/home/index.phtml, который подключаем. Для начала пусть будет просто контентная страница:

<?php
$page = $variables['page'];
?>
        <section>
            <div class="container">
                <div class="row">
                    <div class="col-12">
                        <h1 umi:element-id="<?= $page->id ?>" umi:field-name="h1" umi:empty="<?= $this->translate('empty_page_name') ?>"><?= $page->h1 ?></h1>
                    </div>
                    <div class="col-12">
                        <div umi:element-id="<?= $page->id ?>" umi:field-name="content" umi:empty="<?= $this->translate('empty_page_content') ?>"><?= $page->content ?></div>
                    </div>
                </div>
            </div>
        </section>

Добавление блоков

Обычно на главную страницу стараются запихнуть весь контент сайта. Наверно потому, что не надеются, что пользователь настолько заинтересуется, что пройдет куда-то ещё.

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

Screenshot 5 UMI CMS - Редактирование типа данных.png

Чтобы к этому не возвращаться, добавим все поля, которые хотели, в частности, ссылки на дерево для новостей и 404 ошибки, а также название компании. Новости уже есть, осталось в настройках выбрать нужный раздел, а вот 404 страницы нет, создадим её.

Вообще хорошим тоном является не портить шаблон данных "Настройки", а создать дочерний шаблон, куда и внести все нужные поля. Это без сомнения пригодится, если на одной системе делать несколько сайтов с разным набором настроек.

Разбиваем шаблон на блоки

Чтобы не тащить простыню кода, разделим content/home/index.phtml на фрагменты по блокам:

<?php
echo $this->render($variables, "content/home/intro");
echo $this->render($variables, "content/home/news");
echo $this->render($variables, "content/home/contacts");
?>

Вводный текст

Фрагмент content/home/intro.phtml останется аналогом контентной страницы:

<?php
$page = $variables['page'];
?>
        <section>
            <div class="container">
                <div class="row">
                    <div class="col-12">
                        <h1 umi:element-id="<?= $page->id ?>" umi:field-name="h1" umi:empty="<?= $this->translate('empty_page_name') ?>"><?= $page->h1 ?></h1>
                    </div>
                    <div class="col-12">
                        <div umi:element-id="<?= $page->id ?>" umi:field-name="content" umi:empty="<?= $this->translate('empty_page_content') ?>"><?= $page->content ?></div>
                    </div>
                </div>
            </div>
        </section>

Новости

Фрагмент для новостей content/home/news.phtml:

<?php
$newsListSettings = $variables['settings']->newslist;
if (!empty($newsListSettings)) $newsPageId = $newsListSettings[0]->id;
else $newsPageId = false;
$newsList = $this->macros('news', 'lastlist', [$newsPageId]);
?>
        <section>
            <div class="container">
                <div class="row">
                    <div class="col-12">
                        <h2>Что нового?</h2>
                    </div>
                    <div class="col-12">
                        <ul class="list-group">
<?php
if (!empty($newsList['items'])):
    foreach ($newsList['items'] as $item):
?>
                            <li class="list-group-item">
                                <em><?= date("d.m.Y", $item['publish_time']) ?></em>
                                <a href="<?= $item['link'] ?>"><h3 umi:element-id="<?= $item['id'] ?>" umi:field-name="name" umi:empty="<?= $this->translate('empty_page_name') ?>"><?= $item['name'] ?></h3></a>
                            </li>
<?php
    endforeach;
endif;
?>
                        </ul>
                    </div>
                </div>
            </div>
        </section>

Контакты

Фрагмент для контактов content/home/contacts.phtml:

        <section>
            <div class="container">
                <div class="row">
                    <div class="col-12">
                        <h2>Контакты</h2>
                    </div>
                    <div class="col-12">
                        <div class="row">
                            <div class="col-6">
                                <h3><?= $this->translate('address') ?></h3>
                            </div>
                            <div class="col-6">
                                <h3 umi:object-id="<?= $variables['settings']->id ?>" umi:field-name="address" umi:empty="<?= $this->translate('empty_address') ?>"><?= $variables['settings']->address ?></h3>
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-6">
                                <h3><?= $this->translate('phone') ?></h3>
                            </div>
                            <div class="col-6">
                                <h3 umi:object-id="<?= $variables['settings']->id ?>" umi:field-name="phone" umi:empty="<?= $this->translate('empty_phone') ?>"><?= $variables['settings']->phone ?></h3>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </section>

Не забываем пополнять файлы i18n/i18n.ru.php и i18n/i18n.en.php новыми языковыми константами, которые появляются в шаблонах нашего сайта. Также добавили разметку для Edit-in-place, и теперь можем внести адрес и телефон прямо на "морде" сайта.

Организация блоков на главной странице

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

Кто-то из новых разработчиков задал аналогичный вопрос в группе, получил много ответов, которые его не устроили по причине сложной реализации. Что он сделал после этого? У него была верстка, вся такая из разноцветных блоков. Он в "Шаблонах данных" добавил дочерний шаблон в "Раздел сайта", назвал его "Главная", и добавил туда кучу полей типа HTML-текст с кодом section1, section2 и т.д. После чего скопировал код соответствующих блоков из верстки, и вставил в эти поля. Шаблон главной у него при этом получился, видимо, такой:

<?php
$page = $variables['page'];
?>
<?= ($page->section1)?$page->section1:'' ?>
<?= ($page->section2)?$page->section2:'' ?>
...

А что, так можно было??? Конечно, можно. Но некрасиво, и нельзя поменять блоки местами.

Мне больше нравится другой способ. Создаём в разделе главной страницы несколько подразделов, например, вот так:

Screenshot 22 UMI CMS - Структура сайта.png

Псевдостатические адреса задаём intro, news и contacts соответственно. После чего шаблон главной страницы приобретает вид:

<?php
/**
 * Главная страница:
 *   - Блок с вступительным текстом
 *   - Блок "Новости"
 *   - Блок "Контакты"
 * Для удаления блока достаточно снять
 * у соответствующего раздела признак "Отображать в меню"
 * Для добавления блока надо добавить блок в структуру
 * раздела и создать в папке content/home файл шаблона
 * с именем как в поле "Псевдостатический адрес"
 *
 */
$blocks = [];
$hierarchy = umiHierarchy::getInstance(); 
$children = $hierarchy->getChildrenTree($variables['pageId'], false, false, 1);
foreach ($children as $id => $val) {
    $element = $hierarchy->getElement($id);
    if ($element instanceof umiHierarchyElement) {
        $blocks[$id]['id'] = $element->id;
        $blocks[$id]['name'] = $element->name;
        $blocks[$id]['h1'] = $element->h1;
        $blocks[$id]['altName'] = $element->altName;
        $blocks[$id]['content'] = $element->content;
    }
}
$resourcesDir = cmsController::getInstance()->getResourcesDirectory();

foreach ($blocks as $page) {
    $page['settings'] = $variables['settings'];
    if (isset($page['altName'])) {
        if ($resourcesDir && file_exists($resourcesDir . 'php/content/home/' . $page['altName'] . '.phtml')) echo $this->render($page, 'content/home/' . $page['altName']);
        else echo '<div class="alert alert-danger">Отсутствует шаблон: ', $resourcesDir, 'content/home/', $page['altName'], '.phtml</div>';
    }
}
?>

Кода получилось немного больше, но в следующей статье исправим этот недостаток. Подключили класс umiHierarchy, выбрали все дочерние страницы, выбрали соответствующие объекты и наполнили массив $blocks. Да, еще добыли путь к корневой папке нашего шаблона, чтобы не задавать статикой. В качестве данных передаём в render() массив $page, куда добавили $variables['settings'], чтобы не потерять настройки. Вообще это лучше делать по-другому, но об этом чуть позже.

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

Вступительный текст

В метод render() мы уже передаем не $variables, а элемент массива, содержащий данные подраздела. Здесь название массива по-прежнему будет $variables, но содержимое будет уже другим. Поэтому:

        <section>
            <div class="container">
                <div class="row">
                    <div class="col-12">
                        <h1 umi:element-id="<?= $variables['id'] ?>" umi:field-name="h1" umi:empty="<?= $this->translate('empty_page_name') ?>"><?= $variables['h1'] ?></h1>
                    </div>
                    <div class="col-12">
                        <div umi:element-id="<?= $variables['id'] ?>" umi:field-name="content" umi:empty="<?= $this->translate('empty_page_content') ?>"><?= $variables['content'] ?></div>
                    </div>
                </div>
            </div>
        </section>

Остальные шаблоны

Все, что нам нужно из остальных подразделов - это заголовки, которые специально до этого были оставлены в виде слов. Поэтому меняем только одну строку:

                        <h2 umi:element-id="<?= $variables['id'] ?>" umi:field-name="h1" umi:empty="<?= $this->translate('empty_page_name') ?>"><?= $variables['h1'] ?></h2>

В чем преимущество?

Редактор сайта получает больше возможностей для изменения контента главной, можно использовать Edit-in-place для исправления заголовков блоков, можно менять блоки местами. Попробуйте и убедитесь.

Вообще я обычно использую 2 уровня вложенности подразделов, чтобы внутри каждого из блоков отображать список дочерних блоков. Это очень удобно для программирования современных сайтов, где есть блоки "Наши преимущества", "Наша команда" и "Отзывы наших клиентов", содержащие свои списки данных. Понятно, что кроме заголовка и контента можно добавлять картинки, пиктограммы, анонсы - всё, что только может понадобиться.

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