153 lines
6.3 KiB
Markdown
153 lines
6.3 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
|
||
```
|
||
|
||
Открыть в браузере:
|
||
|
||
- `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
|
||
```
|
||
|
||
## Админка загрузки (по токену)
|
||
|
||
Админка использует тот же `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.
|