Создание настроек сайта: различия между версиями
Olga (обсуждение | вклад) |
Olga (обсуждение | вклад) |
||
(не показано 14 промежуточных версий этого же участника) | |||
Строка 25: | Строка 25: | ||
И тут мы сталкиваемся с очередной засадой UMI CMS. Казалось бы, каждому сайту должен соответствовать какой-то один набор настроек. Но в интерфейсе видим, что этих наборов можно создать сколько угодно. '''Господа разработчики''', может, стоило бы для упрощения ограничить эти возможности? Кто-то вообще использует больше одного набора настроек для конкретной языковой версии сайта? Было бы шикарно получать настройки прямо в массиве $variables, как вы считаете? | И тут мы сталкиваемся с очередной засадой UMI CMS. Казалось бы, каждому сайту должен соответствовать какой-то один набор настроек. Но в интерфейсе видим, что этих наборов можно создать сколько угодно. '''Господа разработчики''', может, стоило бы для упрощения ограничить эти возможности? Кто-то вообще использует больше одного набора настроек для конкретной языковой версии сайта? Было бы шикарно получать настройки прямо в массиве $variables, как вы считаете? | ||
− | Зато есть повод поупражняться с API системы. Один из способов получить настройки - использовать | + | Зато есть повод поупражняться с API системы. Один из способов получить настройки - использовать название настроек, в данном случае 'demo': |
− | < | + | <syntaxhighlight lang="php"> |
− | $ | + | $settings = $this->getObjectById($this->macros('umiSettings', 'getIdByName', 'demo'])); |
− | |||
− | |||
var_dump($settings); | var_dump($settings); | ||
− | </ | + | </syntaxhighlight> |
− | Здесь мы использовали | + | Здесь мы использовали метод getIdByName('...') модуля umiSettings для получения id настроек по названию (это именно название, не идентификатор), а потом получили сам объект настроек при помощи метода getObjectById(). |
− | Добавим этот код в самое начало common.phtml. К счастью, в настройках разных языковых версий можно задавать | + | Добавим этот код в самое начало common.phtml. К счастью, в настройках разных языковых версий можно задавать одно и то же название, а то было бы совсем грустно. В общем, получилось. Если добавить на страницу <?= $settings->copyright ?>, то увидим копирайт, который ввели. |
Теперь попробуем другой путь, ведь мы не фанаты делать кучу настроек: | Теперь попробуем другой путь, ведь мы не фанаты делать кучу настроек: | ||
− | < | + | <syntaxhighlight lang="php"> |
$set = new selector('objects'); | $set = new selector('objects'); | ||
$set->types('object-type')->name('umiSettings', 'settings'); | $set->types('object-type')->name('umiSettings', 'settings'); | ||
− | $set->where('domain_id')->equals($variables[' | + | $set->where('domain_id')->equals($variables['domain-id']); |
− | $set->where('lang_id')->equals($variables[' | + | $set->where('lang_id')->equals($variables['lang-id']); |
$set->limit(0, 1); | $set->limit(0, 1); | ||
$settings = $set->result(); | $settings = $set->result(); | ||
var_dump($settings); | var_dump($settings); | ||
− | </ | + | </syntaxhighlight> |
− | В этом коде был использован самый мощный класс UMI | + | В этом коде был использован самый мощный класс ядра UMI - selector. Он подробно описан в документации. Чего в документации нет, так это - что подставлять в качестве 'object-type'. Но в админке есть где посмотреть: 'Шаблоны данных' - 'Настройки модуля' (ссылка справа вверху). Для начала лучше в этих настройках ничего не менять, но в качестве справочника - бесценно! |
Здесь мы ищем селектором те единственные настройки, что соответствуют конкретной языковой версии нашего сайта. Синтаксически это почти SQL-запрос, на мой взгляд, тут всё просто. | Здесь мы ищем селектором те единственные настройки, что соответствуют конкретной языковой версии нашего сайта. Синтаксически это почти SQL-запрос, на мой взгляд, тут всё просто. | ||
− | UMI CMS в конце каждой страницы выдает время её формирования, что очень удобно. Легко убедиться, что второй способ на 0.001 секунды быстрее, помимо прочих его преимуществ. Конечно, неплохо бы проверить, что хоть какие-то настройки нашлись. В результате, | + | UMI CMS в конце каждой страницы выдает время её формирования, что очень удобно. Легко убедиться, что второй способ на 0.001 секунды быстрее, помимо прочих его преимуществ. Конечно, неплохо бы проверить, что хоть какие-то настройки нашлись. Кроме этого, хотелось бы получить настройки в самом начале, а использовать их в произвольных фрагментах нашего шаблона. В результате модифицируем код common.phtml как-то так: |
+ | |||
+ | <syntaxhighlight lang="php"> | ||
+ | <?php | ||
+ | $set = new selector('objects'); | ||
+ | $set->types('object-type')->name('umiSettings', 'settings'); | ||
+ | $set->where('domain_id')->equals($variables['domain-id']); | ||
+ | $set->where('lang_id')->equals($variables['lang-id']); | ||
+ | $set->limit(0, 1); | ||
+ | $variables['settings'] = array_shift($set->result()); | ||
+ | if (empty($variables['settings'])) { | ||
+ | echo $this->translate('no settings'); | ||
+ | exit(); | ||
+ | } | ||
+ | ?> | ||
+ | <!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://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> | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Копирайт мы собирались использовать в подвале сайта, поэтому пишем в footer.phtml: | ||
+ | |||
+ | <syntaxhighlight lang="php"> | ||
+ | <footer> | ||
+ | <div class="container"> | ||
+ | <?= $variables['settings']->copyright ?><?= date("Y") ?> | ||
+ | |||
+ | </div> | ||
+ | </footer> | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Проверяем результат - всё получилось! Теперь надо разобраться с логотипом. Добавляем <?php var_dump($variables['settings']->logo); ?> в файл header.phtml, и видим, что это объект. Причем - ещё одна засада UMI CMS - все свойства без исключения protected!!! Зато в нем есть все, что нам нужно. Итак, изучаем документацию по классам umiFile и umiImageFile, и новый header.phtml будет выглядеть примерно так: | ||
+ | |||
+ | <syntaxhighlight lang="php"> | ||
+ | <?php | ||
+ | $pageId = isset($variables['pageId'])?$variables['pageId']:0; | ||
+ | $menuTree = $this->macros('content', 'menu', [0, 2, 0, true, $pageId]); | ||
+ | $logo = $variables['settings']->logo; | ||
+ | ?> | ||
+ | <header> | ||
+ | <nav class="navbar navbar-expand-lg navbar-light bg-light"> | ||
+ | <a class="navbar-brand" href="/"> | ||
+ | <?php if ($logo): ?> | ||
+ | <img src="/<?= $logo->getFilePath() ?>" title="<?= $logo->getTitle() ?>" alt="<?= $logo->getAlt() ?>"> | ||
+ | <?php endif; ?> | ||
+ | </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['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']['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> | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Почему перед адресом изображения стоит '/'? Потому что getFilePath() зачем-то перед адресом ставит точку, хоть адрес возвращает абсолютный. Загадка. В качестве alt и title пробуем получить значения, которые должны были задать в админке при заливке файла. Но поскольку ничего не задали, они будут пустые. А вообще, по-хорошему, надо добавить в настройки еще одно поле - название компании, и выводить именно его. | ||
+ | |||
+ | == Edit-in-place для настроек == | ||
+ | |||
+ | Теперь осталось добавить возможность изменять эти поля прямо на сайте. В принципе, ничего сложного: | ||
+ | |||
+ | <syntaxhighlight lang="html"> | ||
+ | <img umi:object-id="<?= $logo->getId() ?>" umi:field-name="logo" src="/<?= $logo->getFilePath() ?>" title="<?= $logo->getTitle() ?>" alt="<?= $logo->getAlt() ?>"> | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Это для логотипа, а для копирайта: | ||
+ | |||
+ | <syntaxhighlight lang="php"> | ||
+ | <span umi:object-id="<?= $logo->getId() ?>" umi:field-name="logo" umi:empty="<?= $this->translate('empty_copyright') ?>"> | ||
+ | <?= $variables['settings']->copyright ?> | ||
+ | </span> <?= date("Y") ?> | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Заметим, что псевдо-атрибуты для id контентных страниц и объектов отличаются, если для полей страниц мы использовали атрибут umi:element-id, то для полей объектов приходится писать umi:object-id. Это отражение внутреннего деления UMI CMS на страницы контента и объекты, за работу с которыми отвечают разные методы. | ||
+ | |||
+ | Также пришлось добавить дополнительный <nowiki><span></nowiki>, чтобы копирайт был в отдельном контейнере. | ||
+ | |||
+ | == Другие модули системы == | ||
+ | |||
+ | Пока нам для сайта хватало модуля content, немного использовали umiSettings. Однако полезных модулей гораздо больше, и пора наконец [[Другие модули системы|добавить на сайт раздел Новости]]. |
Текущая версия на 23:10, 5 ноября 2020
Выбираем в админке раздел "Настройки сайта" и не видим никаких настроек:
Жмём "Создать настройки", и создаём:
Название может быть любое, идентификатор - только латиница. Если создаем настройки для русской версии сайта, на английской они видны не будут. Что в принципе логично.
Теперь видим, что настройки появились:
Вопрос только - что с ними делать? Ставим рядом галку, в пиктографическом меню нажимаем "Редактировать" - и видим ту же самую форму, что только что заполнили. Где логотип, где копирайт? Так мы незаметно подошли к большой теме - Создание шаблонов данных.
Вывод настроек в шаблоне
Добавим в настройки логотип и копирайт:
Теперь попробуем вывести всё это на страницах сайта.
И тут мы сталкиваемся с очередной засадой UMI CMS. Казалось бы, каждому сайту должен соответствовать какой-то один набор настроек. Но в интерфейсе видим, что этих наборов можно создать сколько угодно. Господа разработчики, может, стоило бы для упрощения ограничить эти возможности? Кто-то вообще использует больше одного набора настроек для конкретной языковой версии сайта? Было бы шикарно получать настройки прямо в массиве $variables, как вы считаете?
Зато есть повод поупражняться с API системы. Один из способов получить настройки - использовать название настроек, в данном случае 'demo':
$settings = $this->getObjectById($this->macros('umiSettings', 'getIdByName', 'demo']));
var_dump($settings);
Здесь мы использовали метод getIdByName('...') модуля umiSettings для получения id настроек по названию (это именно название, не идентификатор), а потом получили сам объект настроек при помощи метода getObjectById().
Добавим этот код в самое начало common.phtml. К счастью, в настройках разных языковых версий можно задавать одно и то же название, а то было бы совсем грустно. В общем, получилось. Если добавить на страницу <?= $settings->copyright ?>, то увидим копирайт, который ввели.
Теперь попробуем другой путь, ведь мы не фанаты делать кучу настроек:
$set = new selector('objects');
$set->types('object-type')->name('umiSettings', 'settings');
$set->where('domain_id')->equals($variables['domain-id']);
$set->where('lang_id')->equals($variables['lang-id']);
$set->limit(0, 1);
$settings = $set->result();
var_dump($settings);
В этом коде был использован самый мощный класс ядра UMI - selector. Он подробно описан в документации. Чего в документации нет, так это - что подставлять в качестве 'object-type'. Но в админке есть где посмотреть: 'Шаблоны данных' - 'Настройки модуля' (ссылка справа вверху). Для начала лучше в этих настройках ничего не менять, но в качестве справочника - бесценно!
Здесь мы ищем селектором те единственные настройки, что соответствуют конкретной языковой версии нашего сайта. Синтаксически это почти SQL-запрос, на мой взгляд, тут всё просто.
UMI CMS в конце каждой страницы выдает время её формирования, что очень удобно. Легко убедиться, что второй способ на 0.001 секунды быстрее, помимо прочих его преимуществ. Конечно, неплохо бы проверить, что хоть какие-то настройки нашлись. Кроме этого, хотелось бы получить настройки в самом начале, а использовать их в произвольных фрагментах нашего шаблона. В результате модифицируем код common.phtml как-то так:
<?php
$set = new selector('objects');
$set->types('object-type')->name('umiSettings', 'settings');
$set->where('domain_id')->equals($variables['domain-id']);
$set->where('lang_id')->equals($variables['lang-id']);
$set->limit(0, 1);
$variables['settings'] = array_shift($set->result());
if (empty($variables['settings'])) {
echo $this->translate('no settings');
exit();
}
?>
<!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://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>
Копирайт мы собирались использовать в подвале сайта, поэтому пишем в footer.phtml:
<footer>
<div class="container">
<?= $variables['settings']->copyright ?><?= date("Y") ?>
</div>
</footer>
Проверяем результат - всё получилось! Теперь надо разобраться с логотипом. Добавляем <?php var_dump($variables['settings']->logo); ?> в файл header.phtml, и видим, что это объект. Причем - ещё одна засада UMI CMS - все свойства без исключения protected!!! Зато в нем есть все, что нам нужно. Итак, изучаем документацию по классам umiFile и umiImageFile, и новый header.phtml будет выглядеть примерно так:
<?php
$pageId = isset($variables['pageId'])?$variables['pageId']:0;
$menuTree = $this->macros('content', 'menu', [0, 2, 0, true, $pageId]);
$logo = $variables['settings']->logo;
?>
<header>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/">
<?php if ($logo): ?>
<img src="/<?= $logo->getFilePath() ?>" title="<?= $logo->getTitle() ?>" alt="<?= $logo->getAlt() ?>">
<?php endif; ?>
</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['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']['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>
Почему перед адресом изображения стоит '/'? Потому что getFilePath() зачем-то перед адресом ставит точку, хоть адрес возвращает абсолютный. Загадка. В качестве alt и title пробуем получить значения, которые должны были задать в админке при заливке файла. Но поскольку ничего не задали, они будут пустые. А вообще, по-хорошему, надо добавить в настройки еще одно поле - название компании, и выводить именно его.
Edit-in-place для настроек
Теперь осталось добавить возможность изменять эти поля прямо на сайте. В принципе, ничего сложного:
<img umi:object-id="<?= $logo->getId() ?>" umi:field-name="logo" src="/<?= $logo->getFilePath() ?>" title="<?= $logo->getTitle() ?>" alt="<?= $logo->getAlt() ?>">
Это для логотипа, а для копирайта:
<span umi:object-id="<?= $logo->getId() ?>" umi:field-name="logo" umi:empty="<?= $this->translate('empty_copyright') ?>">
<?= $variables['settings']->copyright ?>
</span> <?= date("Y") ?>
Заметим, что псевдо-атрибуты для id контентных страниц и объектов отличаются, если для полей страниц мы использовали атрибут umi:element-id, то для полей объектов приходится писать umi:object-id. Это отражение внутреннего деления UMI CMS на страницы контента и объекты, за работу с которыми отвечают разные методы.
Также пришлось добавить дополнительный <span>, чтобы копирайт был в отдельном контейнере.
Другие модули системы
Пока нам для сайта хватало модуля content, немного использовали umiSettings. Однако полезных модулей гораздо больше, и пора наконец добавить на сайт раздел Новости.