Вынесение данных проекта в системные настройки и их вывод через Fenom

Клиент конфиг Курс
Урок о том, как правильно работать со значениями, вынесенными в системные настройки MODX. Или как создать единый центр управления всеми данными проекта — от телефона до соц. сетей и логотипов — и автоматически выводить их в шаблонах.

Выносить настройки будем в дополнение ClientConfig. Если вы первый раз слышите о нем, сначала идем в урок с его документацией — здесь мы сосредотачиваемся исключительно на Fenom и практике.

Зачем выносить данные в настройки

В реальном проекте телефон, email, адрес, соцсети и любые повторяющиеся данные не должны храниться в шаблонах и чанках.

Причины:

  • удобно редактировать (в одном месте → появляются везде);
  • можно менять данные без разработчика;
  • меньше дублирования;
  • меньше ошибок;
  • проще поддерживать проект в долгосрочной перспективе;
  • хороший тон для модульных систем.

Создаём настройки

Как создавать группы и настройки есть в уроке по ClientConfig, здесь только важная практическая суть. В общем смотрим код шалона и смотрим, что из него можно вынести. Я вынес следующее:

Созданные настройки

Название Ключ Тип поля Значение
Телефон cc_phone Текст (800) 123-4567
Доп. телефон cc_dop_phone Текст (800) 123-4567
Email cc_email Текст mail@example.com
Часы работы сс_opening_hours Текст Mon — Sat 9:00am — 6:00pm / Sunday — CLOSED
Адрес cc_address Текст 123 Street Name, City, England
Соцсети cc_socials_json Code или
Текстовая
область
[
{
"name": "instagram",
"url": "https://www.instagram.com/",
"icon": "fab fa-instagram",
"title": "Instagram"
},
{
"name": "x",
"url": "https://www.x.com/",
"icon": "fab fa-x",
"title": "X"
},
{
"name": "facebook",
"url": "https://www.facebook.com/",
"icon": "fab fa-facebook-f",
"title": "Facebook"
}
]
Логотип cc_logo Изображение img/demos/seo-2/logo.png
Логотип в подвале cc_logo_footer Изображение img/demos/seo-2/logo-footer.png
Текст в футере cc_about Текстовый редактор Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc viverra lorem ipsum erat orci, ac auctor lacus tincidunt ut…

Все настройки — это просто системные опции MODX с собственным namespace.

Получение значений в Fenom (3 способа)

Прямой вызов config: {'cc_phone' | config};

Через объект MODX: {$_modx.config.cc_phone};

Сохранить в переменную (желательно): {set $phone = 'cc_phone' | config} и соответственно вызывать ее затем так {$cc_phone}

О том почему лучше выносить в системные переменные рассказывал в прошлом уроке.

А вот Json массив выводится интереснее:

{if $json}
  {set $items = $json | fromJSON}
  <ul class="social-icons custom-social-icons-style-1">
    {foreach $items as $item}
      {if $item.url}
        <li class="social-icons-{$item.name}">
          <a href="{$item.url}" target="_blank" title="{$item.title}">
            <i class="{$item.icon}"></i>
          </a>
        </li>
      {/if}
    {/foreach}
  </ul>
{/if}

Подключение и вывод настроек в базовом шаблоне (base.tpl)

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

{* Подтягиваем настройки проекта *}
{set $phone    = 'cc_phone' | config}
{set $email    = 'cc_email' | config}
{set $address  = 'cc_address' | config}
...

<!DOCTYPE html>
<html>
    <head>
        ...

$phone, $email, $socials доступны весь шаблон.

В конечном итоге код базового шаблона (base.tpl), должен принять примерно вот такой вид:

{set $site_name = 'site_name' | config}
{set $site_url = 'site_url' | config}
{set $culture = 'cultureKey' | config}
{set $title = ($_modx->resource.longtitle ?: $_modx->resource.pagetitle) | notags}
{set $description = $_modx->resource.description | replace :' "':' «' | replace :'"':'»'}
{set $cc_phone = 'cc_phone' | config}
{set $cc_dop_phone = 'cc_dop_phone' | config}
{set $cc_email = 'cc_email' | config}
{set $cc_opening_hours = 'cc_opening_hours' | config}
{set $cc_address = 'cc_address' | config}
{set $cc_logo = 'cc_logo' | config}
{set $cc_logo_footer = 'cc_logo_footer' | config}
{set $cc_about = 'cc_about' | config}
{set $json = 'cc_socials_json' | config}
<!DOCTYPE html>
<html lang="{$cultureKey}">
<head>
    <base href="{$site_url}">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{$title}</title>
    <meta name="description" content="{$description}">
    <meta name="author" content="fastdevlab.com">
    <!-- Favicon -->
    <link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon" />
    <link rel="apple-touch-icon" href="img/apple-touch-icon.png">
    <!-- Mobile Metas -->
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, shrink-to-fit=no">
    <!-- Web Fonts  -->
    <link id="googleFonts" href="https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700&display=swap" rel="stylesheet" type="text/css">
    <!-- Vendor CSS -->
    <link rel="stylesheet" href="vendor/bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" href="vendor/fontawesome-free/css/all.min.css">
    <link rel="stylesheet" href="vendor/animate/animate.compat.css">
    <link rel="stylesheet" href="vendor/simple-line-icons/css/simple-line-icons.min.css">
    <link rel="stylesheet" href="vendor/owl.carousel/assets/owl.carousel.min.css">
    <link rel="stylesheet" href="vendor/owl.carousel/assets/owl.theme.default.min.css">
    <link rel="stylesheet" href="vendor/magnific-popup/magnific-popup.min.css">
    <!-- Theme CSS -->
    <link rel="stylesheet" href="css/theme.css">
    <link rel="stylesheet" href="css/theme-elements.css">
    <link rel="stylesheet" href="css/theme-blog.css">
    <link rel="stylesheet" href="css/theme-shop.css">
    <!-- Demo CSS -->
    <link rel="stylesheet" href="css/demos/demo-seo-2.css">
    <!-- Skin CSS -->
    <link id="skinCSS" rel="stylesheet" href="css/skins/skin-seo-2.css">
    <!-- Theme Custom CSS -->
    <link rel="stylesheet" href="css/custom.css">
