Создание "правильного" шаблона для сайта: различия между версиями

Материал из Wiki from ADT Web Solutions
Перейти к навигации Перейти к поиску
Строка 1: Строка 1:
 
Для компактности HTML кода буду использовать библиотеку Bootstrap4 - пользуйтесь своими любимыми фреймворками, если не нравится. Итак, сделаем код нашего шаблона несколько более полным:
 
Для компактности HTML кода буду использовать библиотеку Bootstrap4 - пользуйтесь своими любимыми фреймворками, если не нравится. Итак, сделаем код нашего шаблона несколько более полным:
  
<syntaxhighlight lang="html">
+
<syntaxhighlight lang="php">
 
<?php
 
<?php
 
$page = $variables['page'];
 
$page = $variables['page'];

Версия 22:58, 5 ноября 2020

Для компактности HTML кода буду использовать библиотеку Bootstrap4 - пользуйтесь своими любимыми фреймворками, если не нравится. Итак, сделаем код нашего шаблона несколько более полным:

<?php
$page = $variables['page'];
?>
<!DOCTYPE html>
<html>
<head>
    <base href="/templates/default/">
    <title><?= $page->title ?></title>
    <meta charset="utf-8">
    <meta name="description" content="<?= $page->description ?>">
    <meta name="keywords" content="<?= $page->keywords ?>">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
    <header>
    </header>
    <main>
        <section>
            <div class="container">
                <div class="row">
                    <div class="col-12">
                        <h1><?= $page->h1 ?></h1>
                    </div>
                    <div class="col-12">
                        <p><?= $page->content ?></p>
                    </div>
                </div>
            </div>
        </section>
    </main>
    <footer>
    </footer>

    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>
</html>

В <head> добавили тэг <base ...>, потому что в дальнейшем все, что касается конкретного сайта, планируем хранить в папке конкретного шаблона, в нашем случае default. UMI CMS считает папку шаблона корневой директорией сайта, но это не распространяется на стили, скрипты и картинки.

Теперь главная страница сайта приобрела более "причёсанный" вид:

Screenshot 2020-10-29 Главная.png

Заметим, что Title у страницы пустой, что не слишком хорошо. Можно прописывать это поле для каждой страницы. Но есть способ получше.

Настраиваем Title и другие SEO-параметры

В шаблоне меняем строки заголовка, описания и ключевых слов на:

    <title><?= $this->escape($variables['title']) ?></title>
    <meta name="description" content="<?= $variables['meta']['description'] ?>">
    <meta name="keywords" content="<?= $variables['meta']['keywords'] ?>">

и видим теперь заголовок <title>UMI.CMS - Страница 1</title>. Нам "UMI.CMS - " ни разу не нужно. Чтобы настроить параметры по умолчанию, в модулях (под бабочкой) находим раздел SEO, в нем справа вверху видим ссылку "Настройка модуля", жмём и настраиваем, там всё просто. Заменяю "UMI.CMS - " на "Демонстрационный сайт - ".

Чем отличается от прежнего варианта шаблона? Тем, что мы не выводим тупо поле из данных конкретной страницы, а позволяем CMS сформировать для нас эти параметры, используя настройки по умолчанию.

Делим шаблон на части

Чтобы не мучиться с длинной простынёй кода, существует хорошая практика делить его на разумные фрагменты. Скажем, сразу хочется выделить <head>, <header> и <footer>.

В директории /templates/default/php/ создаём поддиректорию layout, а в ней файлы наших фрагментов:

  • head.phtml
  • header.phtml
  • main.phtml
  • footer.phtml

Помещаем в эти файлы фрагменты кода шаблонов, например, head.phtml будет выглядеть вот так:

<head>
    <base href="/templates/default/">
    <title><?= $variables['title'] ?></title>
    <meta charset="utf-8">
    <meta name="description" content="<?= $variables['meta']['description'] ?>">
    <meta name="keywords" content="<?= $variables['meta']['keywords'] ?>">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>

А main.phtml вот так:

<?php
$page = $variables['page'];
?>
    <main>
        <section>
            <div class="container">
                <div class="row">
                    <div class="col-12">
                        <h1><?= $page->h1 ?></h1>
                    </div>
                    <div class="col-12">
                        <p><?= $page->content ?></p>
                    </div>
                </div>
            </div>
        </section>
    </main>

Теперь в шаблоне можно просто подключить эти фрагменты:

