Liste déroulante sur 12 mois a partir du mois courant

Rechercher

Liste déroulante sur 12 mois a partir du mois courant

Par paintbox  -  11 reponses  -  Le 22/04/2011 16:08  -  Editer  - 

Hello Cyrano,

 

me revoilà une fois de plus pour quelques conseils.

 

Je cherche à afficher une liste déroulante qui liste les mois depuis le mois courant Avril 2011 jusque 12 mois en arrière soit Mai 2010.

 

Cela fonctionne parfaitement, mais je ne trouve pas mon code très "propre". Qu'en pense-tu? Vois tu une autre façon d'y arriver?

 

De plus, je n'arrive pas à utiliser ma fonction month sur la même ligne que ma variable $search_year. Comment l intégrer?

 

Pour info, je récupère après ces données pour interroger ma BD.

 

Voici mes 2 fonctions :

function month($m){ /*Traduction mois*//*------------*/  if ($m=="1")  {    $mois="Janvier";  }  elseif($m=="2")  {    $mois="Février";  }  elseif($m=="3")  {    $mois="Mars";  }  elseif($m=="4")  {    $mois="Avril";  }  elseif($m=="5")  {    $mois="Mai";  }  elseif($m=="6")  {    $mois="Juin";  }  elseif($m=="7")  {    $mois="Juillet";  }  elseif($m=="8")  {    $mois="Aout";  }  elseif($m=="9")  {    $mois="Septembre";  }  elseif($m=="10")  {    $mois="Octobre";  }  elseif($m=="11")  {    $mois="Novembre";  }  elseif($m=="12")  {    $mois="Décembre";  }return $mois;} function SelectMois($current_month, $search_month, $current_year, $search_year){?><SELECT name="date" id="date" size="1" style="width:200px;" onchange="document.forms['monform'].submit();"><?phpecho '<OPTION>Sélectionnez un mois</OPTION>';for ($m=$current_month; $m>=1; $m--){    echo '<OPTION value='.sprintf("%02d",$m).''.$current_year.'>';    echo month($m);    echo ' - '.$current_year;}for ($m=12; $m>=$search_month; $m--){    echo '<OPTION value='.sprintf("%02d",$m).''.$search_year.'>'; // sprintf force l affichage a 2 nbres    echo month($m);    echo ' - '.$search_year;}echo '</OPTION>';echo '</SELECT>';}

 

Et voici mon code :

 

<?php// Recherche de la date du jour$date_courante = getdate();$current_month = $date_courante["mon"];$current_year  = $date_courante["year"]; // Date de recherche$search_month  = $current_month+1;$search_year   = $current_year-1; // On fait une boucle pour parcourir les mois jusque mois courantecho '<form action="'.$_SERVER['PHP_SELF'].'" method="post" name="monform" id="monform">';SelectMois($current_month, $search_month, $current_year, $search_year);if (isset($_POST['date'])){    $SelectedMonth = substr($_POST['date'], 0 ,2);    $SelectedYear  = substr($_POST['date'], 2 ,4);}else{    echo '<p>Pas de choix</p>';}echo '</form>';?>

 

 

 

Merci pour ton aide.

 

Réponses apportées à cette discussion

Par Cyrano  -  Le 22/04/2011 18:16  -  Haut de page  - 

Salut paintbox.

Effectivement, ce code est un peu crade et surtout tu t'es compliqué la vie pour rien.

Tant qu'à utiliser sprintf, ce qui est du reste une bonne idée, ne fais pas les choses à moitié. Là je crois que tu vas peut-être découvrir un truc : tu fais deux boucle, une pour l'année courante, une autre pour l'année précédente. Le truc du jour : on peut avoir des arguments multiples dans une boucle for et traiter certains éléments selon certaines conditions de valeurs du curseur principal.

Je te mets d'abord le code complet, on va décortiquer après :

<?php
/**
 * Construction de la liste de choix du mois
 *
 * @param   Int     $current_month  Mois courant
 * @param   Int     $current_year   Année courante
 * @param   Array   $month          Liste des mois en français
 * @param   String  $sSelect        Code HTML d'une balise SELECT
 * @param   String  $sOption        Code HTML d'une balise OPTION
 * @param   Int     $selectedDate   Mois récupéré en POST_DATA
 * @return  String  Code complet de la liste de sélection.
 */
function SelectMois($current_month, $current_year, $month, $sSelect, $sOption, $selectedDate = null)
{
    $options = sprintf($sOption, '-1', 'Sélectionnez un mois');
    for($i = 0, $m = $current_month, $y = $current_year; $i < 12; $i++, $m--)
    {
        if($m < 1)
        {
            $m = 12;
            $y--;
        }
        $value = sprintf("%02d",$m) .''. $current_year;
        if(!is_null($selectedDate) && $selectedDate == $value)
        {
            $value .= '" selected="selected';
        }
        $label = $month[(int)$m] ." - ". $y;
        $options .= sprintf($sOption, $value, $label);
    }
    $select = sprintf($sSelect, $options);
    return $select;
}
$month = array(
     1 => 'Janvier',
     2 => 'Février',
     3 => 'Mars',
     4 => 'Avril',
     5 => 'Mai',
     6 => 'Juin',
     7 => 'Juillet',
     8 => 'Août',
     9=> 'Septembre',
    10=> 'Octobre',
    11 => 'Novembre',
    12 => 'Décembre'
);
/**
 * Code du formulaire
 */
$sForm = <<<CODE_HTML
<form action="{$_SERVER['PHP_SELF']}" method="post" name="monform" id="monform">
  <p>
%s  </p>
</form>
CODE_HTML;
/**
 * Code de la liste de sélection
 */
$sSelect = <<<CODE_HTML
    <select name="date" id="date" size="1" style="width:200px;" onchange="document.forms['monform'].submit();">
%s    </select>
CODE_HTML;
/**
 * Code pour une option de sélection
 */
$sOption = <<<CODE_HTML
      <option value="%s">%s</option>
CODE_HTML;
$selectedDate = isset($_POST['date']) ? $_POST['date'] : null;
// Recherche de la date du jour
$current_month = date('m');
$current_year  = date('Y');
$listeChoix = SelectMois($current_month, $current_year, $month, $sSelect, $sOption, $selectedDate);
$formulaire = sprintf($sForm, $listeChoix);
echo($formulaire);
?>

Les mois de l'année, ça ne changera pas pour un certain nombre de decennies encore voire quelques siècles : créer une fonction pour ça me semble très exagéré quand un tableau indexé suffirait. Du coup au lieu d'aller chercher month(3), tu vas chercher $month[3] pour exactement le même résultat.

Ensuite ta fonction de création de liste : beuarkkk tu fermes des boucles avant de fermer des options... une question me triture l'esprit : t'es-tu avisé de regarder la source générée de ce truc ? ([Ctrl]+[U] dans n'importe quel navigateur)

Déjà, tu vas peut-être trouver ça plus facile à suivre. Une seule fonction avec ses commentaires : n'oublie pas que si c'est frais maintenant, dans six mois tu vas passer du temps si tu veux la réutiliser rien que pour comprendre les données attendues, donc toujours commenter le code d'une fonction. Deux paramètres ont sauté, trois sont apparus.On va y revenir

Après la fonction, je définis des éléments HTML dans du code avec une syntaxe HEREDOC (regarde dans la documentation si ça ne te parle pas) Sommairement, c'est une chaine de caractère qui va garder son formattage en sortie. Chacune sera utilisée avec la fonction sprintf et la fonction va construire une chaine complete avant un quelconque affichage.

Prends cette habitude : une fonction est faite pour traiter de la donnée, pas pour l'afficher : donc, je te recommande très vivement de privilégier la méthode que je te montre ici : les echo partout, c'est vilain et ingérable en maintenance, et si tu regardes mon code, il n'y en a plus qu'un seul. Mieux que ça : tu veux utiliser ton formulaire de choix de date ailleurs ? mets ça dans un fichier externe et tu pourras l'utilier partout, il suffira d'inclure le fichier et de d'ajouter dans la page en question un écho sur la liste de choix. Magique non ?

Bon on continue : les dates : get_date, pas mal, mais compliqué pour rien , date() est parfaite pour ça. Et puis on a besoin que de l'année et du mois courant, pas de ceux de l'an dernier. Une année a toujours 12 mois et aura toujours douze mois, on coupe donc deux variables inutiles, et les deux paramètres correspondant ont sauté de ta fonction.

La fonction maintenant, avec l'astuce du jour pour tes notes : comment est-ce que je gère le passage de janvier à décembre ? Regarde bien les paramètres de la boucle for ()

Une boucle for a trois paramètres :

  • La situation de départ;
  • La condition de sortie;
  • une action menant vers la sortiePour la première, on est pas limité à une seule assignation, on peut très bien en inscrire plusieurs séparées par des virgules. Donc ici je mets un curseur $i à 0. J'ai aussi besoin du mois de départ, donc aujourd'hui 04 puisqu'on est en avril, et puis l'année aussi, donc ici 2011. Ensuite le second paramètre, la condition de sortie : je dois sortir après douze tours : $i au départ valant 0,tant que $i vaut moins de 12, je boucle. Et enfin l'action qui mène vers la sortie, on passe au mois suivant, j'incrémente mon curseur et je peux ajouter aune autre action : je décrémente le mois..

Le passage de janvier 2011 à décembre 2010 maintenant : Comme je décrémente le mois à chaque tour, il va arriver qu'après le traitement de janvier, il sera à zéro : pas de problème, s'il est à zéro, je lui ré-assigne une valeur 12.. et on est en décembre. Du coup, il faut que je décrémente l'année. Et le tour est joué.

Un petit détail que tu remarqueras peut-être : dans la fonction, pour créer le label qui sera affiché pour l'option, j'ai écrit « $month[(int)$m] » au lieu de mettre simplement « $month[$m] » : le « (int) » est une forme de CAST pour forcer le type de valeur :si $m vaut « 04 », l'index « 4 » ne sera pas trouvé dans le tableau des mois : si je force le type, il va convertir le « 04 » en « 4 ». Alternative : remplacer les index entiers du tableau en chaines de caractères et incrire '04' => 'Avril' au lieu de 4 => 'Avril'.

Allez, il faut que je te laisse un peu de travail de réflexion aussi, regarde et analyse comment je gère la pré-sélection de l'item approprié si j'envoie le formulaire et que le mois sélectionné doit à nouveau être sélectrionné au rechargement : je ramasse les copies dans deux heures :P

En attendant, tu pourras regarder la source générée, c'est bien propre :

<form action="/_Temporaire/_tmp/PaintBox/formulairedates.php" method="post" name="monform" id="monform">
  <p>
    <select name="date" id="date" size="1" style="width:200px;" onchange="document.forms['monform'].submit();">
      <option value="-1">Sélectionnez un mois</option>
      <option value="042011">Avril - 2011</option>
      <option value="032011">Mars - 2011</option>
      <option value="022011">Février - 2011</option>
      <option value="012011">Janvier - 2011</option>
      <option value="122011">Décembre - 2010</option>
      <option value="112011" selected="selected">Novembre - 2010</option>
      <option value="102011">Octobre - 2010</option>
      <option value="092011">Septembre - 2010</option>
      <option value="082011">Août - 2010</option>
      <option value="072011">Juillet - 2010</option>
      <option value="062011">Juin - 2010</option>
      <option value="052011">Mai - 2010</option>
    </select>
  </p>
</form>

 

 

 
Par paintbox  -  Le 22/04/2011 19:05  -  Haut de page  - 

Hello Cyrano,

merci pour ces explications très complètes.

Effectivement le code généré dans le navigateur est loin d'être "Joli". Je m'en doutais !

La boucle for à 3 paramètres c'est très fort et nouveau pour moi, mais je sents que cela me sera très utile à l'avenir.

Je vais également me plonger dans la syntaxe HEREDOC (que tu m'avais déjà conseillé d'utiliser).

J'avoue que je vais analyser cela à tête reposée et noter tous tes bons conseils afin d'améliorer ma technique de codage.

Bref je décortique tout cela et te reviens certainement avec quelques questions.

Merci !

 
Par Cyrano  -  Le 23/04/2011 00:25  -  Haut de page  - 

Principe de base : n'oublie jamais la logique. Les fonctions natives et leurs subtilités, tu les apprendras au fur et à mesure de leur utilisation, mais sans logique, les fonctions les plus efficaces ne servent pas à grand chose ;)

 
Par Cyrano  -  Le 23/04/2011 13:00  -  Haut de page  - 

Ha tiens, je reviens sur un détail, il y a une erreur dans mon code. là où j'ai écrit :

$value = sprintf("%02d",$m) .''. $current_year;

 

 

J'aurais dû écrire :

$value = sprintf("%02d",$m) .''. $y;

 

Je te laisse trouver pourquoi ;)

 
Par paintbox  -  Le 26/04/2011 15:51  -  Haut de page  - 

Hello Cyrano,

 

je remonte enfin à la surface après m'être plongé dans ton code. J'avoue que la plongé à été profonde et j'ai mis du temps à retrouver la surface. J'ai recommencé plusieurs fois ce message estimant que je n'avais pas été assez loin dans mes recherches.

 

J'ai à nouveau appris pas mal de choses notamment au niveau de la manipulation de chaînes de caractères et surtout avec la syntaxe HEREDOC. J'avoue honteusement que je n'avais jamais poussé leur usage jusqu'à ce point, n'y même de cette façon.

 

En ce qui concerne la syntaxe HEREDOC, j'ai compris le principe et la manière de l'utiliser, mais j'ai encore du mal à voir l'avantage que cela apporte, n'y même les différentes applications que je pourrais en faire. En quoi cela facilite le codage? Aurais-tu d'autres exemples, d'autres situations dans lesquels sont usage est intéressant?

 

J'ai également découvert que l'affichage formaté pouvait être poussé aussi loin.

 

 

La fonction à présent.

j'avoue (une fois de plus) que je n'aurais pas pensé procéder de cette façon ce qui m'inquiète un peu. Je n'ai pas cette logique.

 

J'ai aussi noté ta façon de déterminer l'élément sélectionné.

 

Je note également ta façon de "définir" en début de code les différentes variables que tu vas utiliser. C'est une discipline à laquelle je dois me plier.

 

Pour « $month[$m] » qu'entends-tu par "est une forme de CAST" ?

 

 

Bref ce petit bout de code m'a été très instructif. Je vais essayer d'appliquer à l'avenir ces différentes techniques dans mes prochains nouveaux codes mais je crois que je vais avoir du mal dans un premier temps. C'est un réflex et une logique que je vais devoir adopter.

 

Merci en tout cas pour ce code riche en nouveautés !

 

J'ai aussi compris ton erreur entre $current_year et $y. Le premier n'était pas décrémenté.

 
Par Cyrano  -  Le 26/04/2011 16:22  -  Haut de page  - 

Salut Paintbox,

*En ce qui concerne la syntaxe HEREDOC, j'ai compris le principe et la manière de l'utiliser, mais j'ai encore du mal à voir l'avantage que cela apporte, n'y même les différentes applications que je pourrais en faire. En quoi cela facilite le codage? Aurais-tu d'autres exemples, d'autres situations dans lesquels sont usage est intéressant? *

En fait j'utilise cette syntaxe au quotidien. D'abord parce que ça me permet de construire des portions complètes de HTML sans utiliser des « echo » partout. Ensuite lorsque je construis une page, je commence par créer une maquette en HTML dans un éditeur appropriéavec la coloration syntaxique qui va bien et j'affine la mise en page. Dès que c'est prêt, je ne m'occupe plus du tout de HTML, je découpe les différentes parties qui doivent être crées dynamiquement et je remplace le contenu de la maquette par les variables PHP qui contiendront le texte dynamique. La mise en forme de mon code HTML n'est pas affectée et lorsque j'envoie enfin un echo pour afficher le résultat dans un navigateur, si j'ai une bizarrerie imprévue dans la mise en page, un simple [Ctrl]+[U] pour afficher la source et çava me montrer très rapidement ce qui cloque. Le code restant aussi bien aligné que dans ma maquette, je ne prends pas des heures à chercher.

Autre avantage non négligeable : plus besoin de caractères d'échappements en se creusant la tête pour faire attention au apostrophes//guillemets... je peux utiiser les deux indistinctement, ça n'affectera pas le PHP. Ça reste une chaine de caractères sauf qu'elle peut occuper pas mal de place si le bout de code HTML (ou autre) qui est contenu dans la variable est important.

Si tu as lu la documentation sur HEREDOC dans le manuel PHP, tu auras peut-être aussi relevé l'existence de NOWDOC. Un léger inconvénient de HEREDOC est qu'on ne peut pas insérer de fonctions PHP. NOWDOC corrige ce défaut depuis PHP 5.3.x. Mais j'évite malgré tout de me servir de cette option : j'utilise souvent des bouts de code en HEREDOC dans des boucles par exemple, or une fonction effectue un traitement de données. Si le traitement peut-être fait une fois pour toute en amont, c'est préférable à une exécution pour chaque tour de boucle.

Enfin, et c'Est un point principal pour moi, je préfère ça de très loin à un moteur de templates. PHP est déjà en soi un moteur de templates, je trouve donc parfois assez saugrenu de rajouter une couche de traitement supplémentaire.

La fonction à présent.

j'avoue (une fois de plus) que je n'aurais pas pensé procéder de cette façon ce qui m'inquiète un peu. Je n'ai pas cette logique.

La logique, c'est simplement mathématique. Ce qui peut être difficile à déterminer, c'est l'ordre, la chronologie des choses. Programmer n'importe quoi, quelle que puisse êtrela taille de l'application, c'est décomposer un problème complexe en une succession de problèmes à réponses binaires, absolument rien d'autre. L'autre point assez essentiel, c'est que comme beaucoup de développeurs, je suis volontiers d'unnaturel fainéant et si je peux obtenir un résultat en écrivant 10 lignes de code au lieu de vingt, je ne me ferai pas violence pour choisir la solution la plus économe. C'est moins fatigant, ça use moins mon clavier et j'ai beaucoup moins de choses à analyser lorsque je dois revenir dessus pour une modification quelconque.

  • Pour « $month[$m] » qu'entends-tu par "est une forme de CAST" ?*

Un CAST, c'est un « transtypage » ou si tu préfères forcer un type (int, float, string, etc...) à une donnée dans un langage qui est très peu typé. Selon le type d'une donnée, certaines fonctions n'auront pas le même comportement pour une valeur équivalente. Ainsi, l'analyse d'une chaine « 04 »à coté de l'analyse d'un nombre « 04 » donnera un résultat différent. Lorsque je cherche $month['04'] ou $month[04], ça n'a pas le même sens puisque dans le premier mon index est de type string alors que dans l'autre il est de type int. Si le tableau original dans lequel j'effectue ma reche a été défini avec des index entiers (int), le premier cas me retournera une erreur parce que la chaine « 04 » n'existe pas dans le tableau. Là, le typage est possible parce que la valeur est numérique. Il est certain que ça ne fonctionnerait pas si je voulais forer $month['quatre'] en $month[4] parce que PHP ne sait pas transformer à ce niveau là.

Je note également ta façon de "définir" en début de code les différentes variables que tu vas utiliser. C'est une discipline à laquelle je dois me plier.

Ça va surtout te simplifier la vie en redant le code beaucoup plus facile à suivre, en limitant aussi les erreurs d'oubli. C'est, comme tu l'as fort bien compris, une question de discipline personnelleque j'encourage assez vivement.

  • J'ai aussi compris ton erreur entre $current_year et $y. Le premier n'était pas décrémenté.*

Tout juste :)

 
Par paintbox  -  Le 26/04/2011 17:32  -  Haut de page  - 

Merci pour ces explications. Je vois que ta technique de codage est optimalisée (code minimum pour efficacité maximale logique !).

Oui j'avais lu la partie sur NOWDOC.

Je crois qu'il va encore me falloir pas mal de temps avant de pouvoir appliquer tout cela et arriver à un code propre et optimal. Il va aussi falloir que je développe mon analyse face à un problème.

Brefle chemin est encore long

 
Par Cyrano  -  Le 26/04/2011 17:38  -  Haut de page  - 

La seule méthode réellement valable à mon sens, c'est une pratique très régulière et de l'obstination. Crée toi un petit projet, un utilitaire ou un jeu selon tes affinités et établis la structure, puis construis ça petit à petit en tentant de définir une chronologie dans les différentes phases du développement.

Autre méthode très très instructive, lorsque tu commenceras à être plus à l'aise avec tout ça, une participation sur un forum un peu actif. Peut-être pas ici parce que si tu attends des questions tu vas t'ennuyer ferme, mais vas sur PHPFrance et observe, tente de trouver les réponses aux questions d'autres intervenants : le grand truc, ne pas donner la réponse directe quand c'est possible, mais essayer de faire voir à celui qui est en panne le chemin qu'il doit prendre, lui faire voir sur quoi il bute, l'amener à trouver lui-même la solution. C'est la solution que j'y avais adopté et je te garantis que c'est très formateur. Je n'y interviens plus beaucoup, trop de monde et pas le temps, ici c'est plus calme et je peux faire une pause de temps à autre sans que ça affecte mon boulot. ;)

 
Par paintbox  -  Le 26/04/2011 17:56  -  Haut de page  - 

C'est ce que je fais, je travaille sur des projets personnels concrets( site de commerce électronique avec panier, back-office et petite gestion de stock) qui sont déjà un fameux bon par rapport à mes débuts.

Mais pas évident de savoir si la technique et la méthode qu'on utilise est la plus appropriée, la plus efficace.

Je pose des questions sur des forums (autre qu'ici) mais j'avoue sans te lancer des fleurs que c'est grâce à toi que j'en apprend le plus et fais de plus grands pats notamment avec les vues, les triggers, les sessions, maintenant la syntaxe HEREDOC, les boucles avec plusieurs arguments

Bon aller je ne baisse pas les bras et je continue

 
Par Cyrano  -  Le 27/04/2011 22:50  -  Haut de page  - 

C'est pas la voie la plus facile, surtout en partant d'aussi loin, mais c'est motivant quand on avance.

Si ça peut t'inspirer, j'avais du fait une formation pour avoir un papier marqué « Bac+2 » parce que dans ce métier c'est un peu le minimum pour avoir un boulot sérieux. Cette formation comportait un stage en entreprise. Il se trouve cependant que j'étais déjà autonome en PHP, fort heureusement parce qu'en 10 semaines environ, j'ai transformé un site intégralement statique (donc juste en HTML) en site de commerce en ligne avec panier, gestion de catalogue et de commande et paiement en ligne. Mais dis-toi bien que je ne connaissais pas la moitié des trucs que tu as appris ici ;)

Et pour le panier, si tu vas sur le forum de PHPFrance, tu trouveras un lien vers un tuto sur la construction de panier, à l'époque, je l'avais écrit directement inspiré par le panier monté sur le site en question. ( ) Si ton code est en programmation objet, ce ne sera pas utilisable directement, mais c'est relativement facile à adapter. L'emploi de certaines fonctions pourrait être modernisé un peu, il faudrait que je prenne le temps de quelques mises à jour de détails, mais dans l'ensemble, tu auras largement de quoi t'occuper pour tout assimiler ;)

 
Par paintbox  -  Le 28/04/2011 23:11  -  Haut de page  - 

Salut Cyrano,

étant infographiste à la base, j'ai voulu récemment suivre une formation de Developper Web afin d'acquérir une methode de travail et trouver quelques reponses à mes questions. Malheureusement, cette formation n étaient accessible qu'à des informaticiens, chose plutôt incompréhensible parce que je pense que si tu connais déjà un langage et les principes de la programmation tu peux facilement en apprendre un autre. D'autant que PHP reste accessible.

Je poursuit donc par moi meme.

Oui j avais trouvé ton tuto sur le panier électronique. Je me suis grandement inspiré pour réaliser le mien.

 

Ajouter une réponse à la discussion

Seuls les membres connectés sont autorisés à poster dans les forums !

Identifiez-vous
Join |  ID/MDP? |