Bonjour,

Je cherche à obtenir une liste de chambre libres/occupées après avoir effectué un filtre par dates d'arrivées et de départs.
Ex:
Hotel A
room 1
room2

Un 1er client arrive et veut une chambre dans l'hôtel A du 2020-01-01 au 2020-01-05
Donc on aura: room 1

arrival_date | departure_date
2020-01-01 | 2020-01-05

room 2

arrival_date | departure_date
NULL | NULL

Un 2eme client arrive et veut une chambre dans l'hôtel A du 2020-01-01 au 2020-01-05
Donc on aura : room 1

arrival_date | departure_date
2020-01-01 | 2020-01-05

room 2

arrival_date | departure_date
2020-01-01 | 2020-01-05

Un 3eme client arrive et veut une chambre dans l'hôtel A du 2020-01-12 au 2020-01-17
Donc on aura :

room 1

arrival_date | departure_date
2020-01-01 | 2020-01-05

room 1

arrival_date | departure_date
2020-01-12 | 2020-01-17

room 2

arrival_date | departure_date
2020-01-01 | 2020-01-05

Ce que je fais

Voici le code tel qu'il est sans l'application des filtres par dates car lorsque j'essaie de filter par dates j'obtiens une erreur décrite plus bas

index.php

<?php
require('Class/Client.php');
require('Class/Clientmanager.php');

require('Class/Booking.php');
require('Class/Bookingmanager.php');

if (isset($_POST['submitForm'])) 
{
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////                           insertion client                          ////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////

    $name = $_POST['name'];
    $email = $_POST['email'];
    $client_data = array('name' => $name,'email' => $email);
    $client = new Client($client_data);
    $db = new PDO('mysql:host=localhost;dbname=booking;charset=UTF8', 'root', '');
    $clientManager = new clientManager($db);
    $client_id = $clientManager->addclient($client);

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////                           get rooms by resort id                    ////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////

    $arrival = $_POST['arrival'];
    $departure = $_POST['departure'];
    $booking_data = array('client_id' => (int) $client_id, 'arrival' => $arrival);
    $booking = new Booking($booking_data);
    $bookingManager = new bookingManager($db);
    $resort_id = $_POST['resort'];
    $rooms = $bookingManager->getRoomsByResortid($resort_id);
    var_dump($rooms);

    echo '<br>';
    echo 'Après réservation';
    $reservation = $bookingManager->addBooking($booking);
    var_dump($reservation); 
}
?>

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Accueil</title>
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
    <div id="wrapper">
        <h1>Booking Application</h1>
        <nav class="main-nav" role="navigation">
            <ul>
                <li><a href="index.php" role="menuitem">Accueil</a></li>
                <li><a href="resorts.php" role="menuitem">Hôtels</a></li>
            </ul>   
        </nav>

        <section>
            <div class="formulaire">
                <?php if(isset($error_msg)) : ?>    
                <p class="error_msg"><?php echo $error_msg ?></p>
                <?php endif ?>

                <?php if(isset($success_msg)) : ?>  
                <p class="success_msg">
                    <?php echo $success_msg ?></p>
                <?php endif ?>

                <form method="post" action="index.php">
                    <h2>Réservez votre hôtel</h2>
                    <p>
                        Votre nom: <input type="text" name="name" value="<?php $name ?>" placeholder="Nom">
                    </p>

                    <p>
                        Votre email: <input type="email" name="email" value="<?php $email ?>" placeholder="votre@mail">
                    </p>

                    <p>
                        Votre hôtel:<select name="resort">
                                        <option value=""></option>
                                        <?php 
                                            $resorts = array(1 => 'Atlantis The Palm, Dubaï 5*', 'Burj Al Arab, Dubaï 7*', 'Krabi La Playa, Thaïlande 4*', 'Four Seasons, Bora Bora 4*', 'Atlantis Paradise Island, Bahamas 4*');
                                            foreach ($resorts as $resort_id => $resort) 
                                            {
                                                echo '<option value="'.$resort_id.'">' .$resort. '</option>';
                                            }

                                        ?>
                                    </select>

                    </p>

                    <p>
                        Du: <input class="mr-30" type="date" name="arrival" value="">
                        Au: <input class="mr-30" type="date" name="departure" value="">
                    </p>

                    <p>
                        <?php $today = date("Y-m-d") ?>
                        <input type="hidden" name="bookingCreation" value="<?php echo $today ?>" >
                    </p>

                    <p>
                        <input class="submit-bt" type="submit" name="submitForm" value="Réserver">
                    </p>

                </form>
            </div>
        </section>
    </div>
