На чем мы остановились в предыдущей части? Мы создали следующее:
- плагин landing и миграцию
- проработали модель Page
- настроили поля формы и колонки для списка
В итоге на финальном этапе первого урока у нас была следующая картина:
Мы сделали один вариант страницы лендинга и заполнили его тестовым содержимым.
Компонент
Компоненты, в рамкам OctoberCms это настраиваемые элементы, которые могут быть прикреплены к любой странице или шаблону. Мы можем создавать любое количество компонентов для любых задач, которые могут быть использованы на фронте.
Тут снова без выкрутасов - всё очень подробно расписано в документации OctoberCms - https://octobercms.com/docs/plugin/components
Для нашей задачи нам предстоит создать всего один компонент. Назовем его Page.
Для создания компонента воспользуемся следующей командой:
php artisan create:component sandbox.landing page
В результате выполнения команды в директории нашего плагина будет создан компонент Page с подобной структурой:
Поправим файл Page.php под наши нужды:
<?php namespace Sandbox\Landing\Components;
use Cms\Classes\ComponentBase;
class Page extends ComponentBase
{
public function componentDetails(): array
{
return [
'name' => 'Landing page Component',
'description' => 'Simple landing page component'
];
}
public function defineProperties(): array
{
return [
'page' => [
'title' => 'Page',
'description' => 'Select the page to be displayed',
'type' => 'dropdown'
]
];
}
/**
* Получим список страниц для выбора
* в выпадающем списке в настройках компонента на странице
* @return array
*/
public function getPageOptions(): array
{
return \Sandbox\Landing\Models\Page::lists('title', 'id');
}
/**
* Получим содержимое выбранной страницы
* и добавим ее в переменную landing
* @return void
*/
public function onRun(): void
{
$this->page['landing'] = \Sandbox\Landing\Models\Page::find($this->property('page'));
}
}
И самое главное - не забыть зарегистрировать компонент в нашем плагине, для этого откроем Plugin.php и добавим следующее:
/**
* Registers any front-end components implemented in this plugin.
*
* @return array
*/
public function registerComponents()
{
return [
'Sandbox\Landing\Components\Page' => 'Page'
];
}
Итак, мы создали простейший компонент, который берет из настроек идентификатор страницы и отдает ее в переменную landing.
На самом деле, даже этот вариант можно улучшать и улучшать, но цель уроков - ознакомление с возможностями.
Тема для лендинга.
Для нашей лендинговой темы, мы не будем изобретать велосипед и возьмем, уже полюбившуюся всем, стартовую тему demo - просто скопируем ее в папку landing.
Поправим файл themes/landing/theme.yaml
name: Landing theme
description: 'Landing demo theme'
author: OctoberCMS
homepage: 'http://octobercms.com'
code: 'landing-theme'
Далее подправим файл шаблона themes/landing/pages/home.htm
, подготовив его для дальнейшей работы.
title = "Demonstration"
url = "/"
layout = "default"
==
<div class="container">
Our landing content
</div>
Готово. Теперь наш сайт выглядит примерно так:
Не очень круто =)
Подключение компонента и еще немного правок шаблона.
В панели управления переходим в раздел CMS, открываем шаблон нашей темы и бросаем туда компонент Landing.
В настройках компонента выбираем страницу, содержимое которой хотим отображать.
Компонент подключен к шаблону, соответственно свойства и методы его теперь доступны на всех страницах, которые используют этот шаблон.
Далее отредактируем файл themes/landing/partials/site/header.htm
Удалим всё - добавим такое содержимое:
==
function onStart()
{
$this['backendUrl'] = Backend::url('/');
}
==
<!-- Nav -->
<nav id="layout-nav" class="navbar navbar-inverse navbar-fixed-top navbar-autohide" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="{{ 'home'|page }}">
{{ landing.title }}
</a>
</div>
</div>
</nav>
{{ landing.title }} - это название нашей страницы
После чего, наш сайт стал выглядеть так:
Уже лучше!
Группы контента
Приступим к самому интересному - будем оживлять динамические блоки с содержимым, которые мы уже давным давно создали и даже заполнили контентом.
Группы мы определили при создании модели и формы - это:
- text
- image
- features
- slider
Чтобы убедиться - вернемся к файлу plugins/sandbox/landing/models/page/groups.yaml
text:
name: Text block
description: Text block with richeditor
icon: icon-file-text-o
fields:
text:
label: Text block content
type: richeditor
image:
name: Single image
description: Block with single image
icon: icon-image
fields:
image:
label: Image
type: mediafinder
mode: image
imageHeight: 150
imageWidth: 150
thumbOptions:
mode: crop
extension: auto
features:
name: Features
description: Features simple block
icon: icon-star
fields:
title:
label: Feature title
features_items:
type: repeater
form:
fields:
feature_title:
label: Feature title
span: left
feature_description:
label: Feature description
span: right
slider:
name: Slider
description: Block with slider images
icon: icon-play-circle-o
fields:
images:
label: Slides
type: repeater
form:
fields:
image:
label: Slide Image
type: mediafinder
mode: image
imageHeight: 150
imageWidth: 150
thumbOptions:
mode: crop
extension: auto
В нашей теме в разделе в themes/landing/partials
создадим папку content
, где сложим шаблоны для каждой группы контента.
В папке themes/landing/partials/content
создадим следующие файлы:
- text.htm
- image.htm
- features.htm
- slider.htm
Должна получиться такая структура:
Далее вернемся в файлу themes/landing/pages/home.htm
и отредактируем его следующим образом.
title = "Demonstration"
url = "/"
layout = "default"
==
<div class="container">
{% for blockKey, blockContent in landing.content %}
{% partial 'content/'~ blockContent._group blockContent = blockContent blockKey = blockKey %}
{% endfor %}
</div>
Что означает эта конструкция:
В цикле мы перебираем содержимое landing.content
, это содержимое состоит из именованных групп и содержимого этих групп.
Иными словами зная, что это за группа (из свойства _group
), мы можем динамически отправить ключ и содержимое группы в соответствующую партиалку.
Партиалим!
text.htm
Начнем с файла themes/landing/partials/content/text.htm
Приведем его к следующему виду:
<div id="text-{{ blockKey }}" class="content-block text-block">
{{ blockContent.text|raw }}
</div>
image.htm
Партиалку для отображения картинки themes/landing/partials/content/image.htm
приведем к следующему виду:
<div id="image-{{ blockKey }}" class="content-block image-block">
<div class="image-block__image">
<img src="{{ blockContent.image|media }}">
</div>
</div>
features.htm
Партиалку для отображения преимуществ themes/landing/partials/content/features.htm
тоже модифицируем:
<div id="features-{{ blockKey }}" class="content-block features-block">
<h2>{{ blockContent.title }}</h2>
<div class="features-block__features">
{% for feature in blockContent.features_items %}
<div class="features-block__feature">
<div class="features-block__feature-title">
{{ feature.feature_title }}
</div>
<div class="features-block__feature-description">
{{ feature.feature_description }}
</div>
</div>
{% endfor %}
</div>
</div>
slider.htm
И наконец слайдер themes/landing/partials/content/slider.htm
мы поправим в два этапа.
Для примера слайдера используем библиотеку https://github.com/kenwheeler/slick
Как и написано в документации, подключим стили в файл шаблона themes/landing/layouts/default.htm
в раздел head
<head>
<meta charset="utf-8">
<title>October CMS - {{ this.page.title }}</title>
<meta name="description" content="{{ this.page.meta_description }}">
<meta name="title" content="{{ this.page.meta_title }}">
<meta name="author" content="OctoberCMS">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="OctoberCMS">
<link rel="icon" type="image/png" href="{{ 'assets/images/october.png'|theme }}">
<!-- slick -->
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.css"/>
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick-theme.css"/>
<!-- slick -->
<link href="{{ 'assets/css/vendor.css'|theme }}" rel="stylesheet">
<link href="{{ 'assets/css/theme.css'|theme }}" rel="stylesheet">
{% styles %}
</head>
и в конец шаблона добавим js-библиотеку:
<script src="{{ 'assets/vendor/jquery.js'|theme }}"></script>
<script src="{{ 'assets/vendor/bootstrap.js'|theme }}"></script>
<!-- slick -->
<script type="text/javascript" src="//cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.min.js"></script>
<!-- slick -->
<script src="{{ 'assets/javascript/app.js'|theme }}"></script>
{% framework extras %}
{% scripts %}
Далее отредактируем файл themes/landing/partials/content/slider.htm
и приведем его к следующему виду:
<div id="slider-{{ blockKey }}" class="content-block slider-block">
<h2>{{blockContent.hint}}</h2>
<div class="slider-block__slider">
{% for image in blockContent.images %}
<div class="slider-block__slide" style="background-image: url('{{ image.image|media }}');"></div>
{% endfor %}
</div>
</div>
{% put scripts %}
<script>
$('#slider-{{ blockKey }} .slider-block__slider').slick({
dots: true,
infinite: true,
speed: 300,
slidesToShow: 1,
});
</script>
{% endput %}
Немного CSS
Мы не зря добавили css-классы в наши partial-файлы. Приправим наш урок небольшой порцией css.
В конец файла themes/landing/assets/css/theme.css
добавим немного своего:
.content-block {
margin-bottom: 40px;
}
.features-block h2 {
text-align: center;
}
.features-block__features {
display: flex;
justify-content: center;
}
.features-block__feature {
padding: 30px;
flex: 1 1 0;
}
.features-block__feature-title {
font-size: 18px;
text-align: center;
}
.features-block__feature-description {
font-size: 48px;
text-align: center;
}
.image-block {
display: flex;
justify-content: center;
}
.image-block__image {
width: 70%;
}
.image-block__image img {
width: 100%;
}
.slider-block__slide {
height: 500px;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
Что в итоге?
В итоге у нас должно получиться следующее:
Выглядит вполне приемлемо!
Немного универсализации
Что же мы хотим - мы хотим в дальнейшем посадить на один движок OctoberCMS несколько лендингов, чем больше - тем лучше!
Можно заморочиться и написать свой плагин для мультисайта, но в рамках урока используем готовые наработки из маркетплейса OctoberCms - плагин Multiple Websites Manager Lite - простой, понятный и бесплатный.
Что нужно сделать:
- установить плагин Briddle.Multisite
- суметь настроить домен третьего уровня (об этом не в этом уроке)
- отредактировать конфиг плагина
/plugins/briddle/multisite/config
Для примера мы скопируем нашу тему landing
и назовем ее landing2
Не забываем отредактировать файл themes/landing2/theme.yaml
name: Landing theme 2
description: 'Landing demo theme 2'
author: OctoberCMS
homepage: 'http://octobercms.com'
code: 'landing-theme-2'
Далее отредактируем /plugins/briddle/multisite/config
<?php
return [
'sites' => [
[
'host' => 'sandbox.test',
'theme' => 'landing'
],
[
'host' => 'landing2.sandbox.test',
'theme' => 'landing2'
]
]
];
В админке сайта добавляем новый материал:
Теперь заходим в админку сайта, но уже по адресу landing2.sandbox.test
Переходим в раздел CMS и отредактируем файл шаблона layouts/default.htm
Выбираем новую созданную страницу.
Результат
По итогу этого небольшого гайда у нас должно быть в наличии:
- плагин для создания лендинговых страниц
- две темы (сайта) , которые работают с одним движком
- и такой результат:
Надеемся, что данный материал будет кому-то полезен и пригодится для изучения OctoberCMS!
Ссылки
Первая часть урока в нашем блоге
Первая часть урока на OctoClub
Репозиторий с исходным кодом на GitHub