Bonjour tout le monde,

Voilà, j'aurais besoin d'aide concernant une "amélioration" que j'aimerais apporter au Tuto Calendrier en PHP.
Je me sers du calendrier comme planning de réservation.
La problématique : Jusqu'à maintenant, en suivant le tuto, il suffisait d'insérer une ligne dans la base de données pour pouvoir la lire et l'intégrer au calendrier. C'est à la base un système d'événement. Donc une ligne = un événement.
J'aimerais, au lieu d'intégrer 1 seule ligne avec 1 seule date, mettre en place une plage de date.

Pour être plus claire, j'ai pour l'instant une table dans ma bdd de se type :

id : int(11)
dispo : boolean
statut : varchar(255)
date : date

Pour le moment, si dans ma bdd j'ai une ligne " 1, 1, 'Réservé', '01012014' ", alors la case du calendrier correspondant au 01012014 sera marquée comme événement.

Maintenant, j'aimerais avoir une table dans ma bdd de se type :

id : int(11)
datedebut : date
datefin : date
dispo : boolean
statut : varchar(255)

Si dans ma bdd j'ai une ligne " 1, '0101214', '14012014', 1, 'Réservé' ", je voudrais que toutes les dates comprises entre 01012014 et 14012014 soient marquées comme événement.

Voilà, donc pour le moment, on peut dire que 1 ligne = 1 date. Comment faire pour avoir 1 ligne = plusieurs dates ?

Merci d'avance !

Ma page calendrier.php :

<?php
            require('../includes/config.php');
            require('../includes/date.php');
            $date = new Date();
            $year = date('Y');
            $events = $date->getEvents($year);
            $dates = $date->getAll($year);   
        ?>
        <div class="periods">
            <!-- ######################### BLOC ANNÉE ############################ -->
            <center><div class="year"><?php echo $year; ?></div></center>
            <!-- ######################### FIN BLOC ANNÉE ######################## -->

            <!-- ######################### BLOC MOIS ############################# -->
            <div class="months">
                <ul>
                    <?php foreach($date->months as $id=>$m): ?>
                    <center><li><a href="" id="linkMonth<?php echo $id+1; ?>"><?php echo utf8_encode(substr(utf8_decode($m),0,3)); ?></a></li></center>
                    <?php endforeach; ?>
                </ul>
            </div>
            <!-- ######################### FIN BLOC MOIS ######################### -->

            <div class="clear"></div>
            <?php $dates = current($dates); ?>
            <?php foreach ($dates as $m=>$days): ?>

                <!-- ######################### BLOC TABLEAU ####################### -->
                <div class="month relative" id="month<?php echo $m; ?>">
                    <table>
                    <thead>

                        <!-- ######################### BLOC JOUR ####################### -->
                        <tr>
                            <?php foreach ($date->days as $d): ?>
                                <th><?php echo substr($d,0,8); ?></th>
                            <?php endforeach; ?>
                        </tr>
                        <!-- ######################### FIN BLOC JOUR ####################### -->

                    </thead>
                    <tbody>
                        <tr>
                        <?php $end = end($days); foreach($days as $d=>$w): ?>
                        <?php $time = strtotime("$year-$m-$d"); ?>
                            <?php if($d == 1 AND $w-1 > 0): ?>
                                <td colspan="<?php echo $w-1; ?>" class="padding"></td>
                            <?php endif; ?>
                            <td<?php if(isset($events$time])): ?> class="evenement"<?php endif; ?>>
                                <div class="relative">
                                    <div class="day"><?php echo $d; ?></div>
                                </div>
                                <div class="daytitle">
                                    <?php echo $date->days$w-1]; ?> <?php echo $d; ?> <?php echo $date->months$m-1]; ?>
                                </div>
                                <ul class="events">
                                    <?php if(isset($events$time])): foreach($events$time] as $e): ?>
                                        <li><?php echo $e; ?></li>
                                    <?php endforeach; endif; ?>
                                </ul>
                            </td>
                        <?php if($w == 7): ?>
                            </tr><tr>
                        <?php endif; ?>
                        <?php endforeach; ?>
                        <?php if($end != 7): ?>
                            <td colspan="<?php echo 7-$end; ?>" class="padding"></td>            
                        <?php endif; ?>
                        </tr>
                    </tbody>
                </table>
                </div>
            <?php endforeach; ?>
        </div>
        <div class="clear"></div>

