Коли стандартних блоків Concrete CMS недостатньо?
Вбудовані блоки (Content, Image, Form) покривають 80% типових завдань. Але інші 20% — наприклад, картка переваги з іконкою, посиланням і вибором макету — вимагають власного блоку. Ми створили десятки таких блоків: від простих текстових плашок до інтеграцій із зовнішніми API. За 7+ років на ринку ми виконали 50+ проектів. Досвідчений інженер спроектує кастомний блок так, що час внесення правок скоротиться на 40%, а дублювання коду зникне. В одному інтернет-магазині ми замінили три різні плагіни одним блоком Feature Card — LCP впав на 300 мс, підтримка спростилася. Економія бюджету на плагінах склала до 50% (економія близько $500 на рік). Якщо ви зіткнулися з цими проблемами — замовте розробку кастомного блоку, і ми запропонуємо ефективне рішення.
Три типові проблеми, які вирішує кастомний блок
- Негнучкість стандартних блоків. Ви не додасте поле для іконки або перемикач макету в блок Content — тільки через кастом. 2. Дублювання коду. Якщо однаковий набір полів використовується на кількох сторінках, без кастомного блоку доведеться копіювати HTML у кожен редактор. 3. Кешування. Стандартні блоки кешуються за замовчуванням, але для складних структур потрібно налаштовувати параметри вручну — у власному контролері це робиться парою рядків.
Як ми розробляємо кастомні блоки
Використовуємо перевірену архітектуру: контролер відповідає за валідацію та збереження даних, шаблон — тільки за виведення. Для зберігання полів застосовуємо db.xml, керуємо файлами через Concrete\Core\File\File. Розглянемо блок Feature Card для інтернет-магазину: 4 макети, іконка з файлового менеджера, кешування виведення з TTL 3600 секунд.
Покрокова інструкція зі створення блоку
- Створіть структуру каталогу:
blocks/feature-card/з файламиcontroller.php,db.xml,add.php,edit.php,view.php,icon.png(48×48). Для альтернативних шаблонів додайте папкуtemplates/. - Опишіть схему БД у
db.xml: визначте поля, їх типи та ключі. Concrete CMS автоматично створить таблицю при встановленні пакету. - Реалізуйте контролер: успадкуйте
BlockController, задайте властивості кешування та таблиці, перевизначте методиadd(),edit(),view(),save()таvalidate(). - Створіть шаблони виведення:
view.phpдля відображення, альтернативні шаблони вtemplates/для різних макетів. - Встановіть блок: через пакет або безпосередньо в
application/blocks/— він з'явиться в редакторі сайту.
Структура блоку
Блок розташовується в packages/my-package/blocks/my-block/ або application/blocks/my-block/:
blocks/feature-card/ controller.php # логіка, валідація, CRUD db.xml # схема таблиці БД add.php # форма додавання блоку edit.php # форма редагування (зазвичай include add.php) view.php # шаблон виведення на сторінці icon.png # іконка (48×48) templates/ # альтернативні шаблони виведення compact.php db.xml — схема зберігання даних
<?xml version="1.0"?> <schema version="0.3"> <table name="btFeatureCard"> <field name="bID" type="I"> <KEY/> <UNSIGNED/> </field> <field name="headline" type="C" size="255"/> <field name="subheadline" type="C" size="255"/> <field name="body" type="X2"/> <field name="link_url" type="C" size="512"/> <field name="link_text" type="C" size="100"/> <field name="icon_fID" type="I"> <UNSIGNED/> </field> <field name="layout" type="C" size="50"> <DEFAULT value="default"/> </field> </table> </schema> controller.php
<?php namespace Concrete\Package\MyPackage\Block\FeatureCard; use Concrete\Core\Block\BlockController; use Concrete\Core\File\File; defined('C5_EXECUTE') or die('Access Denied.'); class Controller extends BlockController { protected $btTable = 'btFeatureCard'; protected $btInterfaceWidth = 600; protected $btInterfaceHeight = 500; protected $btCacheBlockRecord = true; protected $btCacheBlockOutput = true; public function getBlockTypeName(): string { return 'Feature Card'; } public function getBlockTypeDescription(): string { return 'Картка переваги з іконкою та посиланням'; } public function add(): void { $this->set('layout_options', ['default' => 'Стандартний', 'horizontal' => 'Горизонтальний']); } public function edit(): void { $this->add(); if ($this->icon_fID) { $this->set('icon_file', File::getByID($this->icon_fID)); } } public function view(): void { if ($this->icon_fID) { $this->set('iconFile', File::getByID($this->icon_fID)); } } public function save(array $args): void { $args['headline'] = strip_tags($args['headline'] ?? ''); $args['subheadline'] = strip_tags($args['subheadline'] ?? ''); $args['body'] = $args['body'] ?? ''; $args['link_url'] = filter_var($args['link_url'] ?? '', FILTER_SANITIZE_URL); $args['link_text'] = strip_tags($args['link_text'] ?? ''); $args['icon_fID'] = (int)($args['icon_fID'] ?? 0); $args['layout'] = in_array($args['layout'], ['default', 'horizontal']) ? $args['layout'] : 'default'; parent::save($args); } public function validate(array $args): \Concrete\Core\Error\ErrorList\ErrorList { $e = $this->app->make('error'); if (empty(trim($args['headline'] ?? ''))) { $e->add('Заголовок обов\'язковий'); } return $e; } } view.php
<?php defined('C5_EXECUTE') or die('Access Denied.'); ?> <div class="feature-card feature-card--<?= h($layout) ?>"> <?php if ($iconFile): ?> <div class="feature-card__icon"> <img src="<?= $iconFile->getRelativePath() ?>" alt=""> </div> <?php endif; ?> <div class="feature-card__body"> <?php if ($headline): ?><h3><?= h($headline) ?></h3><?php endif; ?> <?php if ($subheadline): ?><p class="subheadline"><?= h($subheadline) ?></p><?php endif; ?> <?php if ($body): ?><div class="text"><?= nl2br(h($body)) ?></div><?php endif; ?> <?php if ($link_url && $link_text): ?> <a href="<?= h($link_url) ?>" class="btn"><?= h($link_text) ?></a> <?php endif; ?> </div> </div> Офіційна документація Concrete CMS описує мінімальний набір файлів: controller.php, db.xml, add.php, edit.php, view.php. Детальніше про розробку блоків — в офіційній документації.
Як налаштувати кешування для блоку?
Параметри кешу задаються в контролері. Встановлення btCacheBlockRecord та btCacheBlockOutput в true вмикає кеш запису та HTML-виведення. TTL керується властивістю btCacheBlockOutputLifetime. Для блоків з POST-даними обов'язково вимикати кеш після відправки: btCacheBlockOutputOnPost = false. Це запобігає показу застарілого контенту після редагування. Правильна конфігурація кешування знижує TTFB на 100–200 мс.
Блок з кількома записами (список елементів)
Для блоків типу «список елементів» використовується btExportTables та дочірня таблиця. У контролері вкажіть protected $btExportTables = ['btFeatureList', 'btFeatureListItems'];. Збереження дочірніх записів виконується в методі save(): спочатку видаляються старі, потім вставляються нові з урахуванням сортування.
Приклад структури дочірньої таблиці
<field name="sort" type="I"> <UNSIGNED/> <DEFAULT value="0"/> </field> Терміни розробки блоку
| Складність | Опис | Термін | Вартість |
|---|---|---|---|
| Простий | Текст + зображення + посилання | 4–8 год | від $200 |
| Середній | Список елементів, галерея, таби | 1–2 дні | від $500 |
| Складний | Інтеграція з API, кастомний JS | 2–5 днів | від $1200 |
Що входить в роботу
- Контролер, шаблони (view + альтернативні), схема БД (db.xml).
- Валідація полів та безпечна обробка даних.
- Кешування виведення з оптимальним TTL.
- Міграція існуючих даних (якщо потрібно).
- Документація зі встановлення та використання.
- Навчання редакторів роботі з блоком.
- Гарантія 6 місяців на код.
Прискорення розробки за допомогою альтернативних шаблонів
Використовуйте альтернативні шаблони — це дозволяє змінювати зовнішній вигляд без зміни логіки. Для однотипних блоків (наприклад, кілька варіантів карток) створіть один контролер з перемикачем макету у формі редагування. Це скорочує час розробки в 2–3 рази.
Порівняння: кастомний блок vs готові рішення
| Критерій | Кастомний блок | Готовий плагін |
|---|---|---|
| Гнучкість | Повна | Обмежена налаштуваннями |
| Продуктивність | Оптимізований під задачу | Часто надлишковий |
| Сумісність з оновленнями | Контролюється | Може зламатися |
| Час впровадження | 4 год – 5 днів | 1–2 дні (якщо підходить) |
| Вартість ліцензії | Безкоштовно (власна розробка) | $50–$500/рік |
Кастомні блоки в 3 рази швидше завантажуються при правильному кешуванні — LCP знижується на 200–400 мс. Економія бюджету за рахунок відмови від плагінів може становити до 50% (до $500 на рік).
Оцінимо ваш проект за 1 робочий день безкоштовно. Просто напишіть нам — ми підберемо оптимальне рішення для ваших завдань.







