Skip to content

Учебно-демонстрационный сайт отеля с админкой и бронированием (PHP 8.2, MySQL, Docker)

Notifications You must be signed in to change notification settings

nickihysterics/php-hotel

Repository files navigation

Hotel

Учебно-демонстрационный сайт отеля с административной панелью и логикой бронирования. Запуск и инфраструктура — через Docker Compose (PHP 8.2 + Apache, Nginx как reverse proxy, MySQL 8).

Технологии

  • PHP 8.2 (Apache внутри контейнера).
  • Nginx (reverse proxy, самоподписанный TLS).
  • MySQL 8.
  • phpMyAdmin (опционально, для управления БД).
  • Docker + Docker Compose.
  • Composer, PDO.
  • PHPStan, PHP-CS-Fixer.
  • HTML/CSS/JS (готовая тема, статические ассеты в public/).

Запуск

  1. Создайте файл окружения:
cp .env.example .env
  1. Автозапуск с открытием страниц (сразу откроет сайт, админку и phpMyAdmin):
./scripts/start.sh

Если нужен ручной запуск, используйте шаги ниже.

  1. Установите зависимости PHP (по желанию, для разработки):
docker compose run --rm web composer install
  1. Соберите и запустите сервисы:
docker compose up -d --build
  1. Откройте сайт и админку:

Конфигурация окружения

Файл .env:

DB_HOST=db
DB_NAME=hotel
DB_USER=hotel
DB_PASS=hotel
DB_PORT=3306
DB_ROOT_PASS=root
ADMIN_USER=hotel_admin
ADMIN_PASS=HotelDemo2024
  • DB_* — параметры подключения к MySQL.
  • ADMIN_USER/ADMIN_PASS — учетные данные первого администратора, которые создаются при первом входе, если таблица users пустая.

Вход в админку

Адрес: http://localhost/admin/login.php

Логин/пароль по умолчанию:

Логин: hotel_admin
Пароль: HotelDemo2024

Они берутся из .env (ADMIN_USER / ADMIN_PASS). Если нужно изменить учетные данные:

  • обновите запись в таблице users, либо
  • удалите всех пользователей из users и зайдите снова (будет создан новый админ из .env).

Функционал

  • Публичные страницы: главная, список номеров, карточка номера, контакты.
  • Админка: категории, типы номеров, этажи, виды, типы санузлов, клиенты, сотрудники, бронирования, пользователи.
  • Атрибуты номера: этаж, вид из номера, количество спальных мест, раздельный санузел, тип санузла.
  • Бронирования:
    • статусы reserved / confirmed / cancelled;
    • проверка пересечений по датам;
    • учет доступности по количеству (quantity) у типа номера;
    • сумма бронирования считается автоматически, если total = 0.
  • Аналитика и экспорт в Excel (CSV).

Аналитика и экспорт

  • Аналитика: http://localhost/admin/analytics.php
  • Экспорт: http://localhost/admin/exports.php