Ma page date.php :

<?php
class Date{

    var $days = array('Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche');
    var $months = array('Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre');

    function getEvents($year){
        global $DB;
        $req = $DB->query('SELECT id, dispo, statut,date FROM calendrier WHERE YEAR(date)='.$year.' AND dispo = 1');
        $r = array();
        while($d = $req->fetch(PDO::FETCH_OBJ)){
            $r[strtotime($d->date)]$d->id] = $d->statut;
        }
        return $r;
    }

    function getAll($year){
        $r = array();
        $date = new DateTime($year.'-01-01');
        while($date->format('Y') <= $year){
            //Ce que je veux => $r[ANNEE][MOIS][JOUR] = JOUR DE LA SEMAINE
            $y = $date->format('Y');
            $m = $date->format('n');
            $d = $date->format('j');
            $w = str_replace('0', '7', $date->format('w'));
            $r$y]$m]$d] = $w;
            $date->add(new DateInterval('P1D'));
        }
        return $r;
    }

}

Mon formulaire d'insertion :

<form action="../admin/liste_reservation.php" method="post">
                        <label for="datedebut">Date de début du Séjour :</label>
                        <input type="date" name="datedebut" id="datedebut" value="<?php echo $datedebut; ?>" class="form-control" style="width:40%;"><br />
                        <label for="datefin">Date de fin du Séjour :</label>
                        <input type="date" name="datefin" id="datefin" value="<?php echo $datefin; ?>" class="form-control" style="width:40%;"><br />
                        <br>
                        <input type="hidden" name="id_news" value="<?php echo $id_reservation; ?>" />
                        <button type="submit" value="Envoyer" class="btn btn-success btn-small">Envoyer</button>
                    </form>

Le traitement du formulaire :

if (isset($_POST'datedebut']) AND isset($_POST'datefin']))
                                {
                                    $datedebut = addslashes($_POST'datedebut']);
                                    $datefin = addslashes($_POST'datefin']);
                                    // On vérifie si c'est une modification de news ou non.
                                    if ($_POST'id_reservation'] == 0)
                                    {
                                        global $DB;
                                        $req = $DB->query("INSERT INTO calendrier(id, datedebut, datefin, dispo, statut) VALUES('', '" . $datedebut . "', '" . $datefin . "', 1, 'Réservé')");
                                        // Ce n'est pas une modification, on crée une nouvelle entrée dans la table.
                                    }
                                    else
                                    {
                                        // On protège la variable "id_reservation" pour éviter une faille SQL.
                                        $_POST'id_reservation'] = addslashes($_POST'id_reservation']);
                                        // C'est une modification, on met juste à jour les dates.
                                        global $DB;
                                        $req = $DB->query("UPDATE calendrier SET datedebut='" . $datedebut . "', datefin='" . $datefin . "' WHERE id='" . $_POST'id_reservation'] . "'");
                                    }
                                }

7 réponses


azerus
Réponse acceptée

Dans ce cas la, comme je l'ai expliqué :

  1. Tu récupères les événements depuis ta base de données
  2. Tu associes tes événement a un jour du calendrier

    function getEvents($year){
    global $DB;
    $req = $DB->query('SELECT id, title, datedebut, datefin FROM calendrier WHERE YEAR(date)='.$year); // Recuperation des evenements
    $r = array();
    while($d = $req->fetch(PDO::FETCH_OBJ)){ // Pour chaque evenement recupere depuis la base
    $debut = strtotime($d->datedebut); // On recupere la date de debut de la plage
    $fin = strtotime($d->datefin); // On recupere la date de fin de la plage
    $cursor = $debut; // On cree un curseur qui passera pas tous les jours de l'evenement
    while ($cursor <= $fin) { // On parcourt tous les jours de la plage de l'evenement
    $r$cursor]$d->id] = $d->statut; // On ajout a la journee actuelle l'evenement
    $cursor += 86400; // On ajoute un journee pour passer au jour suivant
    }
    }
    return $r;
    }

Chaque événement est alors dispatché sur tous les jours qui le compose.

  1. Tu créés ton calendrier jour par jour, comme fait actuellement

