Как устроена CMS ARGELIT
Что нужно для разработки
- PHP 8.3 или новее (расширения: pdo_mysql, mbstring, openssl, fileinfo, gd, zip, sodium, intl);
- MySQL 5.7+ / MariaDB 10.3+;
- любой локальный сервер (OSPanel, Laragon, Docker) или встроенный:
php artisan serve.
Скачайте архив CMS, распакуйте в папку сайта и пройдите мастер установки. Всё, что вы пишете, лежит в двух папках:
plugins/ и themes/ — ядро трогать не нужно (при обновлении CMS его файлы заменяются).
Папки
| Папка | Что в ней | Можно менять? |
|---|---|---|
core/ |
ядро CMS: админка, сайт, классы Cms\…, функции core/src/helpers.php |
нет — заменяется при обновлении |
vendor/ |
библиотеки (Laravel и другие) | нет |
plugins/ |
плагины, каждый в своей папке | да |
themes/ |
темы; стандартная — themes/starter |
да (стандартную лучше не править — сделайте дочернюю) |
public/uploads/ |
файлы медиатеки | загружаются через админку |
storage/ |
журналы (storage/logs), кэш, резервные копии |
служебная |
.env |
настройки сайта: база, адрес, отладка | да, вручную |
Что происходит на каждом запросе
- Laravel загружается, ядро регистрирует свои типы записей, права, настройки по умолчанию.
- Плагины: подключаются классы (
autoloadизplugin.json), шаблоны и миграции включённых плагинов, затем их адреса (routes/web.php), затем ихplugin.php— и срабатывает событиеplugins_loaded. - Тема: подключаются шаблоны и
functions.phpактивной темы (у дочерней — сначала родительской) — событиеafter_setup_theme. - Событие
init: всё загружено. Здесь регистрируют типы записей, таксономии, блоки, роли. - Дальше — сама страница:
- в админке:
admin_init, построение меню (admin_menu), страница раздела; - на сайте: CMS понимает, что открыто (запись, рубрика, поиск…), событие
template_redirect, выбор шаблона темы (фильтрыtemplate_hierarchy,template_include), вывод — с событиямиsite_head,site_body_open,site_footer.
- в админке:
Поэтому правило простое: в plugin.php и functions.php только подписывайтесь на события, а регистрацию
(типы записей, блоки) делайте в обработчике init.
Хуки: события и фильтры
Событие (action) — «сейчас происходит вот это, кто хочет — сделайте своё»:
// Вывести метку в <head> каждой страницы сайта
add_action('site_head', function ($context) {
echo '<meta name="author" content="Студия ARGELIT">';
});
// Когда пришла заявка с формы — сделать что-то своё
add_action('form_submitted', function ($form, $entry) {
logger()->info('Новая заявка', ['form' => $form->title]);
}, 10, 2);
Фильтр (filter) — «вот значение, можете его поменять»; обработчик обязательно возвращает значение:
// Дописать к заголовку вкладки браузера
add_filter('document_title', fn (string $title) => $title.' — доставка за час');
// Убрать из sitemap.xml записи рубрики «Архив»
add_filter('sitemap_entries', fn (array $entries) => array_filter($entries, fn ($e) => ! str_contains($e['loc'], '/arhiv/')));
- Третий параметр — приоритет (по умолчанию 10): меньше — раньше.
- Четвёртый — сколько аргументов передать обработчику; по умолчанию передаются все.
remove_action()/remove_filter()убирают обработчик,has_action(),did_action()— проверки.- Свои события и фильтры можно вызывать так же:
do_action('my_plugin_saved', $item),apply_filters('my_plugin_price', $price)— так ваш плагин или тему смогут расширять другие.
Все хуки ядра — в справочнике.
Настройки сайта (options)
Настройки — пары «имя → значение» в таблице options; значение может быть строкой, числом или массивом (хранится в JSON).
update_option('otzyvy_per_page', 6);
$perPage = get_option('otzyvy_per_page', 3); // 3 — если настройки ещё нет
delete_option('otzyvy_per_page');
Называйте свои настройки с префиксом плагина (otzyvy_…), чтобы не столкнуться с чужими.
Часто нужные настройки ядра: site_title, site_description, admin_email, timezone, date_format, active_theme, blog_public.
Пользователи, роли и права
Роли: администратор, редактор, автор, участник, подписчик — как в WordPress. Роль — набор прав (edit_posts, manage_options…).
Проверяйте права, а не роли:
if (current_user_can('manage_options')) { … } // в PHP
@can('edit_others_posts') … @endcan // в шаблоне Blade
Свои роли и права — в init:
add_action('init', function () {
add_role('manager', 'Менеджер', ['read', 'edit_posts', 'upload_files', 'manage_reviews']);
app(\Cms\Auth\Roles::class)->addCap('administrator', 'manage_reviews');
});
Laravel внутри
CMS — это приложение на Laravel 13, поэтому в плагинах доступно всё: DB, Eloquent-модели, Http, Cache, Mail
(письма уходят так, как настроено в «Настройки → Почта»), очереди, валидация, Blade. Модели ядра: Cms\Models\Post,
Term, Media, Menu, Form, FormEntry; пользователи — App\Models\User.
Команды
php artisan cms:plugin list # плагины: list | activate папка | deactivate папка
php artisan cms:make-plugin otzyvy --name="Отзывы"
php artisan cms:make-theme pekarnya --name="Пекарня" # дочерняя тема «Старта»; --copy — полная копия
php artisan cms:admin # создать администратора или сменить пароль
php artisan cms:backup # резервная копия сайта
php artisan migrate # таблицы ядра и включённых плагинов
Отладка
- На своём компьютере включите в
.envAPP_DEBUG=true— ошибки будут видны прямо на странице. На рабочем сайте — толькоfalse. - Журнал ошибок —
storage/logs/. - Если плагин падает с ошибкой, CMS сама его отключает и показывает текст ошибки с файлом и строкой в разделе «Плагины» —
сайт продолжает работать. Ошибка в
functions.phpтемы видна в «Внешний вид → Темы». - Плагин, из-за которого не открывается админка, отключается из командной строки:
php artisan cms:plugin deactivate папка. - «Инструменты → Здоровье сайта» показывает версии PHP, базы, настройки сервера.
Безопасность — коротко
- Выводите данные через
{{ }}(экранирует HTML);{!! !!}— только для HTML, который вы сами проверили. - В каждой форме —
@csrf; входные данные проверяйте ($request->validate([...])). - Проверяйте права (
current_user_can) на каждой странице и в каждом обработчике, который что-то меняет. - Не храните пароли открытым текстом: для секретов —
Crypt::encryptString().