Let admins manage section names and ordering from the media sidebar without manual DB edits. Add safe section deletion in admin flow and remove the section storage folder after DB cascade cleanup. |
||
|---|---|---|
| data | ||
| lib | ||
| migrations | ||
| photos | ||
| scripts | ||
| thumbs | ||
| .gitignore | ||
| .htaccess | ||
| admin-mysql.php | ||
| admin.php | ||
| app.js | ||
| config.php.example | ||
| deploy-config.php.example | ||
| deploy.php | ||
| favicon.svg | ||
| index-mysql.php | ||
| index.php | ||
| README.md | ||
| style.css | ||
Галерея фотографий (PHP)
Локальный проект галереи, который:
- читает категории и фото из
photos/(туда можно загружать по FTP), - при каждом открытии страницы проверяет, появились ли новые/обновлённые фото,
- создаёт и обновляет превью в
thumbs/, - показывает категории и фото в веб-интерфейсе,
- открывает большую фотографию в лайтбоксе.
Структура
photo-gallery/
├─ index.php # основной скрипт: индексация + HTML
├─ style.css # стили (material-like, строгий)
├─ app.js # лайтбокс + защита от простого скачивания
├─ deploy.php # webhook-триггер деплоя
├─ admin.php # закрытая админка (папки/фото/сортировка)
├─ deploy-config.php.example # пример конфига webhook
├─ photos/ # исходные фото по категориям (папкам)
├─ thumbs/ # автогенерируемые превью
└─ data/
├─ last_indexed.txt # timestamp последней индексации
└─ sort.json # порядок категорий и фото
Как работает индексация
- Скрипт читает
data/last_indexed.txt. - Сканирует
photos/<категория>/. - Для каждого изображения (
jpg/jpeg/png/webp/gif):- если файл новее
last_indexed, - или превью не существует,
- или превью старее оригинала,
тогда создаётся/обновляется превью (
.jpg) вthumbs/<категория>/.
- если файл новее
- Записывает новый timestamp в
last_indexed.txt.
Индексация выполняется на каждом обращении к index.php.
Также на публичной странице категории показываются с обложкой (берётся превью первой фотографии по текущей сортировке).
Требования
- PHP 8.2+ (8.3 тоже ок)
- Расширение GD или Imagick
- если есть Imagick — будет использоваться он,
- иначе используется GD.
Локальный запуск
Из папки photo-gallery:
php -S 127.0.0.1:8080
MySQL конфиг и миграции (этап перехода на БД)
Быстрый запуск на хостинге (Timeweb)
- Создать базу MySQL в панели хостинга.
- Подтянуть проект из git.
- Создать
config.phpиз шаблона:
cp config.php.example config.php
- Заполнить в
config.phpпараметры подключения к БД. - Запустить миграции:
php scripts/migrate.php
После этого проект должен работать.
Про кодировку
Проект использует utf8mb4:
- в PDO DSN (
charset=utf8mb4), - в миграциях для таблиц (
CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci).
Если база на хостинге по умолчанию с другой кодировкой, это обычно не мешает, т.к. таблицы создаются миграциями с нужной кодировкой.
Файлы:
lib/db.php— подключение PDOmigrations/*.sql— схема БДscripts/migrate.php— runner миграций
Открыть в браузере:
http://127.0.0.1:8080
Загрузка фото
Через FTP кладите файлы в:
photos/Свадьба/001.jpgphotos/Портреты/img_10.png- и т.д.
Папка верхнего уровня = категория.
Деплой (Timeweb shared hosting)
В проекте есть скрипт:
scripts/deploy.sh
Он:
- делает
git fetch, - жёстко переключает код на
origin/<branch>, - сохраняет runtime-папки (
photos,thumbs,data), - создаёт
data/last_indexed.txtпри первом запуске.
Запуск на хостинге:
cd ~/www/photo-gallery
bash scripts/deploy.sh
По умолчанию ветка main. Для другой ветки:
BRANCH=master bash scripts/deploy.sh
Админка загрузки (по токену)
Новый контур на MySQL (основной):
admin.php?token=...— админкаindex.php— публичная витрина + комментарии
Совместимость:
admin-mysql.phpиindex-mysql.phpоставлены как алиасы на новые основные файлы.
Что уже есть в MySQL-контуре:
- создание разделов,
- сценарий загрузки: сначала выбор раздела, затем массовая загрузка только фото "до",
- после загрузки автоматический prefill имени (code_name) из имени файла,
- для каждой карточки фото можно отредактировать: имя, сортировку, комментарий и добавить/заменить фото "после",
- запись в таблицы
sections,photos,photo_files, - персональные комментаторы (генерация ссылок + повторный просмотр/перевыпуск ссылки),
- плоские комментарии к фото,
- удаление комментариев админом,
- watermark на выдаче версии "после".
Админка использует тот же token, что и deploy.php, из файла deploy-config.php.
Ссылка входа:
https://<домен>/admin.php?token=<твой_секрет>
В админке можно:
- создавать папки-категории,
- переименовывать/удалять категории,
- задавать порядок (индекс сортировки) категорий,
- загружать фото в выбранную папку,
- переименовывать/удалять фото,
- задавать порядок (индекс сортировки) фото внутри категории,
- видеть превью фото в таблице админки,
- автоматически очищать
data/sort.jsonот несуществующих папок/файлов.
Ограничения загрузки:
- только изображения: JPG/PNG/WEBP/GIF,
- максимум 3 МБ на файл,
- MIME-тип и расширение проверяются на сервере.
Загрузка новых фото выполняется в секции выбранной категории (чтобы нельзя было загрузить в неправильную папку).
Удалённый запуск деплоя по ссылке (webhook)
- На хостинге создай конфиг из примера:
cp deploy-config.php.example deploy-config.php
- Заполни в
deploy-config.phpминимум:
token(длинный секрет)- при желании
allowed_ips - при желании
basic_auth_user/basic_auth_pass
- Запуск деплоя:
https://<домен>/deploy.php?token=<твой_секрет>
Рекомендация: включить IP whitelist и Basic Auth.
Примечания
- Превью генерируются в формате JPEG с качеством ~82.
- При первом заходе на большую папку возможно небольшое ожидание (генерация превью).
- CSS/JS и favicon подключаются с cache-busting параметром
?v=<filemtime>, чтобы после деплоя пользователю не приходилось чистить кеш вручную. - В футере публичной страницы есть ненавязчивое авторство со ссылкой:
https://t.me/andr33vru. - Для production обычно лучше вынести индексацию в cron/очередь, но для текущей задачи это intentionally on-request.