Enterprise-grade Clean Architecture on Yii2 Framework • PHP 8.5
🏛 Clean Architecture • ⚡ CQS Pattern • 📨 Domain Events
🎯 Value Objects • 🔄 Async Fan-out • 🚦 Status FSM
Этот проект - практическая реализация каталога книг на базе Yii2 и PHP 8.5. Используется Clean Architecture, демонстрирующая возможности написания масштабируемого кода на классическом фреймворке.
Принято считать, что AI-агенты лучше «дружат» с Python или Laravel. Этот проект показал обратное - классический Yii2 тоже позволяет внедрять современные инженерные стандарты. На «олдскульном» фреймворке можно работать качественно и актуально, используя нейросети как инструмент.
Главная цель - отделить бизнес-логику от фреймворка, добавить строгую типизацию и сделать асинхронные процессы надежными. Yii2 в полной мере используется для веба и базы данных, но Use Cases и порты удерживаются в изоляции. Так код получается чистым, понятным и на 100% покрытым тестами.
📋 Подробная история изменений доступна в CHANGELOG.md.
🏗 Архитектурные решения и диаграммы - docs/ARCHITECTURE.md
🆚 Сравнение подходов (Yii2 MVC и Clean Architecture) - docs/COMPARISON.md
📖 Изучение проекта - пошаговое руководство от проблем классического Yii2 до Clean Architecture docs/learning.md
🧾 Автособираемая документация - актуальные отчеты и сводки по коду docs/generated
🤯 Зачем так сложно?
Этот проект - Architectural Showcase. Он показывает, что Yii2 может быть и «быстрым стартом» для новичков, и фундаментом для серьезных систем. Главное - правильно его «приготовить», добавив Clean Architecture, DDD и SOLID.
Здесь всё серьезно. Deptrac и Arkitect следят, чтобы слои не перемешивались, Infection проверяет качество тестов, а PHPStan на максималках (Level 9 + 10 кастомных правил) ловит даже малейшие неточности.
🦖 Зачем взял этого "динозавра" (Yii2)?
Многие считают Yii2 устаревшим, но проект показывает крутой симбиоз - проверенное временем ядро плюс возможности PHP 8.5 (Enums, Readonly, Attributes). «Магия» глобальных переменных полностью убрана, управлением занимается Dependency Injection. Код честный - если классу что-то нужно, он запрашивает это в конструкторе.
🧠 Это просто генерация от AI?
Нет. Немаловажную часть кода написали автономные AI-агенты, работающие прямо в терминале под полным контролем. Они используются как мощный «экзоскелет» - агенты пишут код по строгим правилам и контрактам, с проверкой и направлением каждого решения. Это пример того, как Senior + AI могут строить качественную архитектуру в разы быстрее, сохраняя контроль над качеством.
🤔 А есть подвох?
Без него никак. Добавлен здоровый прагматизм, чтобы проект не стал «академически правильным, но бесполезным в жизни».
ActiveRecordсохранен в инфраструктуре, кастомные решения для БД не создавались. Где фреймворк реально экономит время (формы, роутинг, запросы к БД) - он используется.Но есть важное правило - фреймворк заперт внутри инфраструктуры. Он инструмент, а не основа. Бизнес-логика вообще не знает о его существовании. Подробнее про эти решения и осознанные компромиссы - docs/DECISIONS.md
- ✨ Ключевые особенности
- 🆚 Сравнение подходов
- 🚀 Установка и запуск
- ⚙️ Конфигурация
- 🛠 Технический стек
- 🧪 Тестирование
- 📂 Структура проекта
| 🏛️ Архитектура | ⚡ Производительность |
|---|---|
| 🔹 Clean Architecture Компромисс между чистотой и прагматизмом |
🚀 Async Fan-out Паттерн для масштабируемых уведомлений |
| 🔹 Паттерн CQS Разделение команд и запросов |
🔍 Гибридный поиск FullText + откат к LIKE |
🔹 Value ObjectsIsbn, BookYear, BookStatus, Phone, AuthorId, StoredFileReference |
🛡 Idempotency + Mutex Защита от дублей без гонок |
| 🔹 🚦 Status FSM Конечный автомат статусов книги |
⚡ HTMX Infinite Scroll и реактивные формы |
| 🔹 📦 CAS (File Storage) Контентно-адресуемое хранилище |
📈 Observability Structured Logging + Inspector APM |
🔹 Доменные событияBookStatusChangedEvent, BookUpdatedEvent, BookDeletedEvent |
🩺 Эндпоинт здоровья (Health Check) Prod-readiness /health |
| 🧪 Качество кода | 🐳 DevOps Ready |
| ✅ 1006+ тестов (2400+ assertions) 100% покрытие кода тестами |
🐳 Docker Compose Полный стек одной командой |
| ✅ PHPStan Level 9 10 кастомных правил (Custom Rules) |
🛠 Makefile Автоматизация рутины |
| ✅ Мутационное тестирование Infection PHP (MSI 100%) |
📚 Генерация документации Yii2 API + OpenAPI |
| ✅ Авто-рефакторинг Rector |
🏗 Контроль архитектуры Deptrac + Arkitect |
| Критерий | Yii2 MVC | Yii2 MVC + сервисы | Clean Architecture |
|---|---|---|---|
| Бизнес-логика | Контроллеры и ActiveRecord | Сервисы поверх ActiveRecord | Use Cases и доменные сущности |
| Зависимости | Yii::$app |
Yii::$app |
Порты и DI |
| Тестируемость | Сложно | Сложно | Легко |
Подробное сравнение: docs/COMPARISON.md
# 1. Клонируем проект
git clone https://github.com/WarLikeLaux/yii2-book-catalog.git
cd yii2-book-catalog
# 2. Установка (интерактивно)
make install
# или принудительно (без вопросов):
make install-force
# 3. Готово! 🎉
open http://localhost:8000💡 Что делает
make install:
- 🐳 Поднимает Docker контейнеры (PHP 8.5 + MySQL 8 / PgSQL + воркер очереди)
- 📦 Устанавливает Composer зависимости
- 🗄 Применяет миграции БД
- 🌱 Наполняет базу демо-данными
🔑 Тестовые учётные данные
| Логин | Пароль |
|---|---|
admin |
admin |
demo |
demo |
Приложение будет доступно по адресу: http://localhost:8000
Весь проект управляется через Makefile. Запустите make help, чтобы увидеть полный список команд (более 30 утилит).
Самые важные:
make install # полная установка и запуск 🚀
make test # запуск основных тестов (Unit + Integration) 🧪
make dev # авто-фикс стиля и статический анализ 🛡️
make up # управление контейнерами (up/down) 🐳Все настройки приложения вынесены в файл .env. При установке (make install) он создается автоматически из .env.example.
| Переменная | Значение по умолчанию | Описание |
|---|---|---|
YII_ENV |
dev |
Окружение: dev, prod, test |
YII_DEBUG |
true |
Включить режим отладки Yii2 |
SMS_API_KEY |
MOCK_KEY |
Ключ для SMS шлюза. MOCK_KEY пишет SMS в лог. |
В проекте реализована горячая смена драйвера БД.
| Переменная | Значение | Описание |
|---|---|---|
DB_DRIVER |
mysql / pgsql |
Выбор активной базы данных |
DB_NAME |
yii2basic |
Имя базы данных |
DB_USER |
yii2 |
Пользователь БД |
DB_PASSWORD |
secret |
Пароль пользователя |
MYSQL_PUBLIC_PORT |
33060 |
Внешний порт MySQL (доступ с хоста) |
PGSQL_PUBLIC_PORT |
54320 |
Внешний порт PostgreSQL (доступ с хоста) |
| Переменная | Порт | Сервис |
|---|---|---|
APP_PORT |
8000 |
Основной веб-сервер приложения |
SWAGGER_PORT |
8081 |
Swagger UI документация |
REDIS_PUBLIC_PORT |
6379 |
Внешний доступ к Redis |
💡 Совет: Если порты заняты, просто измените их в
.envи перезапустите контейнеры черезmake up.
Если вы не хотите править файлы вручную, запустите мастер настройки:
make env # или make configureСкрипт пошагово спросит все параметры (порты, пароли, драйвер БД) и обновит .env. Это полезно, если на вашем компьютере уже занят порт 8000 или 3306.
Проект демонстрирует, как Clean Architecture превращает тестирование из "рутины" в мощный инструмент быстрой разработки.
Бизнес-логика (Use Cases) полностью отделена от фреймворка и БД - тестируется «чистый PHP», что позволяет выполнять сотни Unit-тестов за миллисекунды. Все зависимости внедряются через конструктор, и тяжелые части (БД, очереди, SMS-шлюзы) легко подменяются на Mocks или In-memory реализации. Отсутствие обращений к Yii::$app в доменном слое делает тесты изолированными и стабильными.
| 1006 Tests |
2400+ Assertions |
100% Coverage |
~14s Runtime |
Отдельный прогон E2E: 17 сценариев (make test-e2e).
- Unit тесты покрывают доменные сущности, Value Objects и Use Cases в полной изоляции.
make test-unit
- Integration тесты проверяют взаимодействие слоев - работу репозиториев с реальной БД (MySQL/PgSQL), маппинг событий в очереди и интеграцию с Yii2 компонентами.
make test-integration
- E2E тесты (17 сценариев) имитируют действия пользователя в браузере - создание книги, публикация, подписка. Прогон выполняется отдельно.
make test-e2e
Помимо покрытия строк (Line Coverage) выполняется Infection Testing - «тестирование тестов». Infection вносит ошибки в исходный код (мутанты) и проверяет, "заметят" ли это тесты. Mutation Code Coverage 100% и MSI (Mutation Score Indicator) 100% означают, что большая часть изменений логики не пройдет незамеченной.
make test-infectionsrc/domain/ - Слой домена (Business Logic)
├── common/ - Общие доменные элементы
├── entities/ - Сущности (Rich Model)
├── events/ - Domain Events
├── exceptions/ - Исключения домена
├── repositories/
├── services/ - Domain Services (редко)
├── specifications/ - Specifications (criteria)
├── values/ - Value Objects (Immutable)
src/application/ - Слой приложения (Application Logic)
├── common/ - Общие DTO и валидаторы
├── ports/ - Интерфейсы (Ports)
├── {{module}}/
│ ├── commands/ - DTO команд (Write)
│ ├── exceptions/ - Исключения модуля
│ ├── factories/ - Фабрики модуля
│ ├── mappers/ - Mappers модуля
│ ├── queries/ - DTO чтения (Read), DTO-only: final readonly, без infra
│ ├── usecases/ - Классы Use Case (execute)
src/infrastructure/ - Инфраструктурный слой (Framework Logic)
├── adapters/ - Адаптеры инфраструктуры
├── components/ - Вспомогательные компоненты
├── factories/ - Фабрики инфраструктуры
├── listeners/ - Event Listeners
├── mapping/ - Настройки маппинга
├── persistence/ - ActiveRecord модели (Mapping)
├── phpstan/ - Расширения и правила PHPStan
├── queries/ - Query Services
├── queue/ - Обработчики очередей
├── repositories/ - Реализации Repository (через AR)
├── services/ - Внешние сервисы
src/presentation/ - Слой представления (UI/API)
├── common/ - Общие компоненты
├── components/ - UI компоненты
├── controllers/ - Общие контроллеры
├── dto/ - DTO уровня представления
├── mail/ - Шаблоны писем
├── services/ - Общие сервисы представления
├── views/ - Шаблоны представлений
├── widgets/ - UI виджеты
├── {{module}}/
│ ├── dto/ - DTO уровня представления
│ ├── forms/ - Формы валидации
│ ├── handlers/ - Обработчики запросов
│ ├── mappers/ - Mappers модуля
│ ├── services/ - Сервисы модуля
│ ├── validators/ - Валидаторы модуля
│ ├── widgets/ - Виджеты модуля
assets/ - Frontend assets
bin/ - CLI утилиты
├── lib/ - Библиотеки CLI утилит
commands/ - Console контроллеры
├── support/ - Служебные утилиты и вывод карты проекта
config/ - Конфигурация приложения
├── container/ - Конфигурация контейнера зависимостей
docker/ - Docker конфигурация
├── nginx/ - Конфигурация nginx
docs/ - Документация
├── ai/ - Правила и инструкции для AI
├── generated/ - Автоматизированные материалы
messages/ - Переводы i18n
migrations/ - Миграции БД
runtime/ - Runtime кэш и логи
tests/ - Тесты
tools/ - Инструменты разработки
├── PHPUnit/ - Конфигурация PHPUnit
├── Rector/ - Конфигурация Rector
web/ - Web root
Список модулей:
| Модуль | Назначение |
|---|---|
| auth | Авторизация и сессии |
| authors | Управление авторами |
| books | Каталог книг |
| reports | Аналитические отчеты |
| subscriptions | Подписки на уведомления |
Независимы от Yii: application/ и domain/.
Зависят от Yii: infrastructure/ и presentation/.