Skip to content

DreamerView/mini-cms

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mini Headless CMS

Лёгкая headless CMS на PHP, которую можно развернуть одним файлом на обычном shared-хостинге.

PHP API Database Bootstrap

Mini Headless CMS — компактная CMS для сайтов, лендингов, каталогов и небольших веб-проектов. Административная панель, схема контента, формы, REST-подобный JSON API и системные инструменты находятся в одном PHP-файле.

Проект ориентирован на разработчиков, которым нужна простая CMS без Composer, Node.js, отдельного backend-приложения и обязательного VPS.

Содержание

Основные возможности

Простое развёртывание

  • основная CMS поставляется одним PHP-файлом;
  • не требует Composer и сборки frontend;
  • работает с SQLite или MySQL;
  • автоматически создаёт конфигурацию, таблицы, служебные каталоги и индексы;
  • включает мастер первоначальной настройки;
  • подходит для обычного PHP-хостинга.

Проекты и контент

  • несколько независимых проектов в одной установке;
  • разделы контента, объединяющие несколько коллекций;
  • глобальные и вложенные коллекции;
  • коллекции типов Single и Multiple;
  • один уровень вложенных коллекций;
  • готовые пресеты: страница, блог, товар, FAQ и контакты;
  • черновики и опубликованные записи;
  • автоматическое сохранение редактора;
  • история версий и восстановление предыдущего состояния;
  • клонирование коллекций;
  • импорт и экспорт схем коллекций;
  • избранные коллекции и список недавних записей.

Типы полей

  • Text;
  • текст без перевода;
  • Textarea;
  • HTML;
  • Email;
  • Телефон;
  • Number и Integer;
  • Date и Datetime;
  • Boolean;
  • URL;
  • Image и File;
  • JSON;
  • маркированные и нумерованные списки;
  • переводимые списки;
  • связь с глобальной коллекцией;
  • связь с вложенной коллекцией.

Для полей поддерживаются обязательность, значения по умолчанию, минимальная и максимальная длина, числовые границы, регулярные выражения, список разрешённых значений и проверка уникальности.

Интернационализация

  • интерфейс CMS на русском, казахском и английском языках;
  • одноязычный и мультиязычный режим контента;
  • поддержка 15 языков контента;
  • отдельные переводы для Text, Textarea и переводимых списков;
  • переводы названий полей форм и сообщений после успешной отправки;
  • получение нужного языка через параметр API lang.

Файлы

  • единый файловый менеджер проекта;
  • изображения и документы;
  • контроль расширений и MIME-типа;
  • максимальный размер файла по умолчанию — 10 МБ;
  • отслеживание используемых и неиспользуемых файлов;
  • корзина проекта и глобальная корзина;
  • очистка неиспользуемых файлов.

Формы

  • создание публичных endpoint-форм;
  • получение JSON-схемы формы через GET;
  • отправка через JSON, application/x-www-form-urlencoded или multipart/form-data;
  • серверная валидация типов и правил;
  • защита honeypot и ограничение частоты запросов;
  • статусы заявок: новая, прочитанная, спам;
  • массовые операции;
  • экспорт заявок в CSV и JSON;
  • автоматическое хранение заявок: бессрочно, 30, 90, 180 или 365 дней;
  • уведомления на email;
  • подписанный webhook;
  • уведомления в Telegram.

Управление и контроль

  • четыре роли пользователей;
  • права на уровне проекта;
  • журнал действий;
  • встроенная диагностика установки;
  • резервное копирование и восстановление проектов;
  • настройка CORS;
  • светлая и тёмная темы;
  • API Explorer;
  • режим отладки для разработки.

Системные требования

Обязательно

  • PHP 8.1 или новее;
  • PDO;
  • JSON;
  • OpenSSL;
  • Fileinfo;
  • Mbstring;
  • один из драйверов:
    • pdo_sqlite;
    • pdo_mysql;
  • права на запись в каталоги storage и uploads.

Для отдельных функций

  • ZipArchive — резервное копирование и восстановление;
  • cURL или разрешённый file_get_contents() для внешних URL — webhooks и Telegram;
  • настроенная функция mail() — email-уведомления;
  • HTTPS — настоятельно рекомендуется для рабочей установки.

Для загрузки файлов размером до 10 МБ значения upload_max_filesize и post_max_size в php.ini должны быть не меньше 10 МБ.

Установка

1. Разместите CMS на сервере

Скопируйте основной PHP-файл проекта в отдельный каталог сайта. При необходимости переименуйте его в index.php.

Пример:

public_html/
└── cms/
    └── index.php

2. Проверьте права

PHP должен иметь возможность создавать и изменять:

storage/
uploads/

Обычно достаточно прав 775 для каталогов. Не устанавливайте 777, если хостинг не требует этого явно.

3. Откройте CMS в браузере

https://example.com/cms/

Мастер установки предложит:

  1. выбрать язык и тему интерфейса;
  2. включить или отключить мультиязычный контент;
  3. выбрать SQLite или MySQL;
  4. проверить подключение к базе данных;
  5. создать первого администратора.

SQLite

