Проект реализует подборки квартир с веб-страницей, фильтрами, ценами, галереей изображений и REST API. Лайки — персональные, доступные только авторизованным пользователям. Webhook-уведомления отправляются через очередь. Архитектура разделена на слои (Controller -> UseCase -> Domain -> Repository -> Infrastructure).
- Laravel 10, PHP 8.x, Composer
- База данных PostgreSQL (настройки через env)
- Таблица
offersсо всеми полями из ТЗ - Таблица
offer_itemsсо всеми полями из ТЗ - Наполнение тестовыми данными (сиды)
- Страница отображения подборки по верстке
- REST API для создания/обновления подборки
- REST API для создания/удаления элемента подборки
- Запрет добавления элементов при статусе != "Новая"
- Сложный URL через
public_token - Сбор статистики посещений и отметок "Нравится"
- Защита API токеном
- События для оповещения внешних систем
- Тесты: Unit, Integration, Feature
- Цена квартиры и фильтрация
- Несколько изображений/галерея
- Очереди для webhook-уведомлений
- Авторизация и персональные лайки
- Controller: принимает HTTP-запрос, не содержит бизнес-логики.
- UseCase: бизнес-логика (создание/обновление/валидация правил).
- Domain: сущности, value objects, доменные исключения.
- Repository: интерфейсы и реализация работы с БД.
- Infrastructure: PDO/Eloquent, middleware, внешние сервисы.
- DTO/View: входные/выходные структуры данных.
app/— Domain, Application, Infrastructure, Controllers, Eventsdatabase/— миграции и сидыresources/views/— Bladepublic/—style.cssи изображенияtests/— Unit/Feature/Integration
- Установка зависимостей:
composer install- Настройка окружения:
cp .env.example .env
php artisan key:generate- Настроить параметры БД в
.env(PostgreSQL):
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=offers_db
DB_USERNAME=offers_user
DB_PASSWORD=secret
- Миграции и сиды:
php artisan migrate --seed- Запуск:
php artisan serveАдрес проекта: http://localhost:8000/
Пример подборки: http://localhost:8000/offers/demo-8f4c2d1e9a51a2b3c4d5e6f7a8b9c0d1
Docker дает одинаковое окружение для Windows/macOS/Linux.
- Запустить контейнеры:
docker compose up --build -d- Адрес проекта:
http://localhost:8000/Пример подборки:http://localhost:8000/offers/demo-8f4c2d1e9a51a2b3c4d5e6f7a8b9c0d1
Параметры Docker окружения лежат в .env.docker. При необходимости:
- Указать
APP_KEY(если нужен фиксированный ключ). ЕслиAPP_KEYпустой, контейнер сгенерирует ключ автоматически. - Изменить
API_TOKENдля REST API. - Отключить сиды/миграции на старте:
SEED_ON_START=false,MIGRATE_ON_START=false. - После обновления миграций выполнить:
docker compose exec app php artisan migrate.
docker compose -f docker-compose.prod.yml up --build -dАдрес проекта: http://localhost:8080/
Пример подборки: http://localhost:8080/offers/demo-8f4c2d1e9a51a2b3c4d5e6f7a8b9c0d1
В Docker воркер запускается сервисом queue.
Локально:
php artisan queue:work --queue=webhooksПроверка воркера (локально или в Docker):
- Установить
WEBHOOK_URLи включитьWEBHOOK_ENABLED=true. - Запустить воркер (
queue:workили сервисqueueв Docker). - Вызвать тестовый webhook:
curl -X POST http://localhost:8000/api/v1/webhooks/test \
-H "X-API-TOKEN: change_me" \
-H "Content-Type: application/json" \
-d '{"event":"both"}'http://localhost:8000/health
http://localhost:8080/health
APP_KEY- ключ шифрования Laravel (обязателен).API_TOKEN- токен для REST API (передавать вX-API-TOKENили Bearer).WEBHOOK_URL- URL внешней системы для событий.WEBHOOK_ENABLED- включение уведомлений (true/false).QUEUE_CONNECTION- драйвер очереди (для webhook используетсяdatabase).APP_ENV,APP_DEBUG- разделение dev/prod.
По умолчанию тесты используют .env.testing и SQLite :memory: (без файлов).
php artisan testВ Docker:
docker compose exec app php artisan testТестовый конфиг форсируется для изоляции от Docker окружения.
При необходимости можно переопределить тестовую БД через переменные окружения.
Smoke-тесты проверяют доступность страниц /offers/{token} и /api/documentation.
Для страницы:
/offers/{token}?price_min=&price_max=&square_min=&square_max=&type=&complex=
Для API:
/api/v1/offers/{token}?price_min=&price_max=&square_min=&square_max=&type=&complex=
Пользователь для входа:
- Email:
demo@local.test - Пароль:
passwordЕсли пользователь не создан, выполните:php artisan db:seed --class=UserSeederВ Docker:docker compose exec app php artisan db:seed --class=UserSeeder
- Вход:
GET /login - Выход:
POST /logoutилиGET /logout - Лайки доступны только авторизованным пользователям.
UI: http://localhost:8000/api/documentation
JSON: http://localhost:8000/docs
Prod UI: http://localhost:8080/api/documentation
Prod JSON: http://localhost:8080/docs
Генерация вручную:
php artisan l5-swagger:generateВ Docker:
docker compose exec app php artisan l5-swagger:generateВсе API защищены заголовком X-API-TOKEN: <token> или Bearer.
POST /api/v1/offers— создать подборкуPUT /api/v1/offers/{id}— обновить подборкуGET /api/v1/offers/{token}— получить подборку с фильтрамиPOST /api/v1/offer-items— создать элемент подборкиDELETE /api/v1/offer-items/{id}— удалить элемент подборкиPOST /api/v1/webhooks/test— тестовый webhook
Фильтры (query params): price_min, price_max, square_min, square_max, type, complex.
- SQL Injection: Eloquent + prepared statements.
- XSS: экранирование вывода в Blade (
{{ }}). - CSRF: формы на веб-странице защищены
@csrf. - API защита: токен из env, проверка
hash_equals. - Ошибки: доменные исключения без stack trace в ответах API.
- public_token как сложный URL для защиты от перебора ID.
- UseCase-слой отделяет бизнес-логику от контроллеров.
- События (OfferViewed, OfferItemLiked) для уведомлений внешних систем.
- Отдельные таблицы статистики для аудита просмотров и лайков.
- Добавить историю статусов подборки.
- Массовый импорт/экспорт квартир.
- Роли пользователей (менеджер/клиент).