Go to file
Alexander Andreev 48bb460749 Admin: split sections/photos workflows in sidebar
Separate section management from photo management to keep the admin navigation clear and focused. Add autosave for section edits, stronger double-confirmation on section removal, and explicit cleanup of before/after files when a section is deleted.
2026-02-20 18:25:33 +03:00
data Init photo gallery with auto-indexing, thumbs, UI, deploy script 2026-02-19 16:37:51 +03:00
lib Admin: add section rename and delete actions 2026-02-20 18:20:03 +03:00
migrations Public badge for restored photos and commenter link retrieval/regeneration 2026-02-20 15:13:46 +03:00
photos Init photo gallery with auto-indexing, thumbs, UI, deploy script 2026-02-19 16:37:51 +03:00
scripts Fix migration runner for MySQL DDL implicit commit 2026-02-20 14:13:59 +03:00
thumbs Init photo gallery with auto-indexing, thumbs, UI, deploy script 2026-02-19 16:37:51 +03:00
.gitignore Add MySQL admin v1: sections and photo upload before/after 2026-02-20 14:16:03 +03:00
.htaccess Fix redirect loop: robust HTTPS + non-www rules 2026-02-19 18:00:35 +03:00
admin-mysql.php Switch main app to MySQL flow and restore section-first bulk upload UX 2026-02-20 14:39:42 +03:00
admin.php Admin: split sections/photos workflows in sidebar 2026-02-20 18:25:33 +03:00
app.js Show photo titles from filenames in catalog and lightbox 2026-02-19 17:03:10 +03:00
config.php.example Start MySQL implementation: config template, PDO layer and migrations 2026-02-20 14:07:50 +03:00
deploy-config.php.example Add secure deploy webhook with local config example 2026-02-19 16:57:09 +03:00
deploy.php Add secure deploy webhook with local config example 2026-02-19 16:57:09 +03:00
favicon.svg Add favicon and subtle footer author link 2026-02-19 17:46:46 +03:00
index-mysql.php Switch main app to MySQL flow and restore section-first bulk upload UX 2026-02-20 14:39:42 +03:00
index.php Public: mobile sidebar drawer for inner pages 2026-02-20 18:14:12 +03:00
README.md README: add Timeweb DB setup steps and charset note 2026-02-20 15:19:23 +03:00
style.css UI: align footer author to the right 2026-02-20 15:29:16 +03:00

Галерея фотографий (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               # порядок категорий и фото

Как работает индексация

  1. Скрипт читает data/last_indexed.txt.
  2. Сканирует photos/<категория>/.
  3. Для каждого изображения (jpg/jpeg/png/webp/gif):
    • если файл новее last_indexed,
    • или превью не существует,
    • или превью старее оригинала, тогда создаётся/обновляется превью (.jpg) в thumbs/<категория>/.
  4. Записывает новый 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)

  1. Создать базу MySQL в панели хостинга.
  2. Подтянуть проект из git.
  3. Создать config.php из шаблона:
cp config.php.example config.php
  1. Заполнить в config.php параметры подключения к БД.
  2. Запустить миграции:
php scripts/migrate.php

После этого проект должен работать.

Про кодировку

Проект использует utf8mb4:

  • в PDO DSN (charset=utf8mb4),
  • в миграциях для таблиц (CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci).

Если база на хостинге по умолчанию с другой кодировкой, это обычно не мешает, т.к. таблицы создаются миграциями с нужной кодировкой.

Файлы:

  • lib/db.php — подключение PDO
  • migrations/*.sql — схема БД
  • scripts/migrate.php — runner миграций

Открыть в браузере:

  • http://127.0.0.1:8080

Загрузка фото

Через FTP кладите файлы в:

  • photos/Свадьба/001.jpg
  • photos/Портреты/img_10.png
  • и т.д.

Папка верхнего уровня = категория.

Деплой (Timeweb shared hosting)

В проекте есть скрипт:

  • scripts/deploy.sh

Он:

  1. делает git fetch,
  2. жёстко переключает код на origin/<branch>,
  3. сохраняет runtime-папки (photos, thumbs, data),
  4. создаёт 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)

  1. На хостинге создай конфиг из примера:
cp deploy-config.php.example deploy-config.php
  1. Заполни в deploy-config.php минимум:
  • token (длинный секрет)
  • при желании allowed_ips
  • при желании basic_auth_user/basic_auth_pass
  1. Запуск деплоя:
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.