SQLite выбран по умолчанию. Файл базы создаётся автоматически:

storage/cms.sqlite

MySQL

База данных должна быть создана заранее. В мастере установки укажите:

  • host;
  • database;
  • username;
  • password.

Таблицы и индексы CMS создаст самостоятельно.

Структура файлов

После первого запуска структура будет выглядеть примерно так:

cms/
├── index.php
├── storage/
│   ├── .htaccess
│   ├── index.html
│   ├── config.json
│   ├── cms.sqlite
│   ├── login_attempts.json
│   └── cache/
└── uploads/

При использовании MySQL файл cms.sqlite не нужен.

storage/config.json содержит настройки подключения и установки. Не публикуйте его и не добавляйте в открытый репозиторий вместе с реальными учётными данными.

Защита storage в Nginx

CMS автоматически создаёт .htaccess для Apache. Nginx не обрабатывает .htaccess, поэтому доступ нужно запретить в конфигурации сервера:

location ^~ /cms/storage/ {
    deny all;
    return 404;
}

Роли и права

Роль Возможности
Administrator Полный доступ ко всем проектам, пользователям, журналу, диагностике и системным операциям
Developer Схемы коллекций, разделы, настройки, API, ключи доступа и конфигурация форм
Editor Записи, файлы, публикация контента и обработка заявок форм
Viewer Просмотр контента без права изменения

Администратор является глобальной ролью. Для остальных пользователей роль назначается отдельно в каждом проекте.

Модель контента

Проект
├── Раздел контента
│   ├── Коллекция
│   └── Коллекция
├── Коллекция без раздела
├── Вложенная коллекция
├── Формы
└── Файлы

Одна коллекция может быть подключена к нескольким разделам. Удаление связи с разделом не удаляет саму коллекцию.

Вложенная коллекция принадлежит родительской коллекции, хранит отдельные записи для каждой родительской записи и поддерживает только один уровень вложенности.

API

Текущая версия API: 1.4.

API отдаёт только опубликованный контент. Изменение контента выполняется через административную панель.

Базовый запрос

GET https://example.com/cms/?api=index&project=my-project

Параметр project принимает slug проекта. В установке с одним проектом может использоваться проект по умолчанию, однако явное указание slug делает интеграцию предсказуемее.

Основные endpoint-ы

Endpoint Назначение
?api=index&project=PROJECT Информация об API и доступных маршрутах
?api=entries&project=PROJECT&c=COLLECTION Опубликованные записи коллекции
?api=entry&project=PROJECT&c=COLLECTION&s=ENTRY Одна запись по slug
?api=group&project=PROJECT&g=GROUP Раздел вместе с подключёнными коллекциями
?api=collections&project=PROJECT Список коллекций для авторизованного Developer/Admin
?api=groups&project=PROJECT Список разделов для авторизованного Developer/Admin
?api=fields&project=PROJECT&c=COLLECTION Поля коллекции для авторизованного Developer/Admin
?api=schema&project=PROJECT&c=COLLECTION Схема коллекции для авторизованного Developer/Admin
?api=files&project=PROJECT Файлы проекта для авторизованного Editor/Admin
?api=files-trash&project=PROJECT Корзина файлов для авторизованного Editor/Admin

Поддерживаются методы GET, HEAD и OPTIONS.

Параметры выборки

Параметр Пример Описание
lang lang=kk Язык ответа: код языка, default или all
page page=2 Номер страницы
limit limit=25 Размер страницы, максимум 100
q q=automation Полнотекстовый поиск по сериализованным данным ответа
sort sort=-created_at Сортировка; префикс - означает обратный порядок
filter filter[status]=active Фильтрация по системному полю или data.*
fields fields=title,slug,data.price Проекция полей ответа
populate populate=author,category Раскрытие указанных связей
populate populate=all Раскрытие всех связей первого уровня
schema schema=1 Добавление схемы; требует авторизации в CMS

Примеры:

GET /cms/?api=entries&project=site&c=articles&lang=ru&page=1&limit=10&sort=-created_at
GET /cms/?api=entries&project=shop&c=products&filter[data.category]=tools&fields=title,slug,data.price
GET /cms/?api=entry&project=site&c=articles&s=first-post&populate=all

Приватные ресурсы

Коллекцию, раздел или форму можно сделать приватными. Ключ создаётся в административной панели и показывается полностью только один раз.

Передайте его одним из способов:

Authorization: Bearer cms_your_key

или:

X-API-Key: cms_your_key

Пример:

curl \
  -H "Authorization: Bearer cms_your_key" \
  "https://example.com/cms/?api=entries&project=site&c=private-content"

Ключи можно именовать, ограничивать по сроку действия и отзывать. В базе хранится хеш ключа, а не его открытое значение.

Кэширование

Публичные ответы используют:

  • ETag;
  • Last-Modified;
  • условные запросы с ответом 304 Not Modified;
  • файловый response cache;
  • автоматическую инвалидацию при изменении контента.

Приватные ответы возвращаются с Cache-Control: private, no-store.

Вложенные коллекции в API

Вложенные коллекции не публикуются как самостоятельные endpoint-ы и не добавляются в ответы автоматически. Они доступны через поле типа nested_relation и параметр populate.

Публичные формы

Получение схемы

GET https://example.com/cms/?form=contact&project=site&lang=ru

Ответ содержит:

  • данные формы;
  • локализованное название;
  • сообщение об успешной отправке;
  • список полей и правила валидации;
  • URL endpoint-а;
  • поддерживаемые форматы запроса.

Отправка JSON

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Иван",
    "email": "ivan@example.com",
    "message": "Нужна консультация"
  }' \
  "https://example.com/cms/?form=contact&project=site&lang=ru"

Успешный ответ возвращает HTTP 201 Created:

{
  "api_version": "1.4",
  "ok": true,
  "lang": "ru",
  "submission_id": 42,
  "message": "Спасибо! Заявка отправлена."
}

Формы не принимают файлы. Публичный endpoint сохраняет IP, User-Agent и Referer заявки.

Защита форм

  • строгая серверная валидация;
  • отклонение неизвестных или некорректных типов данных;
  • honeypot для автоматического определения спама;
  • не более 20 заявок с одного IP за 10 минут для одной формы;
  • ограничение размера и глубины JSON;
  • публичный CORS согласно настройкам проекта;
  • HMAC-подпись webhook-запросов в заголовке X-CMS-Signature.

Webhook получает событие form.submitted и заголовок:

X-CMS-Signature: sha256=...

Безопасность

В CMS реализованы:

  • пароли через password_hash() и password_verify();
  • минимальная длина пароля 10 символов;
  • CSRF-токены для административных POST-запросов;
  • строгий режим PHP-сессий;
  • cookies с HttpOnly и SameSite=Lax;
  • Secure для session cookie при работе через HTTPS;
  • регенерация session ID после входа;
  • блокировка входа после 5 неудачных попыток на 10 минут;
  • prepared statements через PDO;
  • серверная валидация контента и форм;
  • очистка пользовательского HTML;
  • CORS allowlist на уровне проекта;
  • отдельные API-ключи для коллекций, разделов и форм;
  • срок действия и отзыв API-ключей;
  • журнал действий с пользователем, IP и User-Agent;
  • защитные HTTP-заголовки;
  • автоматическая защита каталога storage для Apache;
  • HMAC SHA-256 для webhook-уведомлений.

Не включайте режим отладки на рабочем сайте: PHP-ошибки могут раскрыть пути, конфигурацию и внутренние данные приложения.

Резервные копии

CMS создаёт ZIP-архив проекта, который включает:

  • проект;
  • коллекции и вложенные коллекции;
  • поля;
  • записи;
  • разделы и связи;
  • формы и поля форм;
  • заявки форм;
  • файлы проекта.

При восстановлении создаётся новый проект, а идентификаторы коллекций, записей, файлов и связей переназначаются автоматически.

Для функции требуется расширение ZipArchive.

Храните резервные копии вне публичного каталога сайта.

Диагностика

Встроенная страница диагностики проверяет:

  • версию PHP;
  • необходимые расширения;
  • выбранный драйвер базы данных;
  • наличие ZipArchive;
  • доступность записи в storage и uploads;
  • наличие config.json;
  • использование HTTPS;
  • защиту каталога storage;
  • значения upload_max_filesize и post_max_size;
  • доступность mail().

Ограничения

  • CMS рассчитана прежде всего на небольшие и средние проекты;
  • публичный контентный API доступен только для чтения;
  • вложенность коллекций ограничена одним уровнем;
  • связи раскрываются на один уровень;
  • публичные формы не поддерживают загрузку файлов;
  • административный интерфейс загружает Bootstrap и Bootstrap Icons через jsDelivr CDN;
  • email-уведомления зависят от конфигурации mail() на сервере;
  • для Nginx защиту storage нужно настроить вручную;
  • single-file архитектура упрощает установку, но требует осторожности при ручном изменении исходного файла.

Обновление

Перед заменой PHP-файла:

  1. скачайте резервные копии проектов;
  2. сохраните каталог storage;
  3. сохраните каталог uploads;
  4. замените основной PHP-файл;
  5. откройте CMS — миграции схемы выполнятся автоматически;
  6. проверьте страницу диагностики.

Не удаляйте storage/config.json, базу данных и uploads во время обновления.

Разработка

Проект не требует отдельной сборки:

PHP 8.1+
HTML5
CSS3
Vanilla JavaScript
Bootstrap 5.3.3
Bootstrap Icons 1.11.3
PDO
SQLite / MySQL

Для локального запуска можно использовать встроенный сервер PHP:

php -S localhost:8000

После запуска откройте:

http://localhost:8000/

Автор

Темирхан Рустемов
DreamerView

GitHub: DreamerView/mini-cms


Mini Headless CMS создаётся как практичный инструмент для разработчиков: минимум требований к серверу, предсказуемая структура данных и быстрый JSON API без лишней инфраструктуры.

About

Минималистичная headless CMS на PHP для быстрого создания API-контента без тяжёлых админ-панелей.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages