Skip to main content

Инструкция по работе с CMS

CMS Module для vsDesk

Модуль CMS позволяет создавать и управлять несколькими сайтами на PHP с хранением данных в БД.

Содержание

Возможности

  • ✅ Создание сайтов в отдельной папке sites в корне системы
  • ✅ Редактирование заголовка и описания каждой страницы (meta tags)
  • ✅ Создание статических страниц
  • ✅ Создание динамических страниц с использованием виджетов Yii Booster (например, bootstrap.widgets.TbListView)
  • ✅ Управление комментариями с возможностью их добавления к страницам
  • ✅ Управление шаблонами с возможностью редактирования в веб-интерфейсе
  • ✅ Управление виджетами для использования на страницах
  • ✅ Загрузка и управление файлами с возможностью быстрой вставки изображений
  • ✅ Создание и управление пользовательскими формами с интеграцией в CRM

Установка

  1. Модуль уже добавлен в конфигурацию protected/config/main.php
  2. Выполните миграцию базы данных:
    php protected/yiic.php migrate
    Или через веб-интерфейс обновления системы.

Структура базы данных

Модуль создает следующие таблицы:

  • cms_sites — сайты
  • cms_pages — страницы (статические и динамические)
  • cms_comments — комментарии
  • cms_templates — шаблоны
  • cms_widgets — виджеты
  • cms_files — файлы
  • cms_forms — формы
  • cms_form_fields — поля форм
  • cms_form_submissions — отправки форм
  • cms_news — контент (новости, статьи, записи блога) с полем content_type для разделения типов

Таблица cms_news:

  • Поддерживает несколько типов контента через поле content_type: news (новости), article (статьи), blog (блог)
  • Каждый тип имеет свой URL-префикс: /news/, /articles/, /blog/
  • Slug уникален в рамках типа контента и сайта

Использование

1. Создание сайта

  1. Перейдите в раздел CMS → Сайты
  2. Создайте новый сайт, указав: Название, Домен (например, example.com), Папку (будет создана в sites/), Шаблон по умолчанию (опционально)

2. Настройка виртуального хоста Apache

Для каждого сайта создайте виртуальный хост, указывающий на папку sites/<folder>/:

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /path/to/vsdesk14/sites/example

    <Directory /path/to/vsdesk14/sites/example>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

3. Создание страниц

Статические страницы

  1. Перейдите в CMS → Страницы
  2. Создайте новую страницу: выберите сайт, укажите заголовок и URL (slug), заполните meta-теги (title, description, keywords), добавьте содержимое через редактор, выберите шаблон (опционально), установите флаги: опубликовано, главная страница, разрешить комментарии

Динамические страницы

Для создания динамической страницы:

  1. Создайте страницу с типом "Dynamic"
  2. В конфигурации виджета укажите JSON с параметрами:
{
  "widget_class": "bootstrap.widgets.TbListView",
  "config": {
    "dataProvider": {
      "class": "CActiveDataProvider",
      "model": "News",
      "pagination": { "pageSize": 10 }
    },
    "itemView": "_news_item"
  }
}

4. Управление контентом (Новости, Статьи, Блог)

Модуль CMS поддерживает несколько типов контента:

  • Новости (news) — доступны по URL /news/{slug}
  • Статьи (article) — доступны по URL /articles/{slug}
  • Блог (blog) — доступны по URL /blog/{slug}

Каждый тип контента может иметь отдельные страницы-списки и использовать свои шаблоны.

Создание контента

  1. Перейдите в CMS → Новости
  2. Создайте новую запись: выберите сайт, выберите тип контента (Новости, Статьи или Блог), укажите заголовок, заполните содержание, добавьте краткое описание (excerpt), укажите автора, выберите шаблон (опционально), установите дату публикации, включите/выключите публикацию
  3. URL формируется автоматически из заголовка (slug) с префиксом в зависимости от типа