</head>
<body>
<div class="body">
    <header id="header" class="header-transparent header-effect-shrink" data-plugin-options="{ 'stickyEnabled': true, 'stickyEffect': 'shrink', 'stickyEnableOnBoxed': true, 'stickyEnableOnMobile': false, 'stickyChangeLogo': true, 'stickyStartAt': 70, 'stickyHeaderContainerHeight': 70 }">
        <div class="header-body border-top-0 appear-animation" data-appear-animation="fadeIn">
            <div class="header-top">
                <div class="container">
                    <div class="header-row">
                        <div class="header-column justify-content-start">
                            <div class="header-row">
                                <nav class="header-nav-top">
                                    <ul class="nav nav-pills">
                                        <li class="nav-item">
                                            <span class="ws-nowrap custom-text-color-grey-1 text-2 ps-0"><i class="icon-envelope icons text-4 top-3 left-1 me-1"></i> <a href="mailto:{$cc_email}" class="text-color-default text-color-hover-primary">{$cc_email}</a></span>
                                        </li>
                                        <li class="nav-item d-none d-md-block">
                                            <span class="ws-nowrap custom-text-color-grey-1 text-2"><i class="icon-clock icons text-4 top-3 left-1 me-1"></i> {$cc_opening_hours}</span>
                                        </li>
                                    </ul>
                                </nav>
                            </div>
                        </div>
                        <div class="header-column justify-content-end">
                            <div class="header-row">
                                {if $json}
                                  {set $items = $json | fromJSON}
                                  <ul class="header-social-icons social-icons social-icons-clean d-none d-lg-block me-3">
                                    {foreach $items as $item}
                                      {if $item.url}
                                        <li class="social-icons-{$item.name}">
                                          <a href="{$item.url}" target="_blank" title="{$item.title}">
                                            <i class="{$item.icon}"></i>
                                          </a>
                                        </li>
                                      {/if}
                                    {/foreach}
                                  </ul>
                                {/if}
                                <a href="tel:{$cc_phone | preg_replace : '/[^0-9+]/' : ''}" class="btn btn-tertiary font-weight-semibold text-3 px-4 custom-height-1 rounded-0 align-items-center d-none d-md-flex">
                                    <i class="icon-phone icons text-4 me-2"></i> {$cc_phone}
                                </a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="header-container container">
                <div class="header-row">
                    <div class="header-column">
                        <div class="header-row">
                            <div class="header-logo">
                                <a href="/">
                                    <img alt="{$site_name}" width="126" height="32" src="{$cc_logo}">
                                </a>
                            </div>
                        </div>
                    </div>
                    <div class="header-column justify-content-end">
                        <div class="header-row">
                            <div class="header-nav header-nav-links order-2 order-lg-1">
                                <div class="header-nav-main header-nav-main-square header-nav-main-effect-2 header-nav-main-sub-effect-1">
                                    <nav class="collapse">
                                        <ul class="nav nav-pills" id="mainNav">
                                            <li>
                                                <a class="nav-link active" href="/">
                                                    Home
                                                </a>
                                            </li>
                                            <li class="dropdown">
                                                <a class="dropdown-item dropdown-toggle" href="demo-seo-2-services.html">
                                                    Services
                                                </a>
                                                <ul class="dropdown-menu">
                                                    <li>
                                                        <a class="nav-link" href="demo-seo-2-services.html">Overview</a>
                                                    </li>
                                                    <li>
                                                        <a class="nav-link" href="demo-seo-2-services-detail.html">Seo Services</a>
                                                    </li>
                                                    <li>
                                                        <a class="nav-link" href="demo-seo-2-services-detail.html">Email Marketing</a>
                                                    </li>
                                                    <li>
                                                        <a class="nav-link" href="demo-seo-2-services-detail.html">Data Analysis</a>
                                                    </li>
                                                    <li>
                                                        <a class="nav-link" href="demo-seo-2-services-detail.html">Digital Marketing</a>
                                                    </li>
                                                    <li>
                                                        <a class="nav-link" href="demo-seo-2-services-detail.html">Social Media Marketing</a>
                                                    </li>
                                                </ul>
                                            </li>
                                            <li>
                                                <a class="nav-link" href="demo-seo-2-blog.html">
                                                    Blog
                                                </a>
                                            </li>
                                            <li>
                                                <a class="nav-link" href="demo-seo-2-contact-us.html">
                                                    Contact Us
                                                </a>
                                            </li>
                                        </ul>
                                    </nav>
                                </div>
                                <button class="btn header-btn-collapse-nav" data-bs-toggle="collapse" data-bs-target=".header-nav-main nav">
                                    <i class="fas fa-bars"></i>
                                </button>
                            </div>
                            <div class="header-nav-features header-nav-features-no-border header-nav-features-lg-show-border order-1 order-lg-2">
                                <div class="header-nav-feature header-nav-features-search d-inline-flex">
                                    <a href="#" class="header-nav-features-toggle text-decoration-none" data-focus="headerSearch" aria-label="Search"><i class="fas fa-search header-nav-top-icon"></i></a>
                                    <div class="header-nav-features-dropdown" id="headerTopSearchDropdown">
                                        <form role="search" action="page-search-results.html" method="get">
                                            <div class="simple-search input-group">
                                                <input class="form-control text-1" id="headerSearch" name="q" type="search" value="" placeholder="Search...">
                                                <button class="btn" type="submit" aria-label="Search">
                                                    <i class="fas fa-search header-nav-top-icon"></i>
                                                </button>
                                            </div>
                                        </form>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </header>

    <div role="main" class="main">
        {block 'content'}

        {/block}
    </div>

    <footer id="footer" class="bg-color-quaternary position-relative mt-0">
        <svg class="custom-section-curved-top-7" width="100%" height="400" xmlns="http://www.w3.org/2000/svg">
            <path id="svg_2" fill="#171940" stroke="#000" stroke-width="0" d="m-16.68437,95.44889c0,0 5.33335,176.00075 660.00283,93.33373c327.33474,-41.33351 503.33549,15.3334 639.00274,35.66682c135.66725,20.33342 59.66691,9.66671 358.33487,28.33346c298.66795,18.66676 268.66829,-45.00088 382.66831,-112.00048c114.00002,-66.9996 718.31698,-59.48704 1221.66946,95.563c503.35248,155.05004 -221.83202,184.10564 -243.66935,197.60521c-21.83733,13.49958 -3008.67549,-19.83371 -3008.00467,-20.83335c-0.67082,0.99964 -30.00428,-232.33469 -10.00419,-317.66839z" class="svg-fill-color-quaternary"/>
        </svg>
        <div class="container position-relative mt-0 mb-4">
            <div class="row py-5">
                <div class="col-lg-3 mb-5 mb-lg-0">
                    <h4 class="font-weight-bold text-color-light text-5 ls-0 pb-1 mb-2">ABOUT US</h4>
                    {$cc_about}
                    <a href="/">
                        <img src="{$cc_logo_footer}" class="img-fluid" alt="{$site_name}">
                    </a>
                </div>
                <div class="col-lg-3 mb-4 mb-lg-0">
                    <h4 class="font-weight-bold text-color-light text-5 ls-0 pb-1 mb-2">USEFUL LINKS</h4>
                    <ul class="list list-unstyled">
                        <li class="mb-1">
                            <a href="#">Features</a>
                        </li>
                        <li class="mb-1">
                            <a href="#">Pages</a>
                        </li>
                        <li class="mb-1">
                            <a href="#">Portfolio</a>
                        </li>
                        <li class="mb-1">
                            <a href="#">About Us</a>
                        </li>
                        <li class="mb-1">
                            <a href="#">Contact Us</a>
                        </li>
                    </ul>
                </div>
                <div class="col-lg-3 mb-4 mb-lg-0">
                    <h4 class="font-weight-bold text-color-light text-5 ls-0 pb-1 mb-2">OUR SERVICES</h4>
                    <ul class="list list-unstyled">
                        <li class="mb-1">
                            <a href="demo-seo-2-services-detail.html">Seo Services</a>
                        </li>
                        <li class="mb-1">
                            <a href="demo-seo-2-services-detail.html">Email Marketing</a>
                        </li>
                        <li class="mb-1">
                            <a href="demo-seo-2-services-detail.html">Data Analysis</a>
                        </li>
                        <li class="mb-1">
                            <a href="demo-seo-2-services-detail.html">Digital Marketing</a>
                        </li>
                        <li class="mb-1">
                            <a href="demo-seo-2-services-detail.html">Social Media Marketing</a>
                        </li>
                    </ul>
                </div>
                <div class="col-lg-3">
                    <h4 class="font-weight-bold text-color-light text-5 ls-0 pb-1 mb-2">CONTACT US</h4>
                    <ul class="list list-unstyled">
                        <li class="mb-1">
                            Address: {$cc_address}
                        </li>
                        <li class="mb-1">
                            Phone: <a href="tel:{$cc_dop_phone | preg_replace : '/[^0-9+]/' : ''}">{$cc_dop_phone}</a>
                        </li>
                        <li class="mb-1">
                            Email: <a href="emailto:{$cc_email}">{$cc_email}</a>
                        </li>
                    </ul>
                    {if $json}
                      {set $items = $json | fromJSON}
                      <ul class="social-icons custom-social-icons-style-1">
                        {foreach $items as $item}
                          {if $item.url}
                            <li class="social-icons-{$item.name}">
                              <a href="{$item.url}" target="_blank" title="{$item.title}">
                                <i class="{$item.icon}"></i>
                              </a>
                            </li>
                          {/if}
                        {/foreach}
                      </ul>
                    {/if} 
                </div>
            </div>
        </div>
        <div class="footer-copyright bg-color-quaternary">
            <div class="container py-2">
                <hr class="bg-color-light opacity-1 mb-0">
                <div class="row justify-content-center py-4">
                    <div class="col-auto">
                        <p class="text-color-light opacity-5 text-3">Porto SEO © Copyright 2025. All Rights Reserved.</p>
                    </div>
                </div>
            </div>
        </div>
    </footer>
</div>
<!-- Vendor -->
<script src="vendor/plugins/js/plugins.min.js"></script>
<!-- Theme Base, Components and Settings -->
<script src="js/theme.js"></script>
<!-- Demo -->
<script src="js/demos/demo-seo-2.js"></script>
<!-- Theme Custom -->
<script src="js/custom.js"></script>
<!-- Theme Initialization Files -->
<script src="js/theme.init.js"></script>
</body>
</html>

В следующем уроке разберем наш шаблон на управляемые блоки. Но перед этим рекомендую создать источник файлов для изображений (чтобы быстрее получать к ним доступ).

Оцените статью
MODX 3
Добавить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.