SPA-социальная сеть на Laravel + Vue с realtime-чатами, медиа-лентой, интернет-радио, IPTV и административным кабинетом.
Автор проекта: Rinat Sarmuldin
Email: ura07srr@gmail.com
IPTV/Radio: используются открытые источники. Ответственность за соблюдение прав на конкретные потоки лежит на пользователе/владельце инстанса.
- О проекте
- Ключевая функциональность
- Скриншоты интерфейса
- Архитектура
- Методика аналитики
- Безопасность
- Технологический стек
- Быстрый старт
- Переменные окружения
- Тестирование
- API ориентиры
- Swagger / OpenAPI
- Тестовые аккаунты
- Частые проблемы
- Деплой в production
- Лицензия и права использования
Solid Social объединяет классический social feed и realtime-взаимодействие с мультимедийными сценариями:
- социальные публикации с медиа, комментариями, репостами и лайками;
- realtime-чаты с presence-статусами и typing-индикаторами;
- радио и IPTV-плеер (direct/proxy/transcode/relay режимы);
- админ-панель для модерации, настройки и аналитического дашборда;
- lifetime text error log для серверных, клиентских и analytics failure ошибок с просмотром и экспортом из админки;
- серверный heartbeat-трекинг пользовательской активности по модулям;
- клиентский event-трекинг для видео, upload-failure, радио и IPTV;
- мультиязычный интерфейс
RU/ENс SEO URL (/ru/...,/en/...).
- Регистрация, вход, подтверждение email.
- Профиль пользователя, подписки, лента подписок.
- Посты, комментарии, лайки, репосты, просмотры.
- Список комментариев к посту заново запрашивается с сервера при каждом открытии, поэтому новые комментарии и удаления видны разным пользователям без hard refresh.
- Если у поста уже есть комментарии, но они свернуты, карточка показывает отдельную заметную плашку
Показать комментарии, чтобы не пропустить обсуждение. - Загрузка изображений и видео через отдельные API-эндпоинты.
- Поддержка форматов пост-медиа:
jpg/jpeg/png/webp/gif/mp4/webm/mov/m4v/avi/mkv, размер файла до200 MB. - В личном кабинете отображаются очередь загрузки, общий и покомпонентный прогресс, статусы и ошибки по каждому файлу.
- Личные и общие диалоги.
- Presence: кто онлайн на сайте и в конкретном чате.
- Typing indicator через
whisper. - Статусы настроения с настройкой видимости (для всех или скрытие от выбранных участников).
- Архивирование/восстановление чатов, реакции, вложения.
- Удаление сообщений/вложений автором и администратором (через API), синхронизация между страницей чатов и виджетом.
- Транспорт realtime:
Laravel Reverb+pusherprotocol.
- Импорт плейлиста по URL (
m3u/m3u8) и пользовательские сидеры. - Фильтрация каналов по имени/группе, избранное, recent.
- Режимы воспроизведения:
Direct(прямой поток),Proxy(серверный прокси для обхода CORS),Compatibility/Transcode(FFmpeg HLS-подготовка),Relay(ретрансляция с минимальной обработкой).
- Автоочистка и остановка серверных сессий при уходе со страницы.
- Поиск станций через Radio Browser API.
- Встроенные подборки станций по категориям с проверкой доступности потоков.
- Карусели подборок и избранного с режимами
Авто/Вручную, скоростью автодвижения и темамиПрозрачнее/Контрастнее. - Блок "Сейчас играет" со статусом воспроизведения, временем сессии и метаданными станции.
- Синхронизация воспроизведения между страницей радио и виджетом, включая корректный
LIVE-таймер сессии. - Компактный адаптивный режим: на телефонах блок "Сейчас играет" сжат, найденные станции по умолчанию свернуты, а счетчики/чипы и служебные badge усилены по контрасту.
- Избранные станции пользователя с мини-контролом текущего трека (play/pause/seek для не-live потоков).
- Одноразовая команда распределения избранного админов всем не-админам:
php artisan radio:distribute-admin-favorites(--dry-runдля проверки).
- Медиа-карусель.
- Компактная карусель авторов с поиском по имени и никнейму.
- Глобальная кнопка
В началона длинных экранах разделов с адаптивным положением для планшетов и телефонов. - Виджет времени и погоды для городов (Нью-Йорк, Москва, Минск, Астана, Анкара, Уральск).
- Источник погоды:
Open-Meteoчерез серверный запрос. - В админке редактирование контента главной отдельно для
RUиEN.
- Админ-дашборд с KPI, графиками подписок/активности и выбором периода
date_from/date_to(в рамках выбранного года). - Отдельные аналитические секции по удержанию и stickiness, эффективности контента, чатам, медиа/видео, радио, IPTV и ошибкам/модерации.
- Cohort-retention по месяцам регистрации, top posts/authors, reply-time по direct chat, mode split для IPTV и failure rate по transport/media.
- Сравнение предпочтений пользователей по
social/chats/radio/iptv. - Выгрузка фактической аналитики за выбранный диапазон в
Excel (.xls)иJSON(скачивание на локальный компьютер/смартфон через браузер). - Excel-выгрузка теперь включает блоки
Summary,Retention,Retention Cohorts,Content,Top Posts,Top Authors,Chats,Media,Radio,IPTV,Errors / Moderation, а также пользовательскую сводку за период. - Серверный endpoint heartbeat:
POST /api/activity/heartbeat(auth + verified). - Серверный endpoint client analytics:
POST /api/analytics/events(auth + verified). - Публичный endpoint client runtime log:
POST /api/client-errorsс записьюruntime/promise/vue/httpошибок в lifetime text log. - В админке есть preview на dashboard и отдельная вкладка журнала ошибок с поиском, фильтром по типу, пагинацией, filtered export и скачиванием полного
.log. - История журнала не теряется после ротации: старые файлы архивируются, при необходимости сжимаются в
.gz, а поиск/фильтр/экспорт читают и активный лог, и архивы. - Агрегация активности в таблицы:
user_activity_sessions(сессии пользователя по feature),user_activity_daily_stats(дневная агрегированная статистика),analytics_events(клиентские события радио/IPTV/видео/upload-failure).
- Для дашборда автоматически выбирается модель аналитики:
actions(fallback по действиям),time_minutes(если доступны heartbeat-данные за период).
- Локализованные роуты:
/ru/...и/en/.... - Автоматический редирект на язык, если префикс не указан.
- Хранение выбранного языка в
localStorage(solid-social:locale). - Поддержка runtime-перевода legacy-строк.
Актуальная галерея интерфейса. Нажмите на изображение, чтобы открыть полный размер.
Главная / лента |
Чаты |
Радио |
IPTV |
Кабинет пользователя |
Админ-панель |
| Скриншоты открываются в новой вкладке — вернуться можно, просто закрыв её. | ||
Каталог со скриншотами: docs/screenshots/.
| Модуль | Назначение | Точка входа |
|---|---|---|
| Auth + профиль | Регистрация, вход, подтверждение email, кабинет | routes/web.php, routes/api.php |
| Feed / posts | Публикации, лайки, комментарии, репосты, discover | app/Http/Controllers/PostController.php |
| Realtime chat | Диалоги, presence, typing, вложения, архивы | app/Http/Controllers/ChatController.php, routes/channels.php |
| IPTV | Загрузка плейлистов, proxy/transcode/relay сессии | app/Http/Controllers/IptvController.php, app/Services/Iptv* |
| Radio | Поиск, подборки, воспроизведение, избранное и их распределение | app/Http/Controllers/RadioController.php, app/Console/Commands/DistributeAdminRadioFavorites.php |
| Админка | Модерация пользователей/контента/обращений, настройки сайта | /api/admin/*, app/Http/Controllers/AdminController.php |
| Аналитика активности | Heartbeat + client analytics events, дашборд и Excel/JSON export | app/Http/Controllers/ActivityHeartbeatController.php, app/Http/Controllers/AnalyticsEventController.php, app/Services/AdminDashboardService.php, app/Services/AdminDashboardExportService.php |
| Диагностика ошибок | Lifetime log сайта, preview/search/filter/export/download, archive rotation | app/Http/Controllers/SiteErrorLogController.php, app/Services/SiteErrorLogService.php, resources/js/utils/siteErrorReporter.js |
| Контент главной | RU/EN контент, world overview (время/погода) | app/Http/Controllers/SiteSettingController.php, app/Services/WorldOverviewService.php |
| i18n + SEO | RU/EN маршруты, runtime перевод, SEO мета | resources/js/router/index.js, resources/js/i18n |
flowchart LR
U[Browser / Vue SPA] -->|HTTP API + Cookie Session + CSRF| N[Nginx]
U -->|WebSocket (Pusher protocol)| R[Laravel Reverb :6001]
N --> A[Laravel API / PHP-FPM]
A --> DB[(MySQL 8.4)]
A --> F[FFmpeg]
A --> WM[Open-Meteo API]
A --> RB[Radio Browser API]
A <--> R
- Frontend (Vue 3 SPA):
- роутер:
resources/js/router/index.js - представления:
resources/js/views - i18n:
resources/js/i18n
- роутер:
- Backend (Laravel 13):
- HTTP API:
routes/api.php - web/shell:
routes/web.php - broadcast channels:
routes/channels.php - бизнес-логика:
app/Services - валидация/безопасность:
app/Rules,app/Http/Middleware
- HTTP API:
- Realtime:
Laravel Reverb(сервисwebsocketв Docker). - Storage/DB: MySQL + файловое хранилище
storage.
Методика аналитики описана прямо в README, Swagger/OpenAPI и проектном отчете без отдельного markdown-файла.
Что зафиксировано:
- точные таблицы-источники и endpoint-источники;
- формулы всех KPI и блоков
summary,dashboard,retention,content,chats,media,radio,iptv,errors_and_moderation; - логика fallback между heartbeat-метриками и action-based расчётом;
- правила
DAU/WAU/MAU,stickiness, cohort retention,engagement per post,failure rate,mode split; - команды для ручной проверки цифр через
php artisan tinker.
Короткая карта:
GET /api/admin/summaryсчитает прямыеCOUNT(*)из БД.GET /api/admin/dashboardстроит единый payload черезapp/Services/AdminDashboardService.php.GET /api/admin/dashboard/exportэкспортирует тот же payload черезapp/Services/AdminDashboardExportService.php, поэтому экран и Excel/JSON должны совпадать.- Heartbeat хранится в
user_activity_sessionsиuser_activity_daily_stats. - Client analytics events для media/radio/IPTV/video хранятся в
analytics_events.
Важно:
- при наличии heartbeat-данных дашборд переключается на
time_minutes; - без heartbeat включается fallback по действиям;
- transport/media/video блоки зависят от реально отправленных
analytics_events; - demo/seed-данные могут смещать пики по месяцам и retention-картины.
app/
Http/
Services/
Events/
Rules/
resources/js/
views/
components/
router/
i18n/
routes/
tests/Feature/
docker/
Laravel Sanctumв stateful-cookie режиме (EnsureFrontendRequestsAreStateful).- Основные API сгруппированы под
auth:sanctum+verified(подтвержденный email). - Админские маршруты защищены middleware
admin(EnsureUserIsAdmin). - Broadcast-каналы имеют явную авторизацию в
routes/channels.php.
- CSRF защита включена для web-запросов.
- XSRF cookie name вынесен в env (
XSRF_COOKIE), чтобы не конфликтовать между local и Docker. - Сессионный cookie name тоже разделен (
SESSION_COOKIE). - CORS ограничен списком
CORS_ALLOWED_ORIGINS, credentials включены.
- Запросы покрыты FormRequest/валидацией.
- Правило
NoUnsafeMarkupблокирует:- HTML-теги,
- encoded-теги (
<...>), javascript:/vbscript:/ inline handlers,- скрытые управляющие символы.
- Для IPTV URL действует фильтрация:
- только
http/https, - блок private/reserved IP и
localhost.
- только
- Upload-валидация пост-медиа опирается на серверный
MIME/Fileinfo; клиентскийMIMEиспользуется только как fallback для контейнеров вродеmkv, которые браузер может отправлять какapplication/octet-stream. - Файлы, замаскированные под видео, но распознанные сервером как не-media (
application/pdfи т.п.), отклоняются до сохранения.
- API throttling настроен по маршрутам:
- авторизованные API-запросы:
throttle:600,1; - публичные
site/home-contentиsite/world-overview:throttle:240,1;
- авторизованные API-запросы:
- feedback anti-spam:
throttle:20,1; - public client error log:
throttle:30,1наPOST /api/client-errors; - media (
post-images,avatars):throttle:600,1; - IPTV segment/playlist delivery (public relay/proxy/transcode):
throttle:1200,1. - Отправка email verification notification:
throttle:6,1. - Heartbeat endpoint:
throttle:120,1наPOST /api/activity/heartbeat. - Client analytics endpoint:
throttle:240,1наPOST /api/analytics/events. - IPTV сессии ограничены по количеству и TTL (proxy/transcode).
- Backend: PHP
^8.5(Docker: PHP 8.5 FPM), Laravel 13, Sanctum 4, Reverb 1.10, L5 Swagger 11. - Frontend: Node 24, Vue 3.5, Vue Router 5, Axios, Vite 8, Laravel Vite Plugin 3, Tailwind CSS 4.
- Media/Streaming: HLS.js, DASH.js, MPEGTS.js, Plyr, FFmpeg.
- Database: MySQL (Docker:
mysql:8.4). - Infra: Docker Compose (Nginx 1.28 + PHP-FPM + Reverb + MySQL + Node profiles).
- Проверьте локальные версии:
- PHP
8.5(.php-version) - Node
24(.nvmrc) - npm использует проектный cache из
.npmrc, чтобы не зависеть от прав на глобальный cache Windows/OSPanel.
- PHP
- Установите зависимости:
composer installnpm ci
- Создайте
.envиз примера:- Linux/macOS:
cp .env.example .env - PowerShell:
Copy-Item .env.example .env - CMD:
copy .env.example .env
- Linux/macOS:
- Настройте подключение к БД в
.env. - Выполните инициализацию:
php artisan key:generatephp artisan migrate --seed(включая демо-контент: пользователи, посты, комментарии, лайки, изображения)php artisan storage:link
- Запустите процессы:
php artisan servenpm run devphp artisan reverb:start --host=0.0.0.0 --port=6001
- Откройте
http://127.0.0.1:8000.
- Запуск:
- Обязательно создайте отдельный Docker env из шаблона
.env.docker.example:- Linux/macOS:
cp .env.docker.example .env.docker - PowerShell:
Copy-Item .env.docker.example .env.docker -Force - CMD:
copy .env.docker.example .env.docker
- Linux/macOS:
- Не копируйте локальный
.envв.env.docker: для Docker здесь нужныDB_HOST=dbи переменные инициализации MySQL (MYSQL_DATABASE,MYSQL_USER,MYSQL_PASSWORD,MYSQL_ROOT_PASSWORD). docker compose up -d --build- Если порты заняты, задайте forward-порты перед запуском (PowerShell):
$env:WEB_FORWARD_PORT=8081; $env:DB_FORWARD_PORT=3308; $env:VITE_FORWARD_PORT=5174; $env:REVERB_FORWARD_PORT=6002; docker compose up -d --build
- Обязательно создайте отдельный Docker env из шаблона
- Проверка:
docker compose psdocker compose top websocket
- Откройте
http://localhost:8080.
В Docker:
- миграции запускаются автоматически (
RUN_MIGRATIONS=1); - при пустой БД (например после
docker compose down -v) сиды запускаются автоматически (RUN_SEEDERS_ON_EMPTY_DB=1); - если нужны реальные demo-фото в seed-постах, включите
DEMO_SEED_USE_REMOTE_IMAGES=1в.env.dockerи затем повторно запуститеdocker compose exec --user=www-data app php artisan db:seed --class=DemoSocialContentSeeder --force; ffmpegуже установлен в образеapp;- отдельный websocket сервис поднимает Reverb на
6001. - Node-сервисы используют кастомный образ
docker/node/Dockerfileна базеnode:24-alpineсgit/openssh-client, чтобыnpm ciвоспроизводимо ставил GitHub-зависимостьmpegts.js. - Docker-шаблон использует
CACHE_DRIVER=file, чтобыwebsocket/Reverb не зависел от таблицыcacheи доступности MySQL при старте. - при первом запуске зависимости (
composer/npm) могут ставиться несколько минут, это нормально. frontend-buildэто одноразовый сервис сборки ассетов, поэтому состояниеExited (0)для него нормально;- runtime-директории Laravel (
bootstrap/cache,storage/framework/*) вынесены в named volumes, чтобы уменьшить лаги на Windows/macOS/Linux bind-mount.
- Миграции вручную:
docker compose exec --user=www-data app php artisan migrate --seed - Сиды:
docker compose exec --user=www-data app php artisan db:seed - Демо-наполнение соцконтентом:
docker compose exec --user=www-data app php artisan db:seed --class=DemoSocialContentSeeder - Наполнение IPTV каналов:
docker compose exec --user=www-data app php artisan db:seed --class=IptvSeedSeeder - Проверка раздачи радио-избранного админа:
docker compose exec --user=www-data app php artisan radio:distribute-admin-favorites --dry-run - Тесты (без пересборки):
docker compose --profile test run --rm --no-build test - Тесты (с пересборкой test image):
docker compose --profile test run --rm --build test - Логи:
docker compose logs --tail=100 app - Остановка:
docker compose down
- App:
http://localhost:8080(переменнаяWEB_FORWARD_PORT) - Vite dev (
profile dev):http://localhost:5173(переменнаяVITE_FORWARD_PORT) - Reverb websocket:
ws://localhost:6001(переменнаяREVERB_FORWARD_PORT) - MySQL с хоста:
127.0.0.1:3307(переменнаяDB_FORWARD_PORT) - MySQL внутри сети Docker:
db:3306
- Локальный режим: используйте
.env(из.env.example). - Docker режим: сервисы используют
${DOCKER_ENV_FILE}; рекомендуемый рабочий файл.env.docker, шаблон.env.docker.example. - Не смешивайте local и docker cookies/домены в одном браузерном контексте.
- Если меняете cache backend для Docker на
databaseилиredis, он должен быть доступен иapp, иwebsocket; дляdatabaseтакже нужны таблицыcache/cache_locks.
- Приложение:
APP_ENV,APP_DEBUG,APP_URL - База:
DB_CONNECTION,DB_HOST,DB_PORT,DB_DATABASE,DB_USERNAME,DB_PASSWORD - Инициализация MySQL в Docker:
MYSQL_DATABASE,MYSQL_USER,MYSQL_PASSWORD,MYSQL_ROOT_PASSWORD - Безопасность/сессия:
SANCTUM_STATEFUL_DOMAINS,CORS_ALLOWED_ORIGINS,SESSION_COOKIE,XSRF_COOKIE,VITE_XSRF_COOKIE_NAME - Realtime:
REVERB_*,VITE_REVERB_* - IPTV:
IPTV_FFMPEG_BIN - Radio API:
RADIO_BROWSER_BASE_URL - Lifetime error log:
SITE_ERROR_LOG_PATH,SITE_ERROR_LOG_ARCHIVE_PATH,SITE_ERROR_LOG_ROTATE_MAX_BYTES,SITE_ERROR_LOG_ROTATE_MAX_AGE_DAYS,SITE_ERROR_LOG_ARCHIVE_COMPRESS - Docker Compose (host only):
WEB_FORWARD_PORT,DB_FORWARD_PORT,VITE_FORWARD_PORT,REVERB_FORWARD_PORT,APP_HEALTHCHECK_START_PERIOD,RUN_MIGRATIONS,RUN_SEEDERS_ON_EMPTY_DB,DEMO_SEED_USE_REMOTE_IMAGES - Docker env selector:
DOCKER_ENV_FILE(например.env.docker)
Локально:
- Все тесты:
php artisan test - Feature suite:
php artisan test --testsuite=Feature - Rate limit и anti-spam:
php artisan test tests/Feature/ApiRateLimitFeatureTest.php - Login lockout/retry-after:
php artisan test tests/Feature/LoginThrottleFeatureTest.php - Медиа (доступ, fallback, cache-bust query):
php artisan test tests/Feature/MediaPostFeatureTest.php - Heartbeat трекинг:
php artisan test tests/Feature/ActivityHeartbeatFeatureTest.php - Дашборд/экспорт админ-аналитики:
php artisan test tests/Feature/AdminAndChatFeatureTest.php - Lifetime error log, фильтры, export и archive rotation:
php artisan test tests/Feature/SiteErrorLogFeatureTest.php - Сид демо-контента:
php artisan test tests/Feature/DemoSocialContentSeederFeatureTest.php - IPTV:
php artisan test tests/Feature/IptvFeatureTest.php - IPTV Админка (Сидеры):
php artisan test tests/Feature/AdminIptvSeedFeatureTest.php - Чаты и realtime:
php artisan test tests/Feature/ChatFeatureTest.php - Broadcast channels:
php artisan test tests/Feature/BroadcastChannelsFeatureTest.php - Swagger/OpenAPI:
php artisan test tests/Feature/SwaggerDocumentationFeatureTest.php - Админка:
php artisan test tests/Feature/AdminPanelFeatureTest.php,php artisan test tests/Feature/AdminAndChatFeatureTest.php - JS unit-тесты helper-логики (
radio,iptv,avatar search,section top button):npm run test:js - Фронт-билд:
npm run build
В Docker:
- Все тесты (одноразовый test-контейнер):
docker compose --profile test run --rm --no-build test - Все тесты (в запущенном app-контейнере):
docker compose exec --user=www-data app php artisan test - Feature suite:
docker compose exec --user=www-data app php artisan test --testsuite=Feature - Конкретный файл тестов:
docker compose exec --user=www-data app php artisan test tests/Feature/ChatFeatureTest.php - Фронт-билд:
docker compose run --rm frontend-build
Изоляция тестового окружения:
- Bootstrap тестов (
tests/CreatesApplication.php) принудительно выставляет testing-env (sqlite :memory:,CACHE_DRIVER=array,SESSION_DRIVER=array,BROADCAST_DRIVER=log) до загрузки приложения. - Для каждого процесса формируется
TEST_TOKEN, а cache/storage paths переносятся в отдельный temp-каталог. - Это устраняет конфликты и падения тестов из-за смешивания cache/storage между запуском от
rootиwww-dataв Docker.
Рекомендуемый pre-commit check:
php artisan testnpm run test:jsnpm run build
Контрольный набор перед релизом:
docker compose run --rm testdocker compose run --rm --no-deps --entrypoint npm node run test:jsdocker compose run --rm --no-deps frontend-build
Проверка зависимостей:
npm outdated— контроль устаревших проектных пакетов.npm audit— должен завершаться без уязвимостей.composer audit— должен завершаться без security advisories; abandoned-зависимости удалены после миграции Swagger/OpenAPI с PHPDoc на PHP attributes.
Ручной smoke-check интерфейса перед релизом:
- длинные секции и кнопки
В началона desktop/tablet/mobile; - радио: карусели, счетчики, контрастные плашки, режимы
Прозрачнее/Контрастнее, компактный mobile-блокСейчас играет; - чаты и виджеты: кнопки удаления, контраст текста/статусов и адаптивные списки.
POST /api/feedbackPOST /api/client-errorsGET /api/site/home-contentGET /api/site/world-overview?locale=ru|en
- Пользователи и профиль:
GET /api/users,GET /api/users/{user}/posts,GET /api/users/following_postsPOST /api/users/profile,POST /api/users/{user}/toggle_following
- Посты и медиа:
POST /api/post_media,GET /api/media/post-images/{postImage}GET /api/posts,POST /api/posts,GET /api/posts/discover,GET /api/posts/carouselPOST /api/posts/{post}/view,GET /api/posts/{post}/comment,POST /api/posts/{post}/comment,DELETE /api/posts/{post}/comments/{comment}
- Чаты:
GET /api/chats,GET /api/chats/unread-summary,GET /api/chats/usersPOST /api/chats/direct/{user},GET /api/chats/{conversation},POST /api/chats/{conversation}/readGET /api/chats/{conversation}/messages,POST /api/chats/{conversation}/messagesPOST /api/chats/{conversation}/messages/{message}/reactionsDELETE /api/chats/{conversation}/messages/{message}DELETE /api/chats/{conversation}/messages/{message}/attachments/{attachment}GET /api/chats/settings,PATCH /api/chats/settingsGET /api/chats/archives,POST /api/chats/archives,GET /api/chats/archives/{archive}/download,POST /api/chats/archives/{archive}/restorePATCH /api/chats/{conversation}/mood-status
- Радио:
GET /api/radio/stations,GET /api/radio/stream,GET /api/radio/favorites,POST /api/radio/favorites,DELETE /api/radio/favorites/{stationUuid} - IPTV библиотека и импорт:
POST /api/iptv/playlist/fetch,GET /api/iptv/saved,POST /api/iptv/saved/playlists,PATCH /api/iptv/saved/playlists/{playlistId},DELETE /api/iptv/saved/playlists/{playlistId},POST /api/iptv/saved/channels,PATCH /api/iptv/saved/channels/{channelId},DELETE /api/iptv/saved/channels/{channelId} - IPTV возможности:
GET /api/iptv/transcode/capabilities POST /api/iptv/proxy/start,DELETE /api/iptv/proxy/{session}POST /api/iptv/transcode/start,DELETE /api/iptv/transcode/{session}POST /api/iptv/relay/start,DELETE /api/iptv/relay/{session}- Activity tracking:
POST /api/activity/heartbeat,POST /api/analytics/events
- Пользователи, посты, комментарии, обращения, диалоги, блокировки, настройки сайта.
- Дашборд аналитики:
GET /api/admin/summaryGET /api/admin/dashboard?year=YYYY&date_from=YYYY-MM-DD&date_to=YYYY-MM-DD
GET /api/admin/dashboard/export?format=xls|json&locale=ru|en&year=YYYY&date_from=YYYY-MM-DD&date_to=YYYY-MM-DD- Диагностика lifetime error log:
GET /api/admin/error-logGET /api/admin/error-log/entries?search=...&type=all|server_exception|client_error|analytics_failure&page=1&per_page=20GET /api/admin/error-log/export?search=...&type=...GET /api/admin/error-log/download
- Экспорт запускается из админки и возвращает поток файла (
Content-Disposition) для прямого скачивания. - JSON/XLS payload синхронизирован с блоками
retention,content,chats,media,radio,iptv,errors_and_moderation. - Lifetime error log работает как отдельный operational diagnostics контур: хранит подробные сырые записи за весь срок жизни сайта, умеет искать по активному логу и архивам и не зависит от периодного dashboard payload.
- JSON/XLS payload строится из heartbeat, client analytics events, users/posts/comments/media/chats/radio/IPTV/error-log данных и покрывается feature-тестами.
- Swagger UI:
GET /api/documentation - Docs route для JSON, который использует Swagger UI:
GET /docs?api-docs.json - Сгенерированный JSON-файл на диске:
storage/api-docs/api-docs.json - Генерация документации:
php artisan l5-swagger:generate - Базовая спецификация на PHP attributes:
app/OpenApi/OpenApiSpec.php - Актуальная версия спецификации:
1.5.0 - Спецификация синхронизирована с ключевыми маршрутами
site config,users,posts,post_media,radio favorites,chat settings/archives/mood-status,IPTV library/playback sessions,activity heartbeat,client analytics events,client error logging,admin summary/analytics/export,admin diagnostics error-log. - Для блока админ-аналитики Swagger синхронизирован с маршрутами dashboard/export и проверяется
SwaggerDocumentationFeatureTest. - На L5 Swagger 11 спецификация переведена на
OpenApi\Attributes; abandoned-пакетdoctrine/annotationsбольше не нужен. - Генерация и доступность Swagger UI дополнительно проверяются тестом
tests/Feature/SwaggerDocumentationFeatureTest.php.
Доступны после php artisan db:seed:
admin@example.com/passworduser1@example.com/passworduser2@example.com/passworduser3@example.com/passworduser4@example.com/passworduser5@example.com/passworddemo01@example.com...demo18@example.com/password
DemoSocialContentSeeder дополнительно создаёт демо-посты, комментарии, лайки, подписки и placeholder-изображения.
По умолчанию изображения генерируются локально (без зависимости от интернета). Если нужны внешние фото из loremflickr.com, включите DEMO_SEED_USE_REMOTE_IMAGES=1.
Если seed-посты уже были созданы с локальными SVG-плейсхолдерами, повторный запуск DemoSocialContentSeeder при DEMO_SEED_USE_REMOTE_IMAGES=1 заменит их на реальные загруженные изображения.
- Проверьте
DB_HOST/DB_PORTв активном env-файле. - Из контейнеров Docker MySQL доступен как
db:3306. - С хоста Windows/MySQL доступен как
127.0.0.1:3307.
- Проверьте
DB_USERNAME/DB_PASSWORDи пользователя в MySQL.
- Самая частая причина: Docker запущен с неправильным
.env.dockerили безMYSQL_ROOT_PASSWORD. - Пересоздайте docker-env из шаблона:
- PowerShell:
Copy-Item .env.docker.example .env.docker -Force
- PowerShell:
- Проверьте, что в
.env.dockerесть:DB_HOST=dbMYSQL_DATABASE=...MYSQL_USER=...MYSQL_PASSWORD=...MYSQL_ROOT_PASSWORD=...
- После исправления env перезапустите стек:
docker compose down -vdocker compose up -d --build
- Порт уже занят другим приложением.
- Запустите Docker с другими host-портами через переменные:
WEB_FORWARD_PORT,DB_FORWARD_PORT,VITE_FORWARD_PORT,REVERB_FORWARD_PORT.
- Это ожидаемо: флаг
-vудаляет том MySQL (db_data), база пересоздаётся с нуля. - В текущей конфигурации контейнер
appсам запускаетdb:seed, если таблицаusersпустая (RUN_SEEDERS_ON_EMPTY_DB=1). - Если вы отключили авто-сидирование, запустите вручную:
docker compose exec --user=www-data app php artisan db:seed --force
- Частая причина: прерванный запрос изображения (например
499при смене маршрута), а не отсутствие файла или интернета. - Маршруты media (
post-images,avatars) используют отдельный лимитthrottle:600,1. - Во фронтенде добавлен автоповтор загрузки изображения перед fallback (cache-bust query
?_img_retry=...). - Если вы обновили код, но эффект не появился, очистите кэш:
docker compose exec --user=www-data app php artisan optimize:clearCtrl+F5в браузере
- Поддерживаются
mp4,webm,mov,m4v,avi,mkvи изображенияjpg/jpeg/png/webp/gif. - Лимит одного файла:
200 MB. - В личном кабинете показываются статус и текст ошибки по каждому файлу; если загрузка отклонена, причина видна под формой.
- Для
mkvзагрузка и скачивание поддерживаются, но встроенное воспроизведение в браузере зависит от кодеков конкретного файла. - В production проверьте, что
Nginx/reverse proxy разрешает тело запроса не меньше200M, иначе запрос будет отклонен до Laravel.
- Это warning от Docker Compose, а не ошибка тестов.
- Используйте:
- без пересборки:
docker compose --profile test run --rm --no-build test - с пересборкой:
docker compose --profile test run --rm --build test
- без пересборки:
- Причина:
artisanзапускался в контейнере отroot, и часть cache-папок создавалась с правами, недоступными дляwww-data. - Профилактика: запускайте artisan в Docker так:
docker compose exec --user=www-data app php artisan ... - Если уже сломалось:
docker compose exec app sh -lc "chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache && find /var/www/html/storage /var/www/html/bootstrap/cache -type d -exec chmod 775 {} \\; && find /var/www/html/storage /var/www/html/bootstrap/cache -type f -exec chmod 664 {} \\;"docker compose exec --user=www-data app php artisan optimize:clear
- Причина: тестовые storage-пути были созданы от другого пользователя (обычно
root), после чего запуск отwww-dataне может очистить директории. - Профилактика: запускайте тесты в Docker от
www-dataи не смешивайтеdocker compose exec app ...иdocker compose exec --user=www-data app .... - Если уже сломалось:
docker compose exec app sh -lc "rm -rf /var/www/html/storage/framework/testing/disks && mkdir -p /var/www/html/storage/framework/testing/disks && chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache && chmod -R ug+rwX /var/www/html/storage /var/www/html/bootstrap/cache"docker compose exec --user=www-data app php artisan test
- Причина: PHP/Symfony Process не может писать lock-файлы во временную директорию по умолчанию (
C:/OSPanel/temp/...). - Решение: запускать тесты с локальным writable temp-каталогом проекта:
- PowerShell:
$tempPath = Join-Path (Get-Location) 'storage\\framework\\testing-runtime\\tmp'New-Item -ItemType Directory -Force -Path $tempPath | Out-Nullphp -d sys_temp_dir="$tempPath" artisan test
- PowerShell:
- Локально: запущен ли
npm run dev. - Docker: пересоберите фронт
docker compose run --rm frontend-build. - Сделайте
Ctrl+F5.
- Это нормально: сервис делает
npm run buildи завершается после успешной сборки. - Проверяйте именно долгоживущие сервисы:
app,web,websocket,db. - Если после простоя сайт отвечает медленно, смотрите
docker compose psиdocker compose logs --tail=100 app web db websocket, а не статусfrontend-build.
- Короткий
502во время ручногоdocker compose up -d --force-recreate appвозможен, покаphp-fpmподнимается заново. - Постоянный
502уже не должен быть связан со stale upstream IP:webрезолвитappчерез Docker DNS во время работы. - Если
502не исчезает после того, какappсталhealthy, проверьте:docker compose psdocker compose logs --tail=100 app webdocker compose exec --user=www-data app php artisan optimize:clear
- Убедитесь, что пользователь авторизован.
- Проверьте домен/порт (
APP_URL) и фактический URL браузера. - Проверьте, что Reverb запущен.
- Очистите cookie и обновите страницу (
Ctrl+F5). - Убедитесь, что не смешаны окружения:
- local:
XSRF_COOKIE=social_network_local_xsrf - Docker:
XSRF_COOKIE=social_network_docker_xsrf
- local:
- После переключения режимов выполните logout и удалите старые cookies.
- Исправление:
php -r "if (is_link('public/storage')) unlink('public/storage');"php artisan storage:link
Подробный production-гайд (Ubuntu + Nginx + PHP-FPM + Supervisor):
DEPLOY.md
© 2026 Rinat Sarmuldin. All rights reserved.- Репозиторий распространяется по проприетарной лицензии:
LICENSE. - Без письменного разрешения автора запрещены:
- использование в production и коммерческих проектах;
- копирование, изменение, распространение и создание производных работ.
- Для получения прав на использование свяжитесь с автором:
ura07srr@gmail.com.