Отображение списка контента на странице

  1. Создайте страницу с типом "Dynamic"
  2. В конфигурации виджета укажите JSON с параметром content_type

Для новостей:

{
  "widget_class": "NewsListViewWidget",
  "config": {
    "site_id": 1,
    "content_type": "news",
    "limit": 10,
    "template_id": 1
  }
}

Для статей:

{
  "widget_class": "NewsListViewWidget",
  "config": {
    "site_id": 1,
    "content_type": "article",
    "limit": 10,
    "template_id": 2
  }
}

Для блога:

{
  "widget_class": "NewsListViewWidget",
  "config": {
    "site_id": 1,
    "content_type": "blog",
    "limit": 10,
    "template_id": 3
  }
}

Параметры конфигурации:

  • site_id (integer, обязательный) — ID сайта
  • content_type (string) — тип контента: "news", "article" или "blog" (по умолчанию "news")
  • limit (integer) — количество записей на странице (по умолчанию 10)
  • template_id (integer, опционально) — ID шаблона из БД
  • template_name (string, опционально) — имя шаблона из БД (альтернатива template_id)

В шаблоне используйте плейсхолдер {widget} для вывода списка.

Пагинация

Для включения пагинации в списке добавьте параметр enable_pagination: true:

{
  "widget_class": "NewsListViewWidget",
  "config": {
    "site_id": 1,
    "content_type": "news",
    "limit": 10,
    "enable_pagination": true,
    "page_var": "page",
    "template_id": 5
  }
}

Параметры пагинации:

  • enable_pagination (boolean) — включить пагинацию (по умолчанию false)
  • limit (integer) — количество записей на странице (по умолчанию 10)
  • page_var (string) — имя GET-параметра для номера страницы (по умолчанию page, при включенной пагинации автоматически меняется на {content_type}_page)

Важно: Если на одной странице несколько виджетов с пагинацией, каждый виджет автоматически получает уникальный page_var на основе content_type. Если нужно другое имя параметра, укажите page_var явно в конфигурации виджета.

Использование в шаблоне: плейсхолдер {pagination} выводит навигацию по страницам. Доступны переменные: $news (массив записей текущей страницы), $pagination (объект CPagination: pageCount, currentPage, pageSize, itemCount). Для вывода пагинации в PHP используйте виджет CLinkPager с pages => $pagination.

URL страниц пагинации: новости — /news?page=1, /news?page=2; статьи — /articles?page=1; блог — /blog?page=1 (при включённой пагинации параметр автоматически: news_page, article_page, blog_page).

Кастомизация отображения контента

Виджет использует шаблоны из БД (таблица cms_templates). Создавайте шаблоны в CMS → Шаблоны и укажите template_id или template_name в конфигурации виджета.

Вариант 1: PHP код (рекомендуется)

<div class="news-list">
    <?php foreach ($news as $item): ?>
        <article class="news-item">
            <h3><a href="/news/<?php echo $item->slug; ?>"><?php echo CHtml::encode($item->title); ?></a></h3>
            <p class="excerpt"><?php echo CHtml::encode($item->excerpt); ?></p>
            <div class="meta"><span class="author"><?php echo CHtml::encode($item->author); ?></span>
            <span class="date"><?php echo date('d.m.Y', strtotime($item->published_at)); ?></span></div>
        </article>
    <?php endforeach; ?>
</div>

Вариант 2: Плейсхолдеры

<div class="news-list">
    {news_loop}
    <article class="news-item">
        <h3><a href="{news_url}">{news_title}</a></h3>
        <p class="excerpt">{news_excerpt}</p>
        <div class="meta"><span class="author">{news_author}</span><span class="date">{news_date}</span></div>
    </article>
    {news_loop}
</div>

Доступные плейсхолдеры: {news_id}, {news_title}, {news_slug}, {news_url}, {news_content}, {news_excerpt}, {news_author}, {news_category}, {news_date}, {news_datetime}, {news_reading_time}, {news_loop}.

Переменные в PHP: $news / $items, $item->id, $item->title, $item->slug, $item->content_type, $item->getUrl(), $item->getReadingTimeMinutes() и др.

Просмотр отдельной записи

URL: новости /news/{slug}, статьи /articles/{slug}, блог /blog/{slug}. Все плейсхолдеры и переменные доступны так же. При просмотре одной записи: $news, $item, $items, $site, $template, $controller. Если шаблон не указан — используется встроенный по умолчанию.

Разделение контента по типам

Каждый тип контента имеет свои URL-префиксы и отдельные шаблоны. Создайте отдельные страницы с виджетом NewsListViewWidget и параметром content_type: news, article, blog.

5. Breadcrumbs (Хлебные крошки)

Плейсхолдер {breadcrumbs} в шаблонах. Для страниц: Главная → Текущая страница (или путь по slug). Для контента: Главная → [Тип контента] → Название записи.

Пример в шаблоне:

<header>
    <nav class="breadcrumbs">{breadcrumbs}</nav>
    <h1>{title}</h1>
</header>

В PHP коде:

<?php
$breadcrumbs = $page->getBreadcrumbs(); // или $news->getBreadcrumbs();
echo $controller->renderBreadcrumbs($breadcrumbs, array(
    'separator' => ' > ',
    'containerClass' => 'my-breadcrumbs',
    'itemClass' => 'crumb',
    'linkClass' => 'crumb-link',
    'currentClass' => 'crumb-current',
)); ?>

Параметры renderBreadcrumbs(): separator, containerTag, containerClass, itemTag, itemClass, linkClass, currentClass.

6. Включение других шаблонов (Template Includes)

Плейсхолдеры: {include:template_name}, {include:template_id}. Включение до обработки других плейсхолдеров; рекурсивное включение с защитой от циклов. Шаблоны должны быть активными (is_active=1), имена чувствительны к регистру.

Пример: шаблоны "Header" и "Footer" — в основном шаблоне: {include:Header}, {include:Footer}.

В PHP: $controller->getTemplateContent('Header'), $controller->getTemplateContent(5), $controller->processTemplateIncludes($content).

7. Управление шаблонами

CMS → Шаблоны. Плейсхолдеры: {content}, {title}, {meta_title}, {meta_description}, {widget}, {breadcrumbs}. Пример базового шаблона: head с meta_title/meta_description, header с title, main с {content}, footer.

Управление комментариями

Включение: при редактировании страницы отметьте «Разрешить комментарии». Комментарии привязаны к страницам (page_id), вложенные через parent_id, модерация is_approved, отображаются только одобренные и не спам. В шаблоне: $page->comments, $page->allow_comments. Свойства комментария: id, author_name, author_email, content, created_at, parent_id, replies.

Форма: POST на /cms/frontend/commentComment[page_id], Comment[author_name], Comment[author_email], Comment[content]. После отправки комментарий ждёт модерации. В админке: CMS → Комментарии — одобрение, пометка как спам, редактирование, удаление.

Пример вывода комментариев в шаблоне:

<?php if ($page->allow_comments): ?>
<div id="comments">
    <h2>Комментарии</h2>
    <?php if (!empty($page->comments)): ?>
        <?php foreach ($page->comments as $comment): ?>
            <div class="comment">
                <strong><?php echo CHtml::encode($comment->author_name); ?></strong>
                <span class="date"><?php echo date('d.m.Y H:i', strtotime($comment->created_at)); ?></span>
                <p><?php echo nl2br(CHtml::encode($comment->content)); ?></p>
            </div>
        <?php endforeach; ?>
    <?php else: ?><p>Пока нет комментариев.</p><?php endif; ?>
    <form action="/cms/frontend/comment" method="post">
        <input type="hidden" name="Comment[page_id]" value="<?php echo $page->id; ?>">
        <input type="text" name="Comment[author_name]" required>
        <input type="email" name="Comment[author_email]">
        <textarea name="Comment[content]" required></textarea>
        <button type="submit">Отправить</button>
    </form>
