# Laravel + Vue Ads

Демка · 8 сентября 2026

Laravel API и Vue-клиент реализуют каталог объявлений: список, карточку, создание, удаление, поиск, сортировку и пагинацию. Контракты ответа и ошибок согласованы между слоями; demo CRUD изолирован по сессии, а API и изображения работают с того же домена.

Версия исходников: 54f1be9aa1057163edd9d095d27e8c5451935de7

Backend и Vue-клиент: апрель 2024. Обновление публичного демо: 7 сентября 2026.

## Задача

Публичный запуск требовал исправить base URL, контракты frontend/backend и валидацию форм, а также исключить влияние одного посетителя на данные другого.

Просмотр и размещение объявлений.

## Выполнено

- Laravel API и Vue-клиент.
- Правки контрактов списка, карточки, описания и изображений.
- Обновление до Laravel 12, валидация, signed cookie и CRUD с ограничениями для демки.

## Что отличает реализацию

Один и тот же контракт покрывает desktop и mobile представление, серверную пагинацию и ошибки валидации. Сессия владеет созданными объявлениями, чужая запись возвращает 404, а сброс восстанавливает исходный набор без отдельной административной операции.

## Состав прикладного кода

- Laravel / PHP: 70.7%
- Vue / JavaScript: 16.3%
- Eloquent / MySQL: 13%

Доли по размеру прикладных файлов Git в закреплённой версии. Каждый файл отнесён к одной подсистеме по правилам scripts/generate-stack-share.mjs; тесты, ассеты, зависимости и generated-файлы исключены. Округление — до 0,1%. Это состав кода, а не уровень владения технологиями.

## Стек

| Технология | Роль |
| --- | --- |
| Laravel / Eloquent | Валидация, owner scope, CRUD и expiry. |
| Vue | Маршруты каталога, карточки, формы, сортировки и пагинации. |
| MySQL | Объявления, DECIMAL-цены и срок хранения. |

## Архитектура

- Клиент и API работают на одном origin без внешнего backend URL.
- 24 исходных объявления общие, созданные посетителем записи фильтруются по владельцу.
- Фото выбирается из фиксированных локальных SVG, произвольные URL и mass assignment исключены.
- Цена хранится DECIMAL(10,2), API возвращает согласованный scalar meta для пагинации.

### Компоненты опубликованного демо

