Méthode pour une appli en ligne de réservation de salles

Eléphanteau du PHP | 38 Messages

05 juin 2006, 12:24

Bonjour,

Je souhaiterais réaliser une application en ligne pour pouvoir réserver des salles (pas toujours pour la même durée).

Mon soucis étant de ne pas me retrouvé coincé en cours de dév. j'aurais voulu avoir votre avis sur la meilleure méthode pour le faire dès le début.

Pensez-vous qu'il faille :

une table contenant un calendrier avec les plages horaires dans laquelle je viendrais y insérer des id de salle ?

une table par salle contenant un calendrier avec les plages horaires ?

une table de réservation (jointures ? si c'est le terme adéquat) qui contiendrait les id de salle, la date, ainsi que l'id de la plage horaire, dont le contenu est à comparer avec la fabrication du calendrier pour savoir si la plage est réservée ou non ?

Je ne sais pas trop vers quelle option m'orienter, vos éclaircissements sont bienvenus.
De même, ne voulant pas réinventer la roue, si il existe des éléments de ce type 'customisable', ça m'intéresse aussi ;)

Merci

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

05 juin 2006, 13:21

La méthode de pensée conceptuelle veut que les ensembles de données soient conçus comme suit:
  • 1. la salle est un individu indépendant de la réservation
    2. le calendrier est un individu indépendant de la réservation
    2. la reservation est une association de salle et d'une plage horaire constituée de 2 date/heures debut et fin distribuées par le calendrier
    C'est une association ternaire :
    salle 0,n<--- réserver
    réserver --- début ---> 0,n calendrier (date/heure)
    et réserver --- fin ---> 0,n calendrier (date/heure)
La reservation d'une salle se fait pour une date/heure de début à une date/heure de fin si cette même salle n'est pas déjà réservée dans la plage horaire désignée.
Autrement dit, la plage (date/heure début, date/heure fin) ne doit pas s'imbriquer dans une autre plage de reservation existante pour la même salle
Cette règle doit être vérifiée à l'ajout et la modification d'une réservation qui joint une salle et deux horaires (date/heure)

On peut simplifier le modèle relationnel issu de cette conception en éliminant l'objet "calendrier" vu qu'un objet "réserver" sera créé et qui sera porteur d'un couple date/heure début et fin
Sous réserve bien sûr d'ajouter une régle à vérifier : fin > début

La requête qui doit vérifier si une salle est déjà réservée, peut être du style:

compter le nombre de réservations existantes pour la plage $debut et $fin et pour la salle $id_salle :

Code : Tout sélectionner

select count(id_salle) as compte from réserver where ('$debut' between debut and fin or '$fin' between debut and fin) and id_salle = '$id_salle'
Si ce compte est égal à 0 alors la réservation est valide
Modifié en dernier par sadeq le 06 juin 2006, 09:06, modifié 5 fois.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Mammouth du PHP | 1511 Messages

05 juin 2006, 13:28

Tiens, tant qu'on parle de la requete count(), comment traiter le resultat de celle-ci ?
@+

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

05 juin 2006, 13:34

Tiens, tant qu'on parle de la requete count(), comment traiter le resultat de celle-ci ?
@+
sous PHP ceci peut être écrit comme ça:
$sql = "select count(id_salle) as compte from réserver where ('$debut' between debut and fin or '$fin' between debut and fin) and id_salle = '$id_salle'";

//Si c'est mysql comme SGBD
$resultat = mysql_query($sql);

//Récupèrer le compte
if ($resultat) {
 $ligne = mysql_fetch_array($resultat); //Lecture du résultat
 $compte = $ligne["compte"]; //accès au champ nommé compte dans la requête
}
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Mammouth du PHP | 1511 Messages

05 juin 2006, 13:39

Et cela m'affichera le nombre de champs que j'ai selectionné??
hmm, c'est tout bon tout ca!
@+

Eléphanteau du PHP | 38 Messages

05 juin 2006, 13:46

Merci pour ces infos,
je reviendrais sans doute vers vous dans le forum Débuter en PHP, si j'ai des soucis dans l'avancement,

Merci,
comme quoi :
Prendre le recul n'est pas une perte de temps. ;)

ViPHP
ViPHP | 2144 Messages

05 juin 2006, 16:14

Ca, on ne peut que te féliciter de prendre le temps de faire une modélisation correcte avant de commencer à coder. :pouce:
Quand on voit le nombre de gens qui se retrouvent en cours de devellopement, à patauger avec une modélisation complétement bancale, et qui veulent des astuces pour ne pas retoucher ce qu'ils appelent une base de donée :wink: :wink:

Bonne chance pour la suitej et n'hésite pas à demander un coup de main si nécessaire.

Petit nouveau ! | 2 Messages

19 nov. 2010, 10:19

Bonjour à tous,

Je viens avec ma requête qui ne me donne pas le résultat escompté. Au fait, dans ma table reservation j'ai une salle qui est réservée pour la période du 18.11.10 au 18.11.10. Avec select * from reservation; // Ok j'arrive à trouver la salle n°3 mais malheureusement pas avec la requête qui suit:
select count(RESERVATION.id) as compte from RESERVATION where ( (to_date('18/11/10','dd.mm.yy') between RESERVATION.debut  and  RESERVATION.fin) or  (to_date('18/11/10','dd.mm.yy') between RESERVATION.debut  and  RESERVATION.fin )) and RESERVATION.salle ='salle3';
Voici la structure de ma table:
Create table RESERVATION
(
  id number(10) not null, 
  debut date not null, 
  fin date not null, 
  salle varchar2(100 char) not null,
  details varchar2(100 char) not null
);
Je dois faire la recherche avant d'insérer une nouvelle réservation. Je suis sous Oracle et java.
Je trouve que la requête postée par Sadeq correspond bien au moins mais je sais pourquoi?

Merci d'avance pour aide

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

09 déc. 2010, 10:41

Bonjour Nanina, vérifie bien si tu n'as pas d'espaces inutiles dans le champ RESERVATION.salle car c'est un varchar2(100 char) sa taille est fixée à 100 caractères et des fois quand l'insertion des données est faite par une requête d'importation ou d'insertion le système Oracle remplie le reste de la taille de la chaine avec des espaces.
Le mieux et de purger les espaces inutiles dans une chaine comparée par la fonction TRIM() dans les requêtes SELECT.

Essaye donc cette variante de ta requête:
SELECT count(RESERVATION.id) AS compte FROM RESERVATION WHERE ( (to_date('18/11/10','dd.mm.yy') BETWEEN RESERVATION.debut  AND  RESERVATION.fin) OR  (to_date('18/11/10','dd.mm.yy') BETWEEN RESERVATION.debut  AND  RESERVATION.fin )) AND TRIM(RESERVATION.salle) ='salle3';
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

nanina00
Invité n'ayant pas de compte PHPfrance

19 janv. 2011, 00:41

Bonjour sadeq,

J'ai suivi ta recommandation mais rien à faire j'ai même essayé d'effacer les espaces à gauche avec LTRIM spécialement Oracle toujours négatif. Mais il y a une chose que je ne comprend pas quand je teste avec une date comme 15/10/10 j'ai le bon résultat j'avoue que je n'arrive pas à comprendre.
SELECT count(RESERVATION.id) AS compte FROM RESERVATION WHERE ( (to_date('18/11/10','dd.mm.yy') BETWEEN RESERVATION.debut  AND  RESERVATION.fin) OR  (to_date('18/11/10','dd.mm.yy') BETWEEN RESERVATION.debut  AND  RESERVATION.fin )) AND LTRIM(RESERVATION.salle) ='salle3';
Merci beaucoup pour ton aide

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

19 janv. 2011, 18:03

A priori, je pense que tu dois virer le dernier point-virgule de ta requête SQL concernant ORACLE.
Par ailleurs, j'ai refais le test pas mal de fois chez moi, et ta requête continue de fonctionner très bien. Voici, si ça peut t'aider, le programme de test que j'ai fait:
<pre>
<?php
### Requêtes utilisées pour le test 
$requêtes[] = "CREATE TABLE RESERVATION_TMP (id INT, debut DATE, fin DATE, salle VARCHAR2(100 CHAR) )";
$requêtes[] = "DELETE FROM RESERVATION_TMP";
### Jeu de données pour le test
$requêtes[] = "INSERT INTO RESERVATION_TMP VALUES (1, '13/12/1999','14/12/1999', 'salle1')";
$requêtes[] = "INSERT INTO RESERVATION_TMP VALUES (2, '13/12/1999','19/12/1999', 'salle2')";
$requêtes[] = "INSERT INTO RESERVATION_TMP VALUES (3, '15/12/1999','16/12/1999', 'salle1')";
$requêtes[] = "INSERT INTO RESERVATION_TMP VALUES (4, '17/12/1999','19/12/1999', 'salle1')";
$requêtes[] = "SELECT * FROM RESERVATION_TMP";
### La requête de recherche des réservations de la salle1 par date
$requêtes[] = "SELECT count(RESERVATION_TMP.id) AS compte FROM RESERVATION_TMP 
WHERE ( (to_date('15/12/1999','dd/mm/yy')  BETWEEN RESERVATION_TMP.debut  AND  RESERVATION_TMP.fin) 
OR  (to_date('17/12/1999','dd/mm/yy')  BETWEEN RESERVATION_TMP.debut  AND  RESERVATION_TMP.fin )) 
AND TRIM(RESERVATION_TMP.salle) ='salle1'";

### Connexion à la base Oracle dans mon cas : le service XE local d'oracle 10g
$conn = oci_connect('hr', 'hr', 'localhost/XE') or die("<p>Connexion impossible : " . oci_error()) . "</p>";
echo "<p>Connexion réussie</p>";

## Exécution du lot de requêtes prévues dans le tableau $requêtes
foreach($requêtes as $index=>$sql){
	$req = @oci_parse($conn, $sql); if (!$req) echo ("<p>Erreur préparation requête ($index)</p>");
	@oci_execute($req); if (!$req) echo ("<p>Erreur d'exécution requête ($index)</p>");

	## Afficheur du résultat des requêtes SELECT
	while($req && ($ligne = @oci_fetch_array($req, OCI_ASSOC+OCI_RETURN_NULLS)))
	{
		print_r($ligne);
	}
}
## Fin
oci_close($conn);
?>
</pre>
Le résultat de ce programme php est le suivant:
Connexion réussie
Array
(
[ID] => 3
[DEBUT] => 15/12/99
[FIN] => 16/12/99
[SALLE] => salle1
)
Array
(
[ID] => 4
[DEBUT] => 17/12/99
[FIN] => 19/12/99
[SALLE] => salle1
)
Array
(
[ID] => 1
[DEBUT] => 13/12/99
[FIN] => 14/12/99
[SALLE] => salle1
)
Array
(
[ID] => 2
[DEBUT] => 13/12/99
[FIN] => 19/12/99
[SALLE] => salle2
)
Array
(
[COMPTE] => 2
)
Le dernier Array ([COMPTE]=>2 ) est le résultat de la requête qui te tracasse :
SELECT count(RESERVATION_TMP.id) AS compte FROM RESERVATION_TMP 
WHERE ( (to_date('15/12/1999','dd/mm/yy')  BETWEEN RESERVATION_TMP.debut  AND  RESERVATION_TMP.fin) 
OR  (to_date('17/12/1999','dd/mm/yy')  BETWEEN RESERVATION_TMP.debut  AND  RESERVATION_TMP.fin )) 
AND TRIM(RESERVATION_TMP.salle) ='salle1'
Ce résultat est correct car dans mon jeu d'essai de données, il y a bien 2 réservations pour la salle1 pour le 15 et 17 décembre 1999.

A+
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

nanina00
Invité n'ayant pas de compte PHPfrance

24 janv. 2011, 12:19

Bonjour sadeq, Tout d'abord je tiens à te remercier pour le temps que tu prends pour m'aider. Maintenant je veux faire le test mais, je ne sais pas si Oracle va accepter une instruction sans le point virgule mais je te donne aussitôt la suite. Merci et A+

nanina00
Invité n'ayant pas de compte PHPfrance

25 janv. 2011, 17:05

Merci Sadeq, je viens de me rendre compte que l'erreur vient du pattern quand je modifie l'année à 4 digits tout va bien le résultat est correct, mais par contre quand je la modifie à 2 digits pas de résultat alors que les données concernant l'année dans ma base est à 2 digits du style: 18.10.10 et depuis mon programme java l'insertion dans la base est du style: 18/10/10. Je ne sais pas qu'est-ce que je n'ai pas compris jusqu'ici. OK avec to_date('19/11/10','dd.mm.yyyy') et non, avec to_date('19/11/10','dd.mm.yy').
Merci beaucoup à toute personne qui serait prête à m'éclairer sur ce sujet.

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

25 janv. 2011, 17:51

Bonjour, pour éviter le problème de l'an 2000 il faut exprimer les dates fournies en paramètres de recherche avec l'année sur 4 sous le format yyyy comme le 15/12/1999.
Dans mon exemple, j'ai utilisé la date 1999 pour éviter la conversion relative de la fonction to_date() de la partie du siècle de l'année.

Donc, si j'avais exprimé ma date du 15/12/1999 dans la fonction to_date() avec l'année sur 2 comme : to_date('15/12/99', 'dd/mm/yyyy') cela donnerait en fait après conversion la date: 15/12/2099 et non 15/12/1999. Ce qui est trompeur.
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

nanina00
Invité n'ayant pas de compte PHPfrance

25 janv. 2011, 18:08

Salut Sadeq, je pense que l'erreur vient de moi lors des insertions dans la base le pattern était avec to_date(18/11/10,'dd/mm/yyyy') voilà pourquoi je n'ai pas de résultat avec to_date(18/11/10,'dd/mm/yy') c'est logique. S'il y a quelques remarques à me faire je reste ouvert. En tout merci beaucoup et à bientôt.