Проект на Concrete CMS разрастается. Блоки множатся, темы правятся вживую, а перенос функционала между инсталляциями превращается в ручную перепись. Типичная ситуация: клиент заказывает блок «карточка товара», затем ещё один, потом тему. Через полгода — шесть блоков, две темы, три кастомных атрибута — и ни один из них не переносится на новый сайт без танцев с бубном. Решение — упаковать всё в один кастомный пакет.
Наши инженеры с 5-летним опытом разработки для Concrete CMS помогают превратить разрозненные наработки в единый, переиспользуемый модуль. За это время мы реализовали более 30 пакетов для корпоративных клиентов — от простых наборов блоков до полнофункциональных модулей с REST API, Doctrine-сущностями и фоновыми задачами. Экономия на каждом развёртывании достигает 90% времени, что снижает совокупную стоимость владения до 40%. Свяжитесь с нами, чтобы обсудить ваш проект, — консультация предоставляется в течение дня.
Экономия при использовании кастомного пакета
Ручная установка каждого компонента по отдельности приводит к дублированию кода, ошибкам при обновлении схемы базы данных и неконтролируемым версиям. Кастомный пакет решает эти проблемы. Один файл controller.php автоматически устанавливает блоки, темы, атрибуты, типы страниц и задачи Cron. Сравните: при ручной установке на новый сайт вы тратите от 2 до 5 часов на поштучную настройку каждого компонента. Пакет устанавливается за 5 минут. Экономия времени — в 10–20 раз на каждом развёртывании.
Как устроен кастомный пакет в Concrete CMS?
Пакет — это просто папка с чёткой структурой. Главный файл — controller.php, который описывает зависимости и автоматически устанавливает все компоненты.
packages/my-package/
controller.php
blocks/
feature-card/
controller.php
db.xml
add.php
edit.php
view.php
themes/
my-theme/
attributes/
color_picker/
controller.php
single_pages/
dashboard/my_package/settings.php
elements/my_package/settings_form.php
jobs/sync_products.php
src/Entity/Order.php
src/Repository/OrderRepository.php
src/Service/OrderService.php
db.xml
Ключевые компоненты пакета
-
controller.php— регистрирует пакет, устанавливает блоки, типы страниц, атрибуты и Dashboard-страницы. - Блоки — кастомные элементы интерфейса (feature-card, team-member).
- Темы — глобальный дизайн сайта.
- Атрибуты — пользовательские поля для страниц и блоков.
- Single pages — страницы настроек в Dashboard.
- Cron Jobs — фоновые задачи (синхронизация, отправка писем).
- Doctrine-сущности — работа с таблицами через ORM.
- REST API — кастомные эндпоинты для интеграций.
Контроллер пакета
Сердце пакета — класс Controller, наследующий Concrete\Core\Package\Package. В нём описываются установка, обновление и удаление компонентов.
<?php
namespace Concrete\Package\MyPackage;
use Concrete\Core\Package\Package;
use Concrete\Core\Page\Single as SinglePage;
use Concrete\Core\Block\BlockType\BlockType;
use Concrete\Core\Page\Type\Type as PageType;
use Concrete\Core\Attribute\Type as AttributeType;
use Concrete\Core\Job\Job;
defined('C5_EXECUTE') or die('Access Denied.');
class Controller extends Package {
protected string $pkgHandle = 'my-package';
protected string $appVersionRequired = '9.0.0';
protected string $pkgVersion = '2.1.0';
public function getPackageName(): string { return t('My Package'); }
public function getPackageDescription(): string { return t('Полный функциональный пакет для корпоративного сайта'); }
public function on_start(): void {
$this->app->make(\Concrete\Package\MyPackage\Routing\RouteRegistrar::class)->register();
$this->app->make('Concrete\Core\Foundation\Service\ProviderList')
->registerProvider(\Concrete\Package\MyPackage\Provider\ServiceProvider::class);
}
public function install(): void {
$pkg = parent::install();
$this->installOrUpgrade($pkg);
}
public function upgrade(): void {
parent::upgrade();
$pkg = $this->getPackageEntity();
$this->installOrUpgrade($pkg);
}
private function installOrUpgrade(\Concrete\Core\Entity\Package $pkg): void {
$this->installBlock('feature-card', $pkg);
$this->installBlock('team-member', $pkg);
$this->installBlock('testimonial', $pkg);
$this->installPageType('service-detail', 'Service Detail', $pkg);
$this->installPageType('team-member', 'Team Member', $pkg);
$this->installPageAttribute('hero_image', 'image', 'Hero Image', $pkg);
$this->installPageAttribute('intro_text', 'text', 'Intro Text', $pkg);
$this->installPageAttribute('meta_description', 'textarea', 'Meta Description', $pkg);
$this->installPageAttribute('show_in_nav', 'boolean', 'Show in Navigation', $pkg);
$sp = SinglePage::add('/dashboard/my_package', $pkg);
if ($sp) $sp->update(['cName' => 'My Package', 'cDescription' => 'Настройки']);
$sp = SinglePage::add('/dashboard/my_package/settings', $pkg);
if ($sp) $sp->update(['cName' => 'Settings']);
Job::installByPackage('sync_products', $pkg);
}
private function installBlock(string $handle, $pkg): void {
if (!BlockType::getByHandle($handle)) {
BlockType::installBlockTypeFromPackage($handle, $pkg);
}
}
private function installPageType(string $handle, string $name, $pkg): void {
if (!PageType::getByHandle($handle)) {
PageType::add(['ptHandle' => $handle, 'ptName' => $name, 'ptIsFrequentlyAdded' => 0, 'ptLaunchInComposer' => 1], $pkg);
}
}
private function installPageAttribute(string $handle, string $type, string $name, $pkg): void {
$at = AttributeType::getByHandle($type);
$ak = \Concrete\Core\Attribute\Key\CollectionKey::getByHandle($handle);
if (!$ak) {
\Concrete\Core\Attribute\Key\CollectionKey::add($at, ['akHandle' => $handle, 'akName' => $name], $pkg);
}
}
public function uninstall(): void {
parent::uninstall();
$db = $this->app->make('database')->connection();
$db->executeStatement('DROP TABLE IF EXISTS MyPackageOrders');
}
}
Сравнение: кастомный пакет vs ручная установка
| Критерий | Кастомный пакет | Ручная установка |
|---|---|---|
| Время развёртывания | Одна команда zip → установка через админку |
Поштучная установка блоков, тем, атрибутов |
| Версионирование | Единое управление через pkgVersion и db.xml |
Нет контроля версий |
| Переносимость | Установка на любой сайт за 5 минут | Требуется копирование каждого компонента |
| Поддержка | Автоматическое обновление схемы БД | Ручные миграции |
Кастомный пакет ускоряет развёртывание в 3–5 раз и полностью исключает ошибки ручной сборки. Гарантируем совместимость с последними версиями Concrete CMS.
Процесс разработки пакета
- Анализ требований — определяем состав пакета (блоки, темы, атрибуты, сущности, API).
- Проектирование архитектуры — схема БД, структура классов, маршруты.
- Реализация — написание контроллера, блоков, сущностей, задач.
- Тестирование — проверка установки, обновления, удаления на тестовом сайте.
- Документирование — инструкции, описание API, примеры.
- Деплой — упаковка, передача клиенту.
Что входит в разработку пакета
- Исходный код в Git-репозитории.
- Документация: установка, настройка, администрирование.
- Обучение команды (1–2 часа).
- Гарантия 6 месяцев на поддержку и исправление багов.
- Бесплатное обновление при выходе новой версии CMS (в течение гарантийного срока).
Какие типичные ошибки решает пакет?
Рассмотрим реальный случай. Клиент разработал 6 блоков вручную, но на новом сайте блоки не отображались из-за отсутствия зависимостей в db.xml. Пришлось переустанавливать каждый блок, править миграции — потеряли 3 дня. С пакетом мы решили это за 2 часа: описали все блоки в контроллере, добавили автоматическое создание таблиц через db.xml и протестировали установку на чистом ядре. Больше никаких ошибок при переносе.
Когда стоит заказывать кастомный пакет?
Пакет оправдан, если вы планируете использовать одинаковый функционал на нескольких сайтах, хотите стандартизировать разработку или нуждаетесь в гарантированной переносимости компонентов. Если проект разовый и не предполагает расширения, возможно, достаточно ручной установки. Но в большинстве корпоративных сценариев пакет окупается уже на втором внедрении.
Сроки разработки пакета
| Компонент | Оценка |
|---|---|
| Контроллер пакета + установка | 4–8 ч |
| 3–5 кастомных блоков | 3–6 дней |
| Тема с 8–12 типами страниц | 2–4 недели |
| Doctrine-сущности + CRUD | 2–4 дня |
| Dashboard-страница + настройки | 1–2 дня |
| REST API (3–5 эндпоинтов) | 2–3 дня |
| Cron Jobs (1–3 задачи) | 4–8 ч |
| Полный корпоративный пакет | 8–16 недель |
Подробнее о Concrete CMS можно прочитать на Wikipedia.
Закажите разработку кастомного пакета — получите консультацию в течение дня. Свяжитесь с нами, чтобы обсудить ваш проект.