<!DOCTYPE html>
<html>
<?= $this->render($variables, 'layout/head') ?>
<body>
<?= $this->render($variables, 'layout/header') ?>
<?= $this->render($variables, 'layout/main') ?>
<?= $this->render($variables, 'layout/footer') ?>

    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>
</html>

Заметим, что в качестве первого параметра при вызове метода render() мы передаем массив $variables конкретной страницы. Второй параметр - это адрес шаблона относительно папки php и без расшмрения ".phtml". Поэтому делать у файлов шаблона именно такое расширение - обязательно! Иначе не найдет.

Добавляем меню

Выше мы использовали волшебную переменную $this, но для вызова только одного метода - render(). А какие еще методы нам доступны?

Полный список был бы весьма желателен. Но если кратко - все публичные методы модуля content, их описание и код можно посмотреть в /classes/components/content/class.php и /classes/components/content/macros.php, а также системные и сервисные методы, наследуемые этими классами. Методы класса можно использовать непосредственно, макросы - при помощи метода macros().

Нам для сайта надо получить "дерево" меню. Для этого в файл header.phtml добавляем код:

<?php
$pageId = isset($variables['pageId'])?$variables['pageId']:0;
$menuTree = $this->macros('content', 'menu', [0, 2, 0, true, $pageId]);
var_dump($menuTree);
?>
    <header>
    </header>

Первый параметр метода macros() - название модуля, второй - название метода, третий - параметры, передаваемые методу. Список параметров можно посмотреть в коде метода, все макросы хорошо документированы комментариями. В данном случае используем:

  • шаблон не задан (шаблон задается в других шаблонизаторах, в PHP не работает)
  • 2 уровня вложенности (у нас пока один, но можем потом добавить)
  • начиная от корня сайта (можно указать id страницы, и тогда "дерево" будет построено от неё)
  • выдавать признак, что есть дочерние страницы
  • id текущей страницы передаем, чтобы в результате этот пункт был выделен как активный.

Чтобы изучить возможность добавления второго уровня, добавим вложенную страницу внутрь нашей "Страницы 1". Для этого с разделе "Структура" сайта ставим галочку рядом со "Страница 1" и нажимаем плюс в меню. Назовем ее "Страница 3" и page3 в качестве псевдостатического адреса. Обновляем страницу в браузере - в массиве $menuTree ничего не поменялось!!!

Это очередная засада UMI CMS. Чтобы используемый нами макрос выдавал вложенные страницы, надо в данном случае на "Странице 1" в Дополнительных параметрах поставить признаки "Меню всегда развернуто" и "Показывать подменю". Понятно, что это вопрос умолчаний, но в современных сайтах чаще используется развернутое меню, управляемое JS, а не как раньше - статическое индивидуальное меню для каждой страницы.

Господа разработчики, может, пора уже облегчить жизнь редакторам сайтов, и изменить настройки? Пусть у всех страниц эти признаки будут по умолчанию включены, как вы считаете?

Полюбовавшись структурой полученного массива, можем теперь вывести нормальное меню сайта:

<?php
$pageId = isset($variables['pageId'])?$variables['pageId']:0;
$menuTree = $this->macros('content', 'menu', [0, 2, 0, true, $pageId]);
?>
    <header>
        <nav class="navbar navbar-expand-lg navbar-light bg-light">
            <a class="navbar-brand" href="/">Логотип</a>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>

            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                <ul class="navbar-nav mr-auto">
<?php 
    foreach ($menuTree['void:lines'] as $item) {
        $dropdown = !empty($item['items']['nodes:item']);
        $active = !empty($item['attribute:status']);
        if (isset($item['link']) && isset($item['name'])) {
            if ($dropdown) {
?>
                    <li class="nav-item dropdown <?=$active?'active':''?>">
                        <a class="nav-link dropdown-toggle" href="<?= $item['link'] ?>" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><?= $item['name'] ?></a>
                        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
<?php
                foreach ($item['items']['nodes:item'] as $sub) {
                    if (isset($sub['link']) && isset($sub['name'])) {
?>
                            <a class="dropdown-item" href="<?= $sub['link'] ?>"><?= $sub['name'] ?></a>
<?php
                    }
                }
?>
                        </div>
                    </li>
<?php
            } else {
?>
                    <li class="nav-item  <?=$active?'active':''?>">
                        <a class="nav-link" href="<?= $item['link'] ?>"><?= $item['name'] ?></a>
                    </li>
<?php
            }
        }
    }
?>
                </ul>
            </div>
        </nav>
    </header>

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