</div>
<?php endif; ?>

Для вложенных комментариев используйте рекурсивную функцию по $comment->replies и выводите только комментарии без parent_id на верхнем уровне.

Загрузка файлов

CMS → Файлы. Файлы сохраняются в sites/<site_folder>/uploads/ или media/cms/. Для изображений автоматически определяются размеры. Используйте URL файла для вставки в контент.

Создание форм

CMS → Формы. Типы полей: text, textarea, email, tel, select, checkbox, radio, file, date, number. Действия при отправке: none, create_request, create_deal. Для CRM укажите ответственного и группу, настройте сопоставление полей формы с полями CRM.

8. Встраивание формы на сайт

Способ 1 (рекомендуется):

<?php echo renderCmsForm(1); ?> // ID формы

Способ 2: через $controller->renderPartial('/cms/form/_form', array('form' => $form)).

В шаблонах доступны: $site, $page, $template, $controller.

Права доступа

Роли модуля:

  • listCmsSite, updateCmsSite, deleteCmsSite, exportCmsSite, importCmsSite — сайты
  • listCmsPage, updateCmsPage, deleteCmsPage — страницы
  • listCmsComment, updateCmsComment — комментарии
  • listCmsTemplate, updateCmsTemplate, deleteCmsTemplate — шаблоны
  • listCmsWidget, updateCmsWidget, deleteCmsWidget — виджеты
  • listCmsFile, deleteCmsFile — файлы
  • listCmsForm, updateCmsForm, deleteCmsForm — формы
  • listCmsNews, updateCmsNews, deleteCmsNews — новости

Экспорт и импорт сайтов

Экспорт: CMS → Сайты → кнопка «Экспорт» — создается ZIP с данными БД и файлами из sites/{folder}/.

Импорт: CMS → Сайты → «Импорт» — выберите ZIP. При совпадении папки создается новая с суффиксом _imported_.

API

Контроллер FrontendController:

  • /cms/frontend/page — отображение страницы (сайт по домену)
  • /cms/frontend/comment — отправка комментария
  • /cms/frontend/formSubmit — отправка формы

Сайт определяется по HTTP_HOST.

Структура папок

sites/
  └── <site_folder>/
      ├── index.php
      ├── .htaccess
      ├── assets/
      ├── css/
      ├── js/
      ├── images/
      └── uploads/

Каждый CMS сайт использует только ресурсы из sites/<folder>/.

Интеграция с CRM

Формы с действием create_request или create_deal создают заявки/сделки. Настройте сопоставление полей формы с полями CRM.

Автоматическое создание контакта

При создании сделки (create_deal) система создаёт или находит контакт по данным формы. Распознаваемые имена полей:

  • Email: email, e-mail, Email, user_email, user-email, userEmail и т.п.
  • Телефон: phone, tel, telephone, Phone, user_phone, userPhone и т.п.
  • Имя (first_name): first_name, firstname, user_name, name, Name и т.п.
  • Фамилия (last_name): last_name, lastname, user_surname, surname, Surname и т.п.
  • Полное имя: name, fullname, full_name, FullName (если first_name/last_name не найдены)
  • Дополнительно: position, address, comment

Логика: поиск контакта по email → при отсутствии создаётся новый; при одном имени разбивается на first_name/last_name; при отсутствии имени используется часть email до @. Все данные формы сохраняются в поле comment сделки.

Пример формы для автосоздания контакта:

<input name="user_email" type="email" required>
<input name="user_phone" type="tel">
<input name="user_name" type="text" placeholder="Имя">
<input name="user_surname" type="text" placeholder="Фамилия">
<!-- или --> <input name="name" type="text" placeholder="Полное имя">
<textarea name="message"></textarea>