![Компоненты опубликованного демо](https://komaroff-dev.ru/evidence/ads/diagrams/components.svg)

[Mermaid](https://komaroff-dev.ru/evidence/ads/diagrams/components.mmd)

### Основной сценарий

![Основной сценарий](https://komaroff-dev.ru/evidence/ads/diagrams/scenario.svg)

[Mermaid](https://komaroff-dev.ru/evidence/ads/diagrams/scenario.mmd)

### Размещение опубликованной версии

![Размещение опубликованной версии](https://komaroff-dev.ru/evidence/ads/diagrams/deployment.svg)

[Mermaid](https://komaroff-dev.ru/evidence/ads/diagrams/deployment.mmd)

### Состав данных и границы хранения

![Состав данных и границы хранения](https://komaroff-dev.ru/evidence/ads/diagrams/data.svg)

[Mermaid](https://komaroff-dev.ru/evidence/ads/diagrams/data.mmd)

## Code-map

| Функция | Экран / API | Модуль | Данные / проверка |
| --- | --- | --- | --- |
| Каталог, поиск, сортировка | AdList / GET api/ad | AdController::index | ads, owner scope |
| Карточка | AdItem / GET api/ad/id | AdController::show | seed или своя запись |
| Создание | AdNew / POST api/ad | Validator, Eloquent | allowlist + session_id + expires_at |
| Удаление и сброс | AdItem / DELETE, POST demo/reset | AdController, DemoSession | только своя сессия |
| Очистка | CLI demo:cleanup | scheduled command | expired rows |

Перед изменением пройти связи экран → API → состояние → хранилище. Проверить входы, ошибки и повторные действия. Обновить карту и схемы вместе с кодом, выполнить связанные проверки и привязать материалы к версии.

## Сценарии

- Откройте каталог, измените сортировку и перейдите на следующую страницу.
- Посмотрите карточку и создайте объявление с локальным изображением.
- Проверьте валидацию пустого/ошибочного ввода.
- Откройте чужой ID во второй сессии: получите 404. Удалите своё объявление и сбросьте пример.

## Проверки

- Повторный полный production QA каталога на /catalog/: создание, удаление, поиск, сортировка, пагинация, сессии и мобильный вид — passed. В исходной Chrome-сессии страница открывается с включённым блокировщиком.
- Sorting, pagination, search, empty state
- Required form validation
- Signed Secure HttpOnly cookie; cross-session GET/DELETE both 404
- Server rejects negative price, short text and external image URL
- Cancel, delete and restored seed count
- Подтверждённого GitHub CI для этого SHA нет; перечислены выполненные локальные проверки и сценарии опубликованной версии. Исторические CI-ссылки, если есть, отмечены отдельно.

[Vue: production-сборка /catalog/](https://github.com/komaroffsergei/laravel-sandbox-ui/actions/runs/34082531195) — ba775c53a6b3b33c1524797390e09a9fb0a432a1, 2026-09-07; исторический запуск.

## Результаты

- Сохранено 13 содержательных кадров фактического интерфейса.
- Дата, сценарий и версия указаны у каждого кадра.
- Максимум RAM контейнеров в коротком тесте: 39.76 MiB. Общие службы учитываются отдельно; магазин включает свою БД.
- Измерено 6 повторений сценария; медиана 1605.5 мс, максимум 2981 мс. Время включает браузер и HTTPS; методика и ограничения приложены.

![Суммарные ресурсы контейнеров проекта · 2026-09-07T01:08:27 — 01:11:22 UTC](https://komaroff-dev.ru/evidence/ads/charts/resources.svg)

[Данные](https://komaroff-dev.ru/evidence/ads/metrics/measurements.json)

![Измеренные повторения сценария через HTTPS · 2026-09-07T01:08:36 UTC; ограничения методики в JSON](https://komaroff-dev.ru/evidence/ads/charts/scenario-time.svg)

[Данные](https://komaroff-dev.ru/evidence/ads/metrics/measurements.json)

## Ограничения

- Все объявления и изображения учебные. Продажи и произвольные загрузки отключены.
- 20 собственных объявлений на сессию, 1000 суммарно; TTL один час и cleanup timer каждые пять минут.
- Legacy инструменты Vue-сборки имеют известные dev-зависимости; полный переход frontend tooling не выполнялся.

## Запуск и эксплуатация

Обновление 7 сентября 2026: frontend опубликован по /catalog/ на основном домене. Старый ads-поддомен перенаправляет сюда, поскольку браузерный блокировщик рекламы блокировал его JS/CSS. Backend Laravel сохранён.

Кейс объединяет laravel-sandbox и laravel-sandbox-ui. Это один проект с двумя репозиториями; SHA обоих сохраняются в release metadata.

Сборка выполняется вне VPS через Dockerfile.portfolio и отдельный build context ads-ui. Версии фиксируются composer.lock и package-lock.json.

Nginx → localhost:18402 → Apache/Laravel. БД ads и пользователь отдельные. Проверять /healthz, GET /api/ad, POST /api/ad, чтение/удаление своего ID. Команда php artisan demo:cleanup вызывается системным таймером; сброс не удаляет seed и чужие записи.

Сборка вне VPS, на сервер уходят готовые файлы и образы с фиксированной версией. Секреты отдельно. Логи ротируются; после изменения log options контейнер нужно пересоздать. Общий docker prune не используется.

Code-map связывает экран или API с модулем и данными. При правке нужно проверить эти связи, обновить карту и прогнать затронутые сценарии: обычный проход, ошибку, повтор, сброс. Схема может устареть, поэтому её версия указана рядом.

Откат проверен 2026-09-07T01:00:33.586236+00:00: 20260907-verified → 20260907b → 20260907-verified. После каждого переключения подтверждены HTTPS, readiness и SHA. Это проверка конфигурации и артефактов на одном проверенном SHA; обратная миграция БД не выполнялась.

## Скриншоты

[Каталог: карточки и сортировка](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/full/01-catalog.png) — 2026-09-07T04:28:20.397008+00:00, ba775c53a6b3b33c1524797390e09a9fb0a432a1.

[Изменение порядка объявлений](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/full/02-sorted.png) — 2026-09-07T04:28:20.909030+00:00, ba775c53a6b3b33c1524797390e09a9fb0a432a1.

[Переход на следующую страницу](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/full/03-page-two.png) — 2026-09-07T04:28:21.390284+00:00, ba775c53a6b3b33c1524797390e09a9fb0a432a1.

[Поиск по названию; на кадре видны введённые параметры, ответ API и итоговое состояние каталога.](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/full/04-search.png) — 2026-09-07T04:28:22.406226+00:00, ba775c53a6b3b33c1524797390e09a9fb0a432a1.

[Пустой результат поиска; на кадре видны введённые параметры, ответ API и итоговое состояние каталога.](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/full/05-empty.png) — 2026-09-07T04:28:23.071492+00:00, ba775c53a6b3b33c1524797390e09a9fb0a432a1.

[Форма создания объявления; на кадре видны введённые параметры, ответ API и итоговое состояние каталога.](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/full/06-new-form.png) — 2026-09-07T04:28:23.520011+00:00, ba775c53a6b3b33c1524797390e09a9fb0a432a1.

[Заполненная форма; на кадре видны введённые параметры, ответ API и итоговое состояние каталога.](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/full/07-filled.png) — 2026-09-07T04:28:24.038342+00:00, ba775c53a6b3b33c1524797390e09a9fb0a432a1.

[Созданное объявление в своей сессии](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/full/08-created.png) — 2026-09-07T04:28:24.690287+00:00, ba775c53a6b3b33c1524797390e09a9fb0a432a1.

[Проверка изоляции объявлений между сессиями](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/full/09-isolation.png) — 2026-09-07T04:28:25.372559+00:00, ba775c53a6b3b33c1524797390e09a9fb0a432a1.

[Подтверждение удаления; на кадре видны введённые параметры, ответ API и итоговое состояние каталога.](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/full/10-delete-confirm.png) — 2026-09-07T04:28:25.856226+00:00, ba775c53a6b3b33c1524797390e09a9fb0a432a1.

[Каталог на мобильном экране; на кадре видны введённые параметры, ответ API и итоговое состояние каталога.](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/full/11-mobile-catalog.png) — 2026-09-07T04:28:26.494282+00:00, ba775c53a6b3b33c1524797390e09a9fb0a432a1.

[Мобильная карточка объявления](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/full/12-mobile-card.png) — 2026-09-07T04:28:26.916150+00:00, ba775c53a6b3b33c1524797390e09a9fb0a432a1.

[Мобильная форма; на кадре видны введённые параметры, ответ API и итоговое состояние каталога.](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/full/13-mobile-form.png) — 2026-09-07T04:28:27.341269+00:00, ba775c53a6b3b33c1524797390e09a9fb0a432a1.

[Материалы](https://komaroff-dev.ru/evidence/ads/revision-ba775c53/materials.zip)
