Go to file
Alexander Andreev 3d28238994 Public: simplify desktop header and photo detail flow
Hide the redundant top heading on desktop while keeping the mobile context title visible. Reorder photo detail content to show images first, then metadata and description, so the page matches the expected viewing flow.
2026-02-21 13:29:20 +03:00
data Init photo gallery with auto-indexing, thumbs, UI, deploy script 2026-02-19 16:37:51 +03:00
lib Admin/Public: refine topics workflow and gallery topic nav 2026-02-21 12:40:39 +03:00
migrations Admin: add hierarchical topics with photo tagging 2026-02-21 12:15:36 +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/Public: add sticky admin sidebar and keyboard navigation 2026-02-21 13:21:50 +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: simplify desktop header and photo detail flow 2026-02-21 13:29:20 +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.