Как редактировать проект

  • Тексты и верстка публичных страниц: public/index.php, public/rooms.php, public/rooms-single.php, public/contact.php.
  • Общие блоки сайта: templates/site/header.php, templates/site/footer.php.
  • Админка и ее страницы: public/admin/*.php.
  • Общие блоки админки: templates/admin/header.php, templates/admin/footer.php.
  • PHP-логика: src/, конфигурация и bootstrap: config/.
  • Статические ассеты: public/css, public/js, public/images, public/fonts.
  • Исходники SCSS: resources/scss/ (сборщик не подключен, правьте CSS напрямую или подключите сборку отдельно).
  • Схема и начальные данные БД: database/init.sql.

Структура проекта

  • public/ — публичный веб‑корень.
  • public/admin/ — админка.
  • src/ — PHP‑классы и логика.
  • config/ — bootstrap и окружение.
  • database/ — схема и сиды.
  • docker/ — настройки контейнеров и Nginx.
  • templates/ — общие шаблоны.
  • resources/ — исходники стилей (SCSS).
  • scripts/ — утилиты локального запуска.
  • storage/ — служебные файлы (логи и т.п.).
  • composer.json, phpstan.neon, .php-cs-fixer.php — инструменты качества кода.

Где хранятся данные пользователей

  • Данные лежат в MySQL внутри Docker volume db-data.
  • Администраторы хранятся в таблице users с password_hash (используется password_hash()).
  • Данные клиентов и сотрудников — таблицы clients и associates.
  • Сессии — стандартные PHP-сессии (по умолчанию файловое хранение в контейнере).
  • Для просмотра структуры БД можно использовать phpMyAdmin: http://localhost:8081/.

Миграции для существующей БД

Если база уже была создана раньше, проще пересоздать volume:

docker compose down -v
docker compose up -d --build

Если нужно сохранить данные, добавьте новые справочники и поля вручную (выполняйте команды по очереди, уже существующие можно пропустить):

docker compose exec -T db mysql -uroot -proot hotel -e "CREATE TABLE IF NOT EXISTS room_views (id INT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(100) NOT NULL, PRIMARY KEY (id), UNIQUE KEY room_views_name_unique (name)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"
docker compose exec -T db mysql -uroot -proot hotel -e "CREATE TABLE IF NOT EXISTS bathroom_types (id INT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(100) NOT NULL, PRIMARY KEY (id), UNIQUE KEY bathroom_types_name_unique (name)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"
docker compose exec -T db mysql -uroot -proot hotel -e "CREATE TABLE IF NOT EXISTS floors (id INT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(100) NOT NULL, level INT NOT NULL, view_id INT UNSIGNED NOT NULL, PRIMARY KEY (id), UNIQUE KEY floors_level_unique (level)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;"
docker compose exec -T db mysql -uroot -proot hotel -e "INSERT IGNORE INTO room_views (name) VALUES ('Город'), ('Парк'), ('Внутренний двор');"
docker compose exec -T db mysql -uroot -proot hotel -e "INSERT IGNORE INTO bathroom_types (name) VALUES ('Душевая кабина'), ('Ванна'), ('Ванна и душевая');"
docker compose exec -T db mysql -uroot -proot hotel -e \"INSERT IGNORE INTO floors (name, level, view_id) VALUES ('1 этаж', 1, 1), ('2 этаж', 2, 1), ('3 этаж', 3, 1);\"
docker compose exec -T db mysql -uroot -proot hotel -e "ALTER TABLE rooms ADD COLUMN floor_id INT UNSIGNED NOT NULL DEFAULT 1 AFTER quantity;"
docker compose exec -T db mysql -uroot -proot hotel -e "ALTER TABLE rooms ADD COLUMN view_id INT UNSIGNED NOT NULL DEFAULT 1 AFTER floor_id;"
docker compose exec -T db mysql -uroot -proot hotel -e "ALTER TABLE rooms ADD COLUMN bed_count INT UNSIGNED NOT NULL DEFAULT 1 AFTER view_id;"
docker compose exec -T db mysql -uroot -proot hotel -e "ALTER TABLE rooms ADD COLUMN bathroom_separate TINYINT(1) NOT NULL DEFAULT 0 AFTER bed_count;"
docker compose exec -T db mysql -uroot -proot hotel -e "ALTER TABLE rooms ADD COLUMN bathroom_type_id INT UNSIGNED NOT NULL DEFAULT 1 AFTER bathroom_separate;"

Также (при необходимости) примените миграции для статусов бронирований:

docker compose exec -T db mysql -uroot -proot hotel -e "ALTER TABLE rooms ADD COLUMN quantity INT UNSIGNED NOT NULL DEFAULT 1 AFTER price;"
docker compose exec -T db mysql -uroot -proot hotel -e "ALTER TABLE bookings ADD COLUMN status ENUM('reserved','confirmed','cancelled') NOT NULL DEFAULT 'reserved' AFTER date_out;"
docker compose exec -T db mysql -uroot -proot hotel -e "CREATE INDEX bookings_room_status_dates_idx ON bookings (room_id, status, date_in, date_out);"
docker compose exec -T db mysql -uroot -proot hotel -e "ALTER TABLE rooms ADD CONSTRAINT rooms_quantity_chk CHECK (quantity >= 0);"

Если в БД уже есть проверка дат date_out >= date_in, замените на строгую:

docker compose exec -T db mysql -uroot -proot hotel -e "ALTER TABLE bookings DROP CHECK bookings_dates_chk;"
docker compose exec -T db mysql -uroot -proot hotel -e "ALTER TABLE bookings ADD CONSTRAINT bookings_dates_chk CHECK (date_out > date_in);"

Сброс базы данных

Полный сброс (удалит данные):

docker compose down -v
docker compose up -d --build

Качество кода

docker compose run --rm web composer stan
docker compose run --rm web composer cs
docker compose run --rm web composer cs:fix

Примечания

  • База инициализируется из database/init.sql при первом запуске (пустой volume).
  • HTTPS использует самоподписанный сертификат — браузер покажет предупреждение.

About

Учебно-демонстрационный сайт отеля с админкой и бронированием (PHP 8.2, MySQL, Docker)

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published