40-pintar con php

 

Validación de Disponibilidad de Habitaciones en un Sistema de Reservas Hotelero

En el desarrollo de un sistema de reservas para hoteles, una de las funcionalidades más críticas es la validación de disponibilidad de habitaciones. En este post, explicaré cómo implementamos esta característica en nuestro proyecto hotelero utilizando PHP y MySQL.

1. Primer Escenario: ¿Existe la habitación en la tabla reservas?

 buscar una habitación que todavía no esté almacenada en la tabla de reservas .

$_POST['id_habitacion'] = '7'; 

Array
(
)

Objetivo: Verificar si la habitación seleccionada ya tiene reservas en la base de datos.


Estructura de la Base de Datos

Para gestionar las reservas, diseñamos tres tablas principales:

sql
CREATE TABLE `reservas` (
  `id_reserva` int(11) NOT NULL,
  `id_habitacion` int(11) NOT NULL,
  `id_usuario` int(11) NOT NULL,
  `pago_reserva` float NOT NULL,
  `numero_transaccion` text NOT NULL,
  `codigo_reserva` text NOT NULL,
  `descripcion_reserva` text NOT NULL,
  `fecha_ingreso` date NOT NULL,
  `fecha_salida` date NOT NULL,
  `fecha_reserva` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `habitaciones` (
  `id_h` int(11) NOT NULL,
  `tipo_h` int(11) NOT NULL,
  `estilo` text NOT NULL,
  `galeria` text NOT NULL,
  `video` text NOT NULL,
  `recorrido_virtual` text NOT NULL,
  `descripcion_h` text NOT NULL,
  `fecha_h` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `categorias` (
  `id` int(11) NOT NULL,
  `ruta` text NOT NULL,
  `color` text NOT NULL,
  `tipo` text NOT NULL,
  `img` text NOT NULL,
  `descripcion` text NOT NULL,
  `incluye` text NOT NULL,
  `continental_alta` float NOT NULL,
  `continental_baja` float NOT NULL,
  `americano_alta` float NOT NULL,
  `americano_baja` float NOT NULL,
  `fecha` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Flujo de Validación de Disponibilidad

El proceso de verificación de disponibilidad sigue estos pasos:

  1. Recepción de datos: El sistema recibe el ID de la habitación y las fechas seleccionadas.

  2. Consulta a la base de datos: Se realiza una consulta combinada (INNER JOIN) entre las tablas de habitaciones, reservas y categorías.

  3. Análisis de resultados:

    • Si no hay coincidencias, la habitación está disponible.

    • Si hay coincidencias, se procede a verificar los rangos de fechas.

El proceso de validación sigue estos pasos:

  1. Recolección de datos: El usuario selecciona una habitación y las fechas de ingreso/salida.

php
if(isset($_POST["id-habitacion"])){
    $valor = $_POST['id-habitacion'];
    $reservas = ControladorReservas::ctrMostrarReservas($valor);
}
  1. Consulta a la base de datos: Usamos un INNER JOIN entre las tablas para obtener información completa.

php
class ModeloReservas{
    static public function mdlMostrarReservas($tabla1, $tabla2, $tabla3, $valor){
        $stmt = Conexion::conectar()->prepare("SELECT $tabla1.*, $tabla2.*, $tabla3.* FROM $tabla1 
        INNER JOIN $tabla2 ON $tabla1.id_h = $tabla2.id_habitacion 
        INNER JOIN $tabla3 ON $tabla1.tipo_h = $tabla3.id WHERE id_h = :id_h");
        
        $stmt -> bindParam(":id_h", $valor, PDO::PARAM_STR);
        $stmt -> execute();
        return $stmt -> fetchAll();
    }
}
  1. Análisis de resultados:

    • Si no hay reservas para esa habitación, está disponible.

    • Si hay reservas, debemos comparar las fechas.

php
<?php if (!$reservas): ?>
    <h1 class="pb-5 float-left">¡Está Disponible!</h1>
<?php else: ?>
    <div class="infoDisponibilidad">
        <!-- Aquí iría la lógica para comparar fechas -->
    </div>
<?php endif ?>



Controlador de Reservas

El controlador actúa como intermediario entre la vista y el modelo:

php
class ControladorReservas{
    static public function ctrMostrarReservas($valor){
        $tabla1 = "habitaciones";
        $tabla2 = "reservas";
        $tabla3 = "categorias";
        
        $respuesta = ModeloReservas::mdlMostrarReservas($tabla1, $tabla2, $tabla3, $valor);
        return $respuesta;
    }
}

 Primer Escenario: ¿Existe la habitación en reservas?

Objetivo: Verificar si la habitación seleccionada ya tiene reservas en la base de datos.

  • Consulta SQL con INNER JOIN:
    Relacionamos 3 tablas: habitacionesreservas y categorías para obtener toda la información relevante (precios, categoría, fechas, etc.).

    php
    $respuesta = ReservasModel::buscarReservasPorHabitacion($id_habitacion);
    // Query: SELECT * FROM habitaciones 
    // INNER JOIN reservas ON habitaciones.id = reservas.id_habitacion
    // INNER JOIN categorias ON habitaciones.tipo = categorias.id
  • Resultados:

    • Si la respuesta está vacía: La habitación está disponible.

    • Si hay datos: Debemos validar cruces de fechas (lo haremos después).

Visualización en la Interfaz

php
Copy
Download
<?php if(!$reservas): ?>
    <h1 class="pb-5 float-left">¡Está Disponible!</h1>
<?php else: ?>
    <div class="infoDisponibilidad">Datos</div>
<?php endif ?>

2. Implementación en el Backend

Estructura del controlador (ReservasController):

php
class ReservasController {
  public $id_habitacion; // Propiedad pública para recibir el ID

  public function mostrarReservas() {
    $respuesta = ReservasModel::buscarReservasPorHabitacion($this->id_habitacion);
    echo json_encode($respuesta); // Envía datos a JavaScript
  }
}

Modelo (ReservasModel):

php
class ReservasModel {
  static public function buscarReservasPorHabitacion($id_habitacion) {
    // Conexión a BD y consulta con INNER JOIN
    $stmt = Conexion::conectar()->prepare("...");
    $stmt->bindParam(":id_habitacion", $id_habitacion, PDO::PARAM_INT);
    $stmt->execute();
    return $stmt->fetchAll();
  }
}

3. Integración con el Frontend

HTML:

  • Campos obligatorios para evitar envíos vacíos:

    html
    <select name="tipo_habitacion" required>
      <option value="">Seleccione una opción</option>
      <!-- Opciones dinámicas -->
    </select>

JavaScript:

  • Si la respuesta de la API está vacía, mostramos "Disponible":

    javascript
    if (respuesta.length === 0) {
      document.querySelector(".info-disponibilidad").innerHTML = "✅ Habitación disponible";
    } else {
      // Lógica para cruce de fechas (próxima clase)
    }

4. Próximos Pasos

En la siguiente parte cubriremos:
🔹 Validación de fechas: Comparar fechas seleccionadas vs. reservas existentes.
🔹 Feedback visual: Mostrar mensajes claros ("Disponible" / "No disponible").
🔹 Optimización: Mejorar consultas SQL para reducir carga del servidor.


💡 ¿Por qué es importante?
Esta validación evita doble reserva de una misma habitación y mejora la experiencia del usuario.

Comentarios

Entradas más populares de este blog

37. Enviando datos de la reserva - parte 1

42. Validar cruce de fechas - parte 1