207 lines
8.7 KiB
Markdown
207 lines
8.7 KiB
Markdown
# Галерея фотографий (PHP)
|
||
|
||
Локальный проект галереи, который:
|
||
|
||
- читает категории и фото из `photos/` (туда можно загружать по FTP),
|
||
- при каждом открытии страницы проверяет, появились ли новые/обновлённые фото,
|
||
- создаёт и обновляет превью в `thumbs/`,
|
||
- показывает категории и фото в веб-интерфейсе,
|
||
- открывает большую фотографию в лайтбоксе.
|
||
|
||
## Структура
|
||
|
||
```text
|
||
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`:
|
||
|
||
```bash
|
||
php -S 127.0.0.1:8080
|
||
```
|
||
|
||
## MySQL конфиг и миграции (этап перехода на БД)
|
||
|
||
### Быстрый запуск на хостинге (Timeweb)
|
||
|
||
1. Создать базу MySQL в панели хостинга.
|
||
2. Подтянуть проект из git.
|
||
3. Создать `config.php` из шаблона:
|
||
|
||
```bash
|
||
cp config.php.example config.php
|
||
```
|
||
|
||
4. Заполнить в `config.php` параметры подключения к БД.
|
||
5. Запустить миграции:
|
||
|
||
```bash
|
||
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` при первом запуске.
|
||
|
||
Запуск на хостинге:
|
||
|
||
```bash
|
||
cd ~/www/photo-gallery
|
||
bash scripts/deploy.sh
|
||
```
|
||
|
||
По умолчанию ветка `main`. Для другой ветки:
|
||
|
||
```bash
|
||
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`.
|
||
|
||
Ссылка входа:
|
||
|
||
```text
|
||
https://<домен>/admin.php?token=<твой_секрет>
|
||
```
|
||
|
||
В админке можно:
|
||
- создавать папки-категории,
|
||
- переименовывать/удалять категории,
|
||
- задавать порядок (индекс сортировки) категорий,
|
||
- загружать фото в выбранную папку,
|
||
- переименовывать/удалять фото,
|
||
- задавать порядок (индекс сортировки) фото внутри категории,
|
||
- видеть превью фото в таблице админки,
|
||
- автоматически очищать `data/sort.json` от несуществующих папок/файлов.
|
||
|
||
Ограничения загрузки:
|
||
- только изображения: JPG/PNG/WEBP/GIF,
|
||
- максимум 3 МБ на файл,
|
||
- MIME-тип и расширение проверяются на сервере.
|
||
|
||
Загрузка новых фото выполняется в секции выбранной категории (чтобы нельзя было загрузить в неправильную папку).
|
||
|
||
## Удалённый запуск деплоя по ссылке (webhook)
|
||
|
||
1. На хостинге создай конфиг из примера:
|
||
|
||
```bash
|
||
cp deploy-config.php.example deploy-config.php
|
||
```
|
||
|
||
2. Заполни в `deploy-config.php` минимум:
|
||
- `token` (длинный секрет)
|
||
- при желании `allowed_ips`
|
||
- при желании `basic_auth_user/basic_auth_pass`
|
||
|
||
3. Запуск деплоя:
|
||
|
||
```text
|
||
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.
|