Коли стандартних блоків 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 робочий день безкоштовно. Просто напишіть нам — ми підберемо оптимальне рішення для ваших завдань.







