Bonjour,

Voila je rencontre un petit problème avec mon code.

Ce que je fais

Table bookings

+-----------+----------+------+-----+---------+-------+
| Field     | Type     | Null | Key | Default | Extra |
+-----------+----------+------+-----+---------+-------+
| id        | int(11)  | NO   | PRI | NULL    |       |
| room_id   | int(11)  | NO   |     | NULL    |       |
| check_in  | date     | NO   |     | NULL    |       |
| check_out | date     | NO   |     | NULL    |       |
| created   | datetime | NO   |     | NULL    |       |
| modified  | datetime | NO   |     | NULL    |       |
+-----------+----------+------+-----+---------+-------+
$check_in = new Date($this->request->data['check_in']);
$check_out = new Date($this->request->data['check_out']);
$bookings = $this->Bookings->find('all')
 ->contain(['Rooms'])
 ->where([
    'Bookings.check_in <=' => $check_in,
    'Bookings.check_out >=' => $check_out
]);

Ce que je veux

Je souhaite afficher les chambres disponible en fonction d'une date d'entrée ($this->request->data['check_in']) et d'une date de sortie ($this->request->data['check_out']), je tourne en rond dans ma réflexion, puis-je le faire en une seul requête ou au contraire en plusieurs ?

Exploration en cours :

$rooms = $this->Rooms->find('all')
->contain(['Bookings'])
->matching('Bookings', function ($q) use ($check_in, $check_out) {
    return $q->where([
        'Bookings.check_in <=' => $check_in,
        'Bookings.check_out >=' => $check_out
    ]);
});

6 réponses


Bed0sk!l
Auteur
Réponse acceptée

C'est bon avec le notMatching

$roomsAvailable = $this->Rooms->find('all')
->contain(['Bookings'])
->notMatching('Bookings', function ($q) use ($check_in, $check_out) {
    return $q
        ->where(function ($q) use ($check_in, $check_out) {
                return $q->between('Bookings.check_in', $check_in, $check_out);
            }
        )
        ->orWhere(function ($q) use ($check_in, $check_out) {
            return $q->between('Bookings.check_out', $check_in, $check_out);
        }
        );
});

Merci pour ta contribution.

Ca doit être faisable en une seule requête dans ce genre :

    $rooms = $this->Rooms->find('all')
            ->contain(['Bookings'])
            ->matching('Bookings', function ($q) use ($check_in, $check_out) {
                return $q
                    ->where(['NOT' => function ($q) use ($check_in, $check_out) {
                            return $q->between('Bookings.check_in', $check_in, $check_out);
                        }
                    ])
                    ->orWhere(['NOT' => function ($q) use ($check_in, $check_out) {
                        return $q->between('Bookings.check_out', $check_in, $check_out);
                    }
                    ]);
            });
Bed0sk!l
Auteur

Merci @Kareylo, en effet ta requête m'affiche les chambres booké, seulement je souhaite les chambres non booké, la requête que j’effectue en SQL :

$results = $connection
->execute('
    SELECT 
        rooms.id
    FROM 
        rooms 
    LEFT JOIN 
        bookings 
        ON (
            bookings.room_id = rooms.id AND 
            NOT ( 
                (bookings.check_in < :check_in and bookings.check_out < :check_in) 
                OR
                (bookings.check_in > :check_out and bookings.check_out > :check_out) 
            )
        ) 
    WHERE 
        bookings.room_id IS NULL;
', 
[
    'check_in' => $check_in->format('Y-m-d'),
    'check_out' => $check_out->format('Y-m-d')
])
->fetchAll('assoc');

Sais tu si je peux l’effectuer avec le SQL Query de CakePHP pour respecter la syntaxe ?

Tu retires juste les 'NOT' => :)
donc :

  $rooms = $this->Rooms->find('all')
            ->contain(['Bookings'])
            ->matching('Bookings', function ($q) use ($check_in, $check_out) {
                return $q
                    ->where(function ($q) use ($check_in, $check_out) {
                            return $q->between('Bookings.check_in', $check_in, $check_out);
                        }
                    )
                    ->orWhere(function ($q) use ($check_in, $check_out) {
                        return $q->between('Bookings.check_out', $check_in, $check_out);
                    }
                    );
            });
Bed0sk!l
Auteur

J'ai toujours les chambres non disponibles avec les deux requêtes, c'est à n'y rien comprendre

Effectivement, c'est à ne rien y comprendre...