</body>
</html>

Booking.php

<?php

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////                                                                           ///////////////////////
///////////////                               BOOKING                                     ///////////////////////
///////////////                                                                           ///////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class Booking
{
    private $_client_id;
    private $_arrival_date;
    private $_departure_date;
    private $_today;
    private $_room_id;

    public function __construct(array $booking_data)
    {
        $this->setClientId($booking_data['client_id']);
        $this->setArrivalDate();
        $this->setDepartureDate();
        $this->setToday();
        $this->setRoomId();

    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////                           setters                                   ////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////

    public function setClientId($client_id)
    {
        if ((is_int($client_id)) && $client_id > 0) 
        {
            $this->_client_id = $client_id;
        }
    }

    public function setArrivalDate()
    {
        $arrival = $_POST['arrival'];
        $this->_arrival_date = $arrival;
    }

    public function setDepartureDate()
    {
        $departure = $_POST['departure'];
        $this->_departure_date = $departure;
    }

    public function setToday()
    {
        $today = date("Y-m-d"); 
        $this->_today = $today;
    }

    public function setRoomId()
    {
        try
        {
            $dbh = new PDO('mysql:host=localhost;dbname=booking;charset=UTF8', 'root', '');
        }
        catch(Exception $e)
        {
            echo 'Message d\'erreur SQL ' .$e->getMessage(). '<br>';
            exit;
        }

        $resort_id = trim($_POST['resort']);
        $sql= 'SELECT number FROM rooms as o 
               INNER JOIN resorts as r 
               ON r.id = o.resort_id
               WHERE r.id = "'.$resort_id.'"';
        $stmnt = $dbh->prepare($sql);
        $stmnt->execute();
        $result = $stmnt->fetchAll();
        $room_id = $result[(array_rand($result))]['number'];
        $this->_room_id = $room_id;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////                           getters                                   ////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////

    public function getClientId()
    {
        return $this->_client_id;
    }

    public function getArrivalDate()
    {
        return $this->_arrival_date;
    }

    public function getDepartureDate()
    {
        return $this->_departure_date;
    }

    public function getToday()
    {
        return $this->_today;
    }

    public function getRoomId()
    {
        return $this->_room_id;
    }

}
?>

Bookingmanager.php

<?php

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////                                                                           ///////////////////////
///////////////                             BOOKING MANAGER                               ///////////////////////
///////////////                                                                           ///////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class bookingManager
{
    private $_db;

    public function __construct($db)
    {
        $this->setDb($db);
    }

    public function setDb(PDO $dbh)
    {
        $this->_db = $dbh;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////                           Obtenir la liste des chambres             ////////////////
    ///////////////                                 pour un hôtel                       ////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////

    public function getRoomsByResortid($resort_id)
    {   
        $resort_id = $_POST['resort'];
        $arrival = $_POST['arrival'];
        $departure = $_POST['departure'];
        $sql = 'SELECT number, arrival_date, departure_date, room_id FROM rooms as o
            LEFT JOIN bookings as b on b.room_id = o.id
            INNER JOIN resorts as r on r.id = o.resort_id
            WHERE r.id = "'.$resort_id.'"'; // [...] "'.$resort_id.'" filtres en fonction des dates ';
        $stmnt = $this->_db->prepare($sql);
        $stmnt->execute();
        while ($row = $stmnt->fetch(PDO::FETCH_ASSOC)) 
        {
            $result[] = $row;
        }
        return $result; 
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////                           ajouter un client                         ////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////

    public function addBooking(Booking $booking)
    {
        $sql = 'INSERT INTO bookings (client_id, arrival_date, departure_date, booking_date, room_id)
                VALUES (:client_id, :arrival, :departure, :today, :room_id)';
        $stmnt = $this->_db->prepare($sql);
        $clientId = $booking->getClientId();
        $arrival = $booking->getArrivalDate();
        $departure = $booking-> getDepartureDate();
        $today = $booking->getToday();
        $roomId = $booking->getRoomId();
        $stmnt->bindParam('client_id', $clientId);
        $stmnt->bindParam('arrival', $arrival);
        $stmnt->bindParam('departure', $departure);
        $stmnt->bindParam('today', $today);
        $stmnt->bindParam('room_id', $roomId);
        $stmnt->execute();

        //gestion des erreurs
        $errors = $stmnt->errorInfo();
        if ($errors[0] != '00000') 
        {
            echo 'Erreur SQL (addbooking)' . $errors[2]; //suppr les ()
        }
        else
        {
            $success_msg = 'Les données ont bien été enregistrées en base de données';
        }
    }
}
?>

Ce que je veux

Je souhaiterais que chaque chambre puisse être attribuée une seule fois pour des dates définies.
Mais puisse aussi l'être pour d'autres dates
Ex: Si une chambre est prise du 01/01/2020 au 05/01/2020 elle ne pourra plus l'être pour ces mêmes dates mais pourra l'être pour toutes autres dates qui n'est pas incluse dans la fourchette du 01/01/2020 au 05/01/2020

Ce que j'obtiens

Si je ne filtre pas par dates voici que que j'obtiens

array (size=17)
  0 => 
    array (size=4)
      'number' => string '4' (length=1)
      'arrival_date' => string '2020-01-01' (length=10)
      'departure_date' => string '2020-01-05' (length=10)
      'room_id' => string '4' (length=1)
  1 => 
    array (size=4)
      'number' => string '2' (length=1)
      'arrival_date' => string '2020-01-01' (length=10)
      'departure_date' => string '2020-01-05' (length=10)
      'room_id' => string '2' (length=1)
  2 => 
    array (size=4)
      'number' => string '3' (length=1)
      'arrival_date' => string '2020-01-01' (length=10)
      'departure_date' => string '2020-01-05' (length=10)
      'room_id' => string '3' (length=1)
  3 => 
    array (size=4)
      'number' => string '3' (length=1)
      'arrival_date' => string '2020-01-01' (length=10)
      'departure_date' => string '2020-01-05' (length=10)
      'room_id' => string '3' (length=1)
  4 => 
    array (size=4)
      'number' => string '4' (length=1)
      'arrival_date' => string '2020-01-01' (length=10)
      'departure_date' => string '2020-01-05' (length=10)
      'room_id' => string '4' (length=1)

Voici ce que j'obtiens lorsque j'essaie de filter par dates

Notice: Undefined variable: result in C:\wamp64\www\PHP04-02-test\class\Bookingmanager.php on line 44

Voici les requêtes que j'ai essayé et qui ont entraînées cette erreur:

1) AND arrival_date < "'.$arrival.'" AND departure_date >= "'.$departure.'"
2) AND arrival_date == "NULL" AND departure_date == "NULL"
3), arrival_date<:arrival, departure_date>=:departure ';
            $stmnt = $this->_db->prepare($sql);
            $stmnt->bindParam(':arrival', $arrival);
            $stmnt->bindParam(':departure', $departure);
Avec et sans passer $arrival = '', $departure = '' en paramètres

D'avance merci à celles et ceux qui prendront la peine de me lire et de m'aider.

1 réponse


Avec cette requete tu n'auras que les chambres disponibles pour tes dates.

SELECT * 
FROM room
LEFT JOIN booking where departure_date < :arrival and arrival_date > :depature
GROUP by room.id 
HAVING count(booking.room_id) = 0

pour des dispo de dates il faut inverser tes comparaisons.
la date de début de l'un avec l'arrivée de l'autre et inversement.

Fais un schéma sur papier et tu comprendra mieux, en cas de chevauchement, plus grand ou plus petit, ca passe mieux.