Je ne vois pas comment être plus précis (déjà que je n'aime pas donner du code .....), et espère avoir été assez clair pour que tu comprennes l'idée.

Azerus

Bonjour,

Si j'ai bien compris, tu sais comment le stocker, mais pas comment l'utiliser après ?
Si oui, alors je te conseillerais de le faire en ajoutant une partie javascript pour ajouter les plages à ton calendrier.

  1. Affichage des différents éléments du calendriers VIDE en PHP
  2. Chargement et stockage des différentes plages dans le code javascript
  3. Pour chaque plage :
    a) sélectionner la plus grande date entre la date de début de l'affichage de ton calendrier et la date de début de ta plage
    b) sélectionner la plus petite date entre la date de fin de l'affichage de ton calendrier et la date de fin de ta plage
    c) parcourir les jours entre les 2 dates de a) et b) pour les ajouter au calendrier

Je pense qu'il s'agit de la façon la plus simple de gérer ton problème.
Je ne peux pas être plus précis sur l'affichage des différentes plages dans ton calendriers, car cela dépend du rendu que tu veux avoir.

J'espère avoir répondu à tes questions.

Azerus

Bonjour Azerus,

Merci de ta réponse. Cependant, je ne suis déjà pas forcément une flèche en PHP (bien que je me débrouille un minimum) mais en JavaScript.. c'est même pas la peine.

Le soucis c'est qu'en fait, pour une date fixe, sa fonctionne très bien, mais je voudrais faire le même système avec une plage de date.

Autre proposition :

Après récupération de tes evenements, tu les parcours pour créé le tableau de cache que tu fait actuellement :
Pour chaque jour de la plage de l'evenement, tu rajoutes l'évènement à la journée.

L'inconvénient est que tu ne pourras pas visuellement et simplement voir qu'un evenement est sur plusieurs jours ou non.

L'avantage est que c'est beaucoup plus simple ^^

Azerus

Je vais tâcher d'être plus claire (désolé, c'est pas forcément facile d'expliquer son besoin ^^")

Prenons la démonstration du calendrier proposé par GrafikArt : http://www.grafikart.fr/demo/PHP/calendar/index.html

On voit sur le calendrier, des puces, puces qui servent à marquer un événement.

L'affichage de ses événements se fait par le biais d'une lecture dans la bdd.
Un enregistrement se fait de la sorte suivante : ID, TITLE, DATE
Donc chaque événements est caractérisés par une et une seule DATE.
Un événement est marqué dans le calendrier comme suit :

function getEvents($year){
    global $DB;
    $req = $DB->query('SELECT id, title, date FROM calendrier WHERE YEAR(date)='.$year);
    $r = array();
    while($d = $req->fetch(PDO::FETCH_OBJ)){
        $r[strtotime($d->date)]$d->id] = $d->statut;
    }
    return $r;
}
--------------------------------------------------------------------------------------------
<ul class="events">
    <?php if(isset($events$time])): foreach($events$time] as $e): ?>
        <li><?php echo $e; ?></li>
    <?php endforeach; endif; ?>
</ul>

Moi je voudrais qu'un événement se caractérise par un ensemble de DATE (datedebut et datefin par exemple).
Si datedebut = 01012014 et datefin = 14012014, je voudrais que les 14 jours soient marqués d'une puce.

Le formulaire, l'insertion et la lecture dans la base de données n'est pas un problème, ce que je cherche à faire, c'est comment les afficher.

Voilà, en espérant avoir été plus claire,
Merci d'avance, et merci de votre patience

Bonjour Azerus,

ton code fonctionne parfaitement, je te remercie beaucoup !

J'avais déjà du mal avec la POO, mais la notion de curseur en MySQL m'était inconnue jusqu'à ce jour.
Quel dommage que cette notion ne soit pas abordée en cours d'SQL lorsque j'étais à la Fac...

Je dormirais désormais moins bête !

Merci encore !

Juste pour indication, ce n'est pas un curseur en MySQL, c'est juste une variable PHP.
Je l'appelle $cursor car elle indique à quelle date on est dans une boucle.
Grosso modo, c'est comme une barre de chargement :

0% ====> ] 40%

0% = date de debut
100% = date de fin
40% = curseur, par exemple, je suis au 4eme jour sur 10 de l'evenement.

J'espere avoir ete plus clair.

Azerus