Skip to content

07Rinat07/task-2_laravel

Repository files navigation

Подборка квартир (Laravel 10)

Описание проекта

Проект реализует подборки квартир с веб-страницей, фильтрами, ценами, галереей изображений и 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, Events
  • database/ — миграции и сиды
  • resources/views/ — Blade
  • public/style.css и изображения
  • tests/ — Unit/Feature/Integration

Запуск локально

  1. Установка зависимостей:
composer install
  1. Настройка окружения:
cp .env.example .env
php artisan key:generate
  1. Настроить параметры БД в .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
  1. Миграции и сиды:
php artisan migrate --seed
  1. Запуск:
php artisan serve

Адрес проекта: http://localhost:8000/ Пример подборки: http://localhost:8000/offers/demo-8f4c2d1e9a51a2b3c4d5e6f7a8b9c0d1

Запуск в Docker

Docker дает одинаковое окружение для Windows/macOS/Linux.

  1. Запустить контейнеры:
docker compose up --build -d
  1. Адрес проекта: 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 (prod)

docker compose -f docker-compose.prod.yml up --build -d

Адрес проекта: http://localhost:8080/ Пример подборки: http://localhost:8080/offers/demo-8f4c2d1e9a51a2b3c4d5e6f7a8b9c0d1

Очереди (webhooks)

В Docker воркер запускается сервисом queue. Локально:

php artisan queue:work --queue=webhooks

Проверка воркера (локально или в Docker):

  1. Установить WEBHOOK_URL и включить WEBHOOK_ENABLED=true.
  2. Запустить воркер (queue:work или сервис queue в Docker).
  3. Вызвать тестовый 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"}'

Healthcheck

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
  • Лайки доступны только авторизованным пользователям.

Swagger

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 эндпоинты

Все 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) для уведомлений внешних систем.
  • Отдельные таблицы статистики для аудита просмотров и лайков.

Возможные точки расширения

  • Добавить историю статусов подборки.
  • Массовый импорт/экспорт квартир.
  • Роли пользователей (менеджер/клиент).

Releases

No releases published

Packages

 
 
 

Contributors