Boucles imbriquées Départements/Villes

Rechercher
Boutique en ligne, solution e-commerce, script PHP et PERL : RAYNETTE

Boucles imbriquées Départements/Villes

Par Pone  -  33 reponses  -  Le 11/09/2009 15:48  -  Editer  - 

Bonjour,

Cela fait plusieurs jours que je me torture l'esprit pour résoudre mon problème : faire une boucle qui liste les départements, puis une boucle imbriquée qui liste les villes du département en question. Il y a plusieurs départements.

Tout ce petit monde est stocké dans des tables différentes.

 

Réponses apportées à cette discussion

Par Cyrano  -  Le 11/09/2009 20:07  -  Haut de page  - 

Salut, en fait la solution n'est pas vraiment compliquée mais il faut de l'astuce.

Première étape, on va ajouter une clause ORDER BY à ta requête de façon à avoir directement dans le bon ordre nos données : on va ordonner d'abord par département puis par ville, ce qui donne :

<?php
$connexion = mysql_connect($serveur, $admin, $mdp);
mysql_select_db($base, $connexion);
$sql =  "SELECT ".
        "    d.dep_id, ".
        "    d.dep_nom, ".
        "    v.vil_id, ".
        "    v.vil_nom, ".
        "    v.vil_ref_dep ".
        "FROM db_dept d ".
        "    LEFT JOIN db_ville v ON d.dep_id = v.vil_ref_dep ".
        "ORDER BY d.dep_id, v.vil_nom";
$req = mysql_query($sql) or die (mysql_error());
mysql_close();

Tu noteras au passage que j'ai remis en forme le code, c'est plus facile à lire.

Seconde étape, on va ajouter un point de repère variable. Ce qui nous intéresse, c'est d'avoir une fois le nom du département suivi de la liste des villes qui s'y trouvent, puis le département suivant, une seule fois également et ainsi de suite. On définit donc une variable juste avant la boucle et on l'initialise à rien, ou chaine vide si tu préfères. Ensuite dans la boucle, on va comparer l'identifiant du département et cette variable : s'il y a différence, on affiche le département et on ré-initialise la variable. On continue avec l'affichage de la ville. Au tour suivant, même comparaison : mais cette fois, on a le même département, donc on ne l'affiche pas et on saute directement à la ville suivante.

Le code devient donc :

<?php
//...
$dept = '';
while(false !== ($data = mysql_fetch_assoc($req)))
{
    if($dept != $data['dep_id'])
    {
        echo 'Département : ' . $data['dep_nom'] . ' : ';
        $dept = $data['dep_id'];
    }
    if($data['vil_id'] != 0)
    {
        echo $data['vil_nom'] . ', ';
    }
}

Et voilà le travail.

Je t'invite à observer une formulation plus stricte du while : while étant une structure de contrôle, on ne devrait pas y trouver un opérateur d'affectation mais un opérateur de comparaison. En pratique je t'accorde que ta version fonctionne quand même, mais c'est moins propre.

Bon code ;-)

 

 

 
Par Pone  -  Le 11/09/2009 20:54  -  Haut de page  - 

Ouah ça marche :) Et en plus c'est une réponse bien détaillée.

Jamais je n'aurais pu sortir ce code tout seul, merci ! Il me reste à faire quelques adaptations pour coller à mon script réel (car j'ai en plus une base de pays en plus des dépts et villes) mais ça fonctionne.

PS : je n'ai pas trouvé comment faire pour mettre en forme le code comme tu as fais.

A+

 
Par Cyrano  -  Le 11/09/2009 20:56  -  Haut de page  - 

Pour la mise en forme, regarde la barre d'outils, il y a un petit logo avec : en cliquant dessus, ça ouvre un pop-up : tu choisis le type de code dans la liste déroulante, tu ajoutes une légende et tu colles ton code dedans ;-)

 
Par Pone  -  Le 24/09/2009 11:40  -  Haut de page  - 

Salut,

C'est encore moi avec cette histoire de boucle : ça a fonctionné très bien jusqu'à ce que je veuille intégrer des listes (ul/li) imbriquées... qui ont du mal à s'imbriquer du coup :)Le but c'est de faire un arbre comme ici http://www.dhtmlgoodies.com/scripts/folder-tree-static/folder-tree-static.html

Je pense que ça bloque au niveau des accolades je pense, mais après plusieurs heures de tests je sature et je ne vois pas ce qui se passe. Note : j'ai simplifié quelques passages pour faciliter la compréhension.

<ul>
<?php
$connexion = mysql_connect($serveur, $admin, $mdp);
mysql_select_db($base, $connexion);
$req = mysql_query('
SELECT pay_id, pay_nom, dep_id, dep_nom, dep_ref_pay, vil_id, vil_nom, vil_ref_dep, etb_id, etb_nom, etb_ref_vil
FROM db_pays
LEFT JOIN db_dept
ON db_dept.dep_ref_pay = db_pays.pay_id
LEFT JOIN db_ville
ON db_ville.vil_ref_dep = db_dept.dep_id
LEFT JOIN db_etb
ON db_etb.etb_ref_vil = db_ville.vil_id
ORDER BY pay_nom, dep_nom, vil_nom, etb_nom') or die (mysql_error());
$pays = '';
$dept = '';
$ville = '';
while($data = mysql_fetch_assoc($req)) {
  if($pays != $data['pay_id']) {
  echo "\r\n\t" . '<li>' . $data['pay_nom'] . "\r\n";
  $pays = $data['pay_id'];
  echo "\t\t<ul>\r\n";
  }
  if($dept != $data['dep_id']) {
  echo "\t\t" . '<li>' . $data['dep_nom'] . "\r\n";
  $dept = $data['dep_id'];
  echo "\t\t\t<ul>\r\n";
  if($ville != $data['vil_id']) {
  echo "\t\t\t" . '<li>' . $data['vil_nom'] . "\r\n";
  $ville = $data['vil_id'];
  echo "\t\t\t\t<ul>\r\n";
  if($etab != 0) {
  echo "\t\t\t\t" . '<li>' . $data['etb_nom'] . "\r\n";
  }
  echo "\t\t\t\t</ul>\r\n\t\t\t</li>\r\n";
  }
  echo "\t\t\t</ul>\r\n";
  }
}
?>
</ul>

Merci !

 

 
Par Cyrano  -  Le 24/09/2009 12:10  -  Haut de page  - 

Peut-être bien que tu ne pose pas le problème de manière appropriée :

Tu obtiens un résultat non satisfaisant : soit, mais partant de ce premier résultat, quelles sont les points qu'il faudrait corriger pour que ça devienne conforme à tes attentes ? En d'autres termes, tu nous dit que ça ne marche pas et que l'imbrication est foireuse : si tu le dis, je n'ai pas de raisons de ne pas te croire mais ça ne m'avance pas des masses. Il faudrait voir le code généré pour avoir une idée du résultat que tu as jusqu'à maintenant.

Et surtout n'oublie surtout pas : tout ça, c'est d'abord de la logique, donc tu as peut-être (probablement) omis certains détails.

 
Par Pone  -  Le 24/09/2009 12:38  -  Haut de page  - 

En effet, c'est plus clair avec le code généré, je le joins. Je ne sais pas si l'indentation va bien rendre ici, mais dans Notepad++ c'est lisible.

Ce qui me pose problème exactement c'est que je n'arrive pas à faire réellement des boucles (avec le while), c'est-à-dire que même si j'ai plusieurs villes dans un même département (par exemple), et bien le script ne m'en liste qu'une seule : la boucle ne se fait pas.

Ensuite, certains et ne sont pas correctement fermés, ce qui provoque un décalage dans l'arborescence (ici, les Etats-Unis sont imbriqués dans la France alors qu'ils devraient être sur le même niveau).

J'y retourne!

<ul>
  <li>France
    <ul>
    <li>Ain
      <ul>
      <li>Oyonnax
        <ul>
        <li>Etab Oyonnax</li>
        </ul>
      </li>
      </ul>
    <!-- ici manque </li> pour fermer le dept Ain -->
    <li>Somme
      <ul>
      <li>Amiens
        <ul>
        <li>Etab Amiens</li>
        </ul>
      </li>
      </ul>
    <!-- ici manque </li> pour fermer le dept Somme -->
    <!-- ici manque </ul> pour fermer la liste des dept -->
  <!-- ici manque </li> pour fermer le pays France -->
  <li>Etats-Unis
    <ul>
    <li>Floride
      <ul>
      <li>Fort Lauderdale
        <ul>
        <li>Etab Fort Lauderdale</li>
        </ul>
      </li>
      </ul>
    <!-- ici manque </li> pour fermer le dept Floride -->
    <li>Californie
      <ul>
      <li>San Bernardino
        <ul>
        <li>Etab San Bernardino</li>
        </ul>
      </li>
      </ul>
    <!-- ici manque </li> pour fermer le dept Californie -->
    <!-- ici manque </ul> pour fermer la liste des dept -->
  <!-- ici manque </li> pour fermer le pays Etats-Unis -->
</ul>

 

 

 
Par Cyrano  -  Le 24/09/2009 14:23  -  Haut de page  - 

Ok, en fait je m'en doutais un peu : il manque donc des balises de fermeture ou : regarde attentivement ton code et pose-toi la question suivante :

  • à quel endroit telle balise de fermeture devrait-elle être créée ? et pourquoi ?

En d'autres termes, dans le déroulement de ton code, tu vérifies des conditions pour ouvrir ou non certaines balises. Mais est-ce que ton code comporte des vérifications similaires pour décider ou non de fermer ces mêmes balises ?

Je t'ai préparé le début, mais je te laisse le soin de terminer toi-même, il est important que tu comprennes le raisonnement à suivre. Pour simplifier, je suis parti de données dans un tableau. Mais le principe reste strictement le même, j'utilise juste une boucle foreach au lieu de while mais le résultat est exactement le même. Ce code est exécutable, enregistre c¸a et affiche la page, puis observe le résultat. J'ai largement commenté le code :

<?php$infos = array(    array(        'pays'  => 'France',        'dept'  => 'Ain',        'ville' => 'Oyonnax',        'etb'   => 'Etab Oyonnax'    ),    array(        'pays'  => 'France',        'dept'  => 'Ain',        'ville' => 'La Valbonne',        'etb'   => 'Etab La Valbonne'    ),    array(        'pays'  => 'France',        'dept'  => 'Somme',        'ville' => 'Amiens',        'etb'   => 'Etab Amiens'    ),    array(        'pays'  => 'Etats-Unis',        'dept'  => 'Floride',        'ville' => 'Fort Lauderdale',        'etb'   => 'Etab Fort Lauderdale'    ),    array(        'pays'  => 'Etats-Unis',        'dept'  => 'Californie',        'ville' => 'San Bernardino',        'etb'   => 'Etab San Bernardino'    ),    array(        'pays'  => 'Etats-Unis',        'dept'  => 'Californie',        'ville' => 'San Francisco',        'etb'   => 'Etab San Francisco'    ),    array(        'pays'  => 'Etats-Unis',        'dept'  => 'Californie',        'ville' => 'San Francisco',        'etb'   => 'Succursale San Francisco'    ));/** * Mise en place des points de repère */$pays  = '';$dept  = '';$ville = '';/** * On vérifie qu'on a des données : il ne faudrait pas * initialiser une liste vide pour rien. */$ne = count($infos);$sSortie = "<p>Aucune donnée n'est disponible</p>\n";if($ne > 0){    $sSortie  = '    <ul>';    foreach($infos as $etb)    {        /**         * Si on change de pays, on ferme le précédent et on ouvre         * le suivant, mais si c'est le premier pays, on limite à         * l'ouverture         */        if($pays != $etb['pays'])        {            /**             * On sait déjà qu'on est avec un nouveau pays.             * Donc on peut ré-initialiser les repères de département             * et de ville.             */            $dept  = '';            $ville = '';            if($pays != '')            {                /**                 * Là on sait que ce n'est pas le premier pays :                 * donc il faut commencer par fermer le précédent                 */    $sSortie .= '          </li>        </ul>      </li>';            }            /**             * Maintenant on ouvre le nouveau pays             */            $sSortie .= '      <li>        '. $etb['pays'] .'';            /**             * Mise à jour du repère de pays             */            $pays = $etb['pays'];        }        /**         * Maintenant il faut entamer un processus similaire         * pour le département/état :         */        /**         * Si on change de pays, on ferme le précédent et on ouvre         * le suivant, mais si c'est le premier pays, on limite à         * l'ouverture         */        if($dept != $etb['dept'])        {            /* On sait déjà qu'on est avec un nouveau département */            if($dept != '')            {                /**                 * Là on sait que ce n'est pas le premier département :                 * donc il faut commencer par fermer le précédent                 */    $sSortie .= '          </li>';            }            else            {    $sSortie .= '        <ul>';            }            /**             * Maintenant on ouvre le nouveau département             */            $sSortie .= '          <li>            '. $etb['dept'] .'';            /**             * Mise à jour du repère de département             */            $dept = $etb['dept'];        }    }    /**     * Maintenant il faut tout fermer pour le dernier item     */    $sSortie .= '          </li>        </ul>      </li>    </ul>';}?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">  <head>    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" xml:lang="fr" />    <title>Listes imbriquées dynamiquement</title>  </head>  <body><?phpecho($sSortie);?>  </body></html>

 

 
Par Pone  -  Le 25/09/2009 21:59  -  Haut de page  - 

Quelques nouvelles : au bout de 2 jours d'efforts terribles :) je crois que c'est bon. Il ne me reste plus qu'a tester avec les infos de ma BDD.

Merci pour ton aide Cyrano.

 

 

 
Par Cyrano  -  Le 25/09/2009 22:36  -  Haut de page  - 

Ben voilà : si tu as compris le fonctionnement, c'est le plus important :)

À partir de ta base de données, le résultat devrait fonctionner tout aussi bien.

 
Par Pone  -  Le 04/10/2009 01:13  -  Haut de page  - 

*si tu as compris le fonctionnement, c'est le plus important :) *

Oui j'ai compris pour la partie de code que tu m'as expliqué, et ça fonctionne très bien mais je viens de m'apercevoir que lorsqu'il n'existe pas d'enfant à une catégorie le même problème de balises non fermées recommence.

Par exemple si je ne renseigne pas de ville pour le département Isère, ou encore si un établissement n'est pas associé à la ville de Quimper.

J'ai essayé de rajouter une condition dans le script mais en vain. Je crois que je ne m'en sortirai jamais avec ce truc pourtant ça doit être simple.

 
Par Cyrano  -  Le 04/10/2009 04:25  -  Haut de page  - 

« J'ai essayé de rajouter une condition dans le script mais en vain »

Quelle sorte de condition ? Es-tu sûr d'avoir testé la bonne ? Je crois bien que le problème est en amont : si tu as dans les informations retournées une ligne où l'établissement est absent, ça vient peut-être d'une erreur de la requête qui n'aurait pas dû retourner une information non pertinente.

 
Par Pone  -  Le 04/10/2009 15:20  -  Haut de page  - 

"si tu as dans les informations retournées une ligne où l'établissement est absent, ça vient peut-être d'une erreur de la requête qui n'aurait pas dû retourner une information non pertinente"

Le fait de ne pas avoir d'enfant dans une catégorie peut arriver et ça fait partie du fonctionnement normal du site : on peut vouloir gagner du temps en entrant les villes dans la base de données, puis enregistrer les établissements plusieurs jours après.

"Quelle sorte de condition ?"

J'ai tenté de vérifier si $data['dept'] == true, autrement dit, si à tel pays un département existait (idem pour département, ville, étab). Puis si ce n'est pas le cas, j'affiche des balises différentes mais ça commence à devenir une vraie usine à gaz !

"Es-tu sûr d'avoir testé la bonne ?"

On n'est jamais sûr de rien quand on ne maîtrise pas son sujet ;)

 
Par Cyrano  -  Le 04/10/2009 16:10  -  Haut de page  - 

Ok, donc on par du fait qu'on peut avoir une ville mais pas d'établissement. Dans ce cas, si on considère qu'on veut afficher les établissements, on a deux options :

  1. Soit on affiche une valeur par défaut lorsqu'on a une ville et pas d'établissement enregistrée;
  2. Soit on procède à un comptage sur nombre d'établissement avant d'afficher la ville et soit on a une valeur égale à zéro et on saute à la ville suivante, soit on affiche les établissements comme prévu.

Ce sont les éléments que je te laisse méditer quelque peu pour continuer :)

Note que je ne suis pas certain que cette réponse soit très satisfaisante pour toi, mais ce qui m'intéresse davantage, c'est de t'amener à trouver toi-même la bonne réponse et donc j'essaye de te montrer quelles sont les questions que tu dois te poser. Si tu as les bonnes questions, c'est que tu as correctement identifié la source de ta difficulté : c'est plus des trois-quart de la réponse. En faisant ça, tu gagnes en autonomie et tu n'auras avec le temps plus besoin de moi (ou d'un autre d'ailleurs) pour avancer ;)

 

 
Par nanou  -  Le 20/02/2016 14:55  -  Haut de page  - 

Bonjour à vous!
Merci pour ce forum que je trouve très utile.
J'ajoute une réponse à cette discussion qui semble ancienne "Boucles imbriquées Départements/Ville"s car je me retrouve devant un problème similaire. Je tourne en rond depuis… longtemps. car j'aime trouver par moi-même sauf que là, je bute.…
Si vous aviez la gentillesse de m'éclairer ou de me donner des exemples de bonne syntaxe.
J'ai un extranet dans lequel des vétérinaires se connectent. Ces vétos ont des clients qui ont des contrats d'assurance avec des sinistres sur lesquels les vétos sont intervenus .
J'ai fait une requête avec jointure sur les 6 tables concernées (clients, contrats, sinistres, vétos, animaux, et table pivot qui contient des interventions de vétos sur les sinistres) qui me remonte toutes les réponses que je souhaite.(38 occurences)
Ces 38 occurences je veux juste les présenter de façon hiérarchique au vétérinaire
Là je bloque sur le bon affichage des résultats de cette requête que je voudrai indenter en accordéon avec 3 niveaux de rupture
Listes de sinistres de mes clients (un clic sur le client, déploit ses contrats, un clic sur un contrat déploit les sinistres)

    Client 1  
        Contrat 1  
            Sinistre 1  
            Sinistre 2  
        Contrat 2  
            Sinistre 3          
    Client 2  
        Contrat 3  
            Sinistre 4  
            Sinistre 5  
            Sinistre 6  
    Client 3  
        Contrat 4  
            Sinistre 7  

etc…
J'initialise mes variables

    $client = "";  
    $contrat = "";  
    $sinistres = "";  

et je voudrai pouvoir continuer mes boucles de façon dynamique tant que le résultat de la requête est différent de la valeur trouvée. Euh c'est là que ça pêche. Je sais que je pourrai contourner le problème en faisant des séries de sous-requêtes? mais bon, une belle jointure qui me remonte parfaitement exactement ce que je veux, et que je n'arrive juste pas à hierarchiser. Quelqu'un peut-il m'aider? Je vous en remercie d'avance?
bonne journée

 
Par Cyrano  -  Le 20/02/2016 20:10  -  Haut de page  - 

Salut,
pour l'indentation, j'ai édité ton message et remis en forme. Il faut utiliser la syntaxe Markdown pour ça. Du coup, le message de correction devenant inutile, je l'ai supprimé.

Ta question maintenant : il est sûrement possible de tout extraire en une seule requête avec les jointures appropriées. Pour ça, il faudrait connaitre la structure exacte des données. Mais je vais partir d'une hypothèse avec trois des tables :

        +----------+       +-------------+       +-------------+
        | Client   |       | Contrat     |       | sinistres   |
        +----------+       +-------------+       +-------------+
        | cli_id   | ----- | ctr_id      | ------| sns_id      |
        | cli_nom  |       | cli_id      |       | ctr_id      |
        +----------+       | ctr_libelle |       | sns_libelle |
                           +-------------+       +-------------+

Partant de la, je vais faire la requête suivante :

    SELECT
      cl.cli_id,
      cl.cli_nom,
      ct.ctr_id,
      ct.ctr_libelle,
      sn.sns_id,
      sn.sns_libelle
    FROM client           cl
      INNER JOIN contrat  ct ON cl.cli_id = ct.cli_id
      INNER JOIN sinistre sn ON ct.ctr_id = sn.ctr_id
    ORDER BY cl.cli_id, ct.ctr_id;

Et là, j'obtiendrai quelque chose du style :

    +--------+----------+--------+-------------+--------+-------------+
    | cli_id | cli_nom  | ctr_id | ctr_libelle | sns_id | sns_libelle |
    +--------+----------+--------+-------------+--------+-------------+
    |      1 | Client 1 |      1 | Contrat 1   |      1 | Sinistre 1  |
    |      1 | Client 1 |      1 | Contrat 1   |      2 | Sinistre 2  |
    |      1 | Client 1 |      2 | Contrat 2   |      3 | Sinistre 3  |
    |      2 | Client 2 |      3 | Contrat 3   |      4 | Sinistre 4  |
    |      2 | Client 2 |      3 | Contrat 3   |      5 | Sinistre 5  |
    |      2 | Client 2 |      3 | Contrat 3   |      6 | Sinistre 6  |
    |      3 | Client 3 |      4 | Contrat 4   |      7 | Sinistre 7  |
    +--------+----------+--------+-------------+--------+-------------+

Partant de là, l'affichage reste un problème relativement simple : le truc consiste à bien ordonner le résultat de la requête avant pour le traiter ensuite.

 
Par nanou  -  Le 20/02/2016 20:36  -  Haut de page  - 

bonsoir,

Merci beaucoup d'avoir pris le temps de me répondre
Je n'ai pas de pb de requête, les jointures que j'ai faites me font remonter exactement ce que je cherche.
J'ai un pb de syntaxe pour l’affichage hiérarchie des résultats,
exactement comme je l’ai présenté dans le tableau que vous m’avez corrigé (merci!)
C’est un problème de 3 accordéons imbriqués.
Je peux vous communiquer mon code si vous voulez

 
Par Cyrano  -  Le 20/02/2016 20:47  -  Haut de page  - 

Ce serait effectivement utile parce que ça indiquerait le point de départ.

Ceci dit, c'est une question de logique : on va avoir trois boucles :
dans la première, on définit si on a le même client qu'au tour précédent, dans la seconde le même contrat qu'au tour précédent et la troisième pour les sinistres.

Le problème, c'est le premier tour, aux deux premiers niveau s'entend : donc en amont de la boucle, on définit un pointeur avec la valeur NULL.

 
Par nanou  -  Le 20/02/2016 21:46  -  Haut de page  - 

Code :

<?php
$query_liste_client = "SELECT *
FROM tb_sante_clinique clin
    LEFT JOIN tb_sante_SinVetClin svc ON clin.NumClin = svc.refNumClin
    LEFT JOIN tb_sante_clients cli ON svc.refNumCli = cli.NumCli
    LEFT JOIN tb_sante_contrats con ON svc.refNumPol = con.NumPol 
    LEFT JOIN tb_cheval che ON svc.refNumChe = che.NumChe
    LEFT JOIN tb_sante_sinistres sin ON svc.refNumSin = sin.NumSin
WHERE clin.NumClin = 'FRC033260' AND sin.NumCarteVeto !='' GROUP BY svc.refNumCli";

$liste_client           = mysql_query($query_liste_client, $cavalass) or die(mysql_error());
$row_liste_client       = mysql_fetch_assoc($liste_client);
$totalRows_liste_client = mysql_num_rows($liste_client);
$max                    = $totalRows_liste_client;
?>
<!-- LE CONTENU DE LA PAGE ************************************************* -->

<div class="wrap" id="contenu">
  <section class="fond_blanc">
    <article class="container_12">
      <div class="bord_vertical">
        <div class="grid_12">
          <h3 class="titre">Les sinistres tiers-payant de mes clients</h3>
          <!-- Tous les clients avec sinistres tiers-payant -->
<?php

if($totalRows_liste_client > 0)
{
    /*do {
if ($totalRows_liste_client > 0) { */
    $z = 0;
    do
    {
        $f = "form_" . $z;
        $ff = "fform_" . $z;
        $z++;
        switch($row_liste_client['StatutSinistre'])
        {
            case 1 :
                $param = '<input type="submit" name="couleur" id="couleur" value="Impossible" class="coul_bt gris"/>'; // IMPOSSIBLE GRIS
                $class = 'gris';
                break;
            case 2 :
                $param = '<input type="submit" name="couleur" id="couleur" value="En Etude" class="coul_bt jaune"/>'; //EN ETUDE JAUNE
                $class = 'jaune';
                break;
            case 3 :
                $param = '<input type="submit" name="couleur" id="couleur" value="Accepté" class="coul_bt vert"/>'; //ACCEPTE VERT
                $class = 'vert';
                break;
            case 4 :
                $param = '<input type="submit" name="couleur" id="couleur" value="Refusé" class="coul_bt rouge"/>'; //REFUSE ROUGE
                $class = 'rouge';
                break;
            default :
                $param = '<input type="submit" name="couleur" id="couleur" value="Cloturé" class="coul_bt bleu" />';
                $class = 'bleu'; //cloturé
                break;
        }
?>
                    <div class="accordion">
            <!-- les données du contrat -->
            <!--Mes contrats MORTALITE SANS CARTE ASSOCIEE - > achat de carte cavalsante possible-->
            <h3><?php echo $row_liste_client['Nom'];?> <?php echo $row_liste_client['Prenom'];?> <?php echo $row_liste_client['RaisonSociale'];?> - Tel : <?php echo $row_liste_client['Tel'];?> - Mobile : <?php echo $row_liste_client['Mobile'];?> </h3>
            <div class="contenu_accordion garantie bt_libre">
              <div class="sin_acc">
                <h5><?php echo $row_liste_client["che_nom"]; ?> - <?php echo $row_liste_client['NumSin']; ?> <?php echo $row_liste_client["NumCarteVeto"]; ?><i  class="sinistre_statut <?php echo $class; ?>"> </i></h5>
                <div class="cont_sin_acc">
                  <p>
                    <span class="label2"><label>Date du sinistre</label> : <?php echo date_us2fr($row_liste_client['DateSinistre']); ?></span>
                    <span class="label2"><label>Carte N°</label> : <?php echo $row_liste_client["NumCarteVeto"]; ?></span>
                    <span class="label2"><label><?php echo $onglet[98]; ?></label> : <?php echo $XSousFamilleSinistre[$row_liste_client['SousFam']]; ?></span>
                    <span class="label2"><label><?php echo $onglet[99]; ?></label> : <?php echo $row_liste_client['Mt11Remb']; ?></span>
                    <span class="label2"><label><?php echo $onglet[101]; ?></label> : <?php echo $row_liste_client['MtSolde']; ?></span>
                  </p>
                  <form class="pls_coul" method="post" name="<?php echo $f; ?>" action="sinistre_detail.php">
                    <input type="hidden" name="NumSin" id="NumSin" value="<?php echo $row_liste_client['NumSin']; ?>" />
                    <input type="hidden" name="NumCarteVeto" id="NumCarteVeto" value="<?php echo $row_liste_client['NumCarteVeto']; ?>" />
                    <input type="hidden" name="NumPol" id="NumPol" value="<?php echo $row_liste_client['NumPol']; ?>" />
                    <input type="hidden" name="NumChe" id="NumChe" value="<?php echo $row_liste_client['NumChe']; ?>" />
                                        <?php echo $param; ?>
                                    </form>
                </div>
                <!-- cont_sin_acc -->
              </div>
              <!-- sin_acc -->
            </div>
            <!-- contenu_accordion -->
          </div>
          <!-- accordion -->

<?php
    } while ($row_liste_client = mysql_fetch_assoc($liste_client));
?>
<?php
}
else
{
?>
                    <p><?php echo $onglet[127]; ?> <?php echo $row_liste_client["NumCarteVeto"]; ?> …</p>
<?php
}
?>
                </div>
      </div>
    </article>
  </section>
</div>
<?php
include($_SERVER['DOCUMENT_ROOT'].'/commun/footer.php');
?>
 
Par nanou  -  Le 20/02/2016 21:49  -  Haut de page  - 

Oops, je n'ai pas dût bien utiliser le format markdown…

En gros l'affichage des 12 clients fonctionne pour le 1er niveau mais ensuite pour leur contrats et leur sinistres, il n'affichent que le 1er résultat de chaque boucle (alors que la requête exécutée directement remonte bien les 38 résultats)

 
Par Cyrano  -  Le 20/02/2016 22:11  -  Haut de page  - 

Je ne vois qu'une seule boucle while, mais aucune alternative pour définir s'il faut ou non afficher tel ou tel élément.

Il faudrait vérifier ce qui est retourné par la requête, de préférence en ligne de commande, l'affichage est plus facile à transcrire ici et à lire, comme pour l'exemple que j'ai utilisé plus tôt. Quelques lignes suffiraient pour avoir la structure des données.

Par ailleurs, pour simplifier, j'aurais tendance à découper et à créer des fonctions pour construire les éléments. Mais on verra ça après. D'abord, il faudrait que je voie un exemple du résultat attendu en HTML, que je puisse identifier quelles parties sont ou non à répéter avec telle ou telle partie des données. Mettons un client, un ou deux contrats et un ou deux sinistre par contrat.

 
Par nanou  -  Le 20/02/2016 23:06  -  Haut de page  - 

Voilà vous avez pointé le pb
je n'ai qu'une boucle while car je n'ai qu'une requête globale … (je n'ai justement pas voulu utiliser de sous-requête)
Comme formuler mes 2 autres while pour faire ressortir mes 2 autres ruptures?

Ma requête avec jointures sort 38 résultats de sinistres pour le véto x
12 contrats et 11 clients différents
Le client 1 a 1 contrat et 4 sinistres
Le client 2 à 2 contrats et 2 sinistres
Le client 3 à 1 contrats et 1 sinistres
etc…

Je dois présenter ces résultats sous la forme

    Client 1  
        Contrat 1  
            Sinistre 1  
            Sinistre 2  
        Contrat 2  
            Sinistre 3          
    Client 2  
        Contrat 3  
            Sinistre 4  
            Sinistre 5  
            Sinistre 6  
    Client 3  
        Contrat 4  
            Sinistre 7 

Je ne sais pas comment vous communiquer des éléments et markdown, j'avoue n'avoir pas compris comment s'en servir

 
Par Cyrano  -  Le 20/02/2016 23:19  -  Haut de page  - 

Il aurait fallu que je voie les données, mais on va faire sans à partir de l'exemple que j'ai indiqué plus haut pour illustrer.

Partons du principe que je vais devoir boucler mais n,afficher le nom d'un client qu'une seule fois, suivi de chacun des contrats qui le concerne spécifiquement sans répéter le nom du client, et de même pour les sinistres sans répéter les contrats.
Le jeu d'essai est donc celui-ci :

+--------+----------+--------+-------------+--------+-------------+
| cli_id | cli_nom  | ctr_id | ctr_libelle | sns_id | sns_libelle |
+--------+----------+--------+-------------+--------+-------------+
|      1 | Client 1 |      1 | Contrat 1   |      1 | Sinistre 1  |
|      1 | Client 1 |      1 | Contrat 1   |      2 | Sinistre 2  |
|      1 | Client 1 |      2 | Contrat 2   |      3 | Sinistre 3  |
|      2 | Client 2 |      3 | Contrat 3   |      4 | Sinistre 4  |
|      2 | Client 2 |      3 | Contrat 3   |      5 | Sinistre 5  |
|      2 | Client 2 |      3 | Contrat 3   |      6 | Sinistre 6  |
|      3 | Client 3 |      4 | Contrat 4   |      7 | Sinistre 7  |
+--------+----------+--------+-------------+--------+-------------+

On va faire ça en pseudo-code :

id_client = NULL;
id_contrat = NULL;
TANT QUE ligne_suivante ALORS
    SI id_client DIFFÉRENT DE ligne_suivante[cli_id] ALORS
        AFFICHER ligne_client[cli_nom];
        id_client = ligne_suivante[cli_id];
        id_contrat = NULL;
    FIN SI;
    SI id_contrat DIFFERENT DE ligne_suivante[ctr_id] ALORS
        AFFICHER ligne_suivante[ctr_libelle];
        id_contrat = ligne_suivante[ctr_id];
    FIN SI;
    AFFICHER ligne_suivante[sns_libelle]
FIN TANT QUE;

Voilà, schématiquement, le raisonnement à suivre. Est-ce que c'est assez clair ?

 
Par nanou  -  Le 20/02/2016 23:53  -  Haut de page  - 

Ok pour le raisonnement,
Maintenant c est la syntaxe que je n'arrive pas à mettre en oeuvre
Jinitialise mes 3 variables
Je fais 1 While général
Je pose mes 3 conditions
Mais quelle syntaxe?
Merci encore pour votre aide.

 
Par Cyrano  -  Le 21/02/2016 08:55  -  Haut de page  - 

Salut,
le pseudo-code montre cette syntaxe.

Ainsi, TANT QUE correspond à une boucle, à chaque tour, on vérifie qu'une assertion est vraie, et on en sort si elle devient fausse.
Ici, le

TANT QUE ligne_suivante ALORS

correspond en PHP à

while(false != ($row_liste_client = mysql_fetch_assoc($liste_client))) {

Et le FIN TANT QUE correspond à l'accolade fermante :

TANT QUE ligne_suivante ALORS
    ...
FIN TANT QUE

Est équivalent à :

while(false != ($row_liste_client = mysql_fetch_assoc($liste_client))) {
    ...
}

C'est la même chose pour le SI condition ALORS // FIN SI qui devient alors :

if(true == $condition){
    ...
}

Est-ce qu'il reste des difficultés ?

 
Par nanou  -  Le 21/02/2016 10:24  -  Haut de page  - 

J'ai initialisé mes 3 variables

$NumCli = "";
$NumPol = "";
$NumSin = "";

Ensuite j'ai inséré mes 3 conditions dans mon code affichant les 3 accordéons

<?php if ($NumCli != $row_liste_client['NumCli']) { ?>
<?php if ($NumPol != $row_liste_client['NumPol']) { ?>
   <?php if ($NumSin != $row_liste_client['NumSin']) { ?>
 <?php } ?>
 <?php } ?>
 <?php } ?>

il ne sa passe rien ! la liste complète et redondante continue de s'afficher avec mes 34 résultats
sans indentation :(

 
Par Cyrano  -  Le 21/02/2016 12:02  -  Haut de page  - 

Ok, on va essayer avec une approche un peu différente. Voici le début (je n'ai pas eu le temps de finir) de la manière dont j'aurai approché le sujet.

Première phase, découper le code dynamique et créer des fonctions appropriées.

    <?php
    $query_liste_client = "SELECT". PHP_EOL .
                          "  *". PHP_EOL .
                          "FROM tb_sante_clinique clin". PHP_EOL .
                          "    LEFT JOIN tb_sante_SinVetClin svc ON clin.NumClin = svc.refNumClin". PHP_EOL .
                          "    LEFT JOIN tb_sante_clients cli ON svc.refNumCli = cli.NumCli". PHP_EOL .
                          "    LEFT JOIN tb_sante_contrats con ON svc.refNumPol = con.NumPol". PHP_EOL .
                          "    LEFT JOIN tb_cheval che ON svc.refNumChe = che.NumChe". PHP_EOL .
                          "    LEFT JOIN tb_sante_sinistres sin ON svc.refNumSin = sin.NumSin". PHP_EOL .
                          "WHERE clin.NumClin = 'FRC033260' AND sin.NumCarteVeto !='' GROUP BY svc.refNumCli";

    $liste_client           = mysql_query($query_liste_client, $cavalass) or die(mysql_error());
    $row_liste_client       = mysql_fetch_assoc($liste_client);
    $totalRows_liste_client = mysql_num_rows($liste_client);
    $max                    = $totalRows_liste_client;

    /* Fonction de construction des lignes de chaque sinistre par client et par contrat */
    function setBlocClient($ligne, $lignesContrats)
    {
        $sBloc = <<<CODE_BLOC
              <div class="accordion">
                <!-- les données du contrat -->
                <!--Mes contrats MORTALITE SANS CARTE ASSOCIEE - > achat de carte cavalsante possible-->
                <h3>{$ligne['Nom']} {$ligne['Prenom']} {$ligne['RaisonSociale']} - Tel : {$ligne['Tel']} - Mobile : {$ligne['Mobile']}</h3>
                <div class="contenu_accordion garantie bt_libre">
    {$lignesContrats}              <!-- sin_acc -->
                </div>
                <!-- contenu_accordion -->
              </div>
              <!-- accordion -->

    CODE_BLOC;
        //...
        return $sBloc;
    }

    function setBlocContrat($ligne, $lignesSinistres, $class)
    {
        $sBloc = <<<CODE_BLOC
                  <div class="sin_acc">
                    <h5>{$ligne["che_nom"]} - {$ligne['NumSin']} {$ligne["NumCarteVeto"]}<i  class="sinistre_statut {$class}"> </i></h5>
    {$lignesSinistres}              </div>

    CODE_BLOC;
        return $sBloc;
    }


    function setLigneSinistre($f, $ligne, $onglet, $XSousFamilleSinistre, $param)
    {
        $sDateSinistre = date_us2fr($ligne['DateSinistre']);
        $sBloc = <<<CODE_BLOC
                    <div class="cont_sin_acc">
                      <p>
                        <span class="label2"><label>Date du sinistre</label> : {$sDateSinistre}</span>
                        <span class="label2"><label>Carte N°</label> : {$ligne["NumCarteVeto"]}</span>
                        <span class="label2"><label>{$onglet[98]}</label> : {$XSousFamilleSinistre[$ligne['SousFam']]}</span>
                        <span class="label2"><label>{$onglet[99]}</label> : {$ligne['Mt11Remb']}</span>
                        <span class="label2"><label>{$onglet[101]}</label> : {$ligne['MtSolde']}</span>
                      </p>
                      <form class="pls_coul" method="post" name="{$f}" action="sinistre_detail.php">
                        <input type="hidden" name="NumSin" id="NumSin" value="{$ligne['NumSin']}" />
                        <input type="hidden" name="NumCarteVeto" id="NumCarteVeto" value="{$ligne['NumCarteVeto']}" />
                        <input type="hidden" name="NumPol" id="NumPol" value="{$ligne['NumPol']}" />
                        <input type="hidden" name="NumChe" id="NumChe" value="{$ligne['NumChe']}" />
                        {$param}
                      </form>
                    </div>
                    <!-- cont_sin_acc -->

    CODE_BLOC;
        return $sBloc;
    }

    $sListeSinistres = '';
    /* Construction de la liste des sinistres */
    if($totalRows_liste_client > 0)
    {
        $z = 0;
        $id_client  = null;
        $id_contrat = null;
        $sLignesSinistres = '';
        $sLignesContrats  = '';
        $aLignePrecedente = null;
        while(false != ($row_liste_client = mysql_fetch_assoc($liste_client)))
        {
            $f = "form_" . $z;
            $ff = "fform_" . $z;
            $z++;
            switch($row_liste_client['StatutSinistre'])
            {
                case 1 :
                    $param = '<input type="submit" name="couleur" id="couleur" value="Impossible" class="coul_bt gris"/>'; // IMPOSSIBLE GRIS
                    $class = 'gris';
                    break;
                case 2 :
                    $param = '<input type="submit" name="couleur" id="couleur" value="En Etude" class="coul_bt jaune"/>'; //EN ETUDE JAUNE
                    $class = 'jaune';
                    break;
                case 3 :
                    $param = '<input type="submit" name="couleur" id="couleur" value="Accepté" class="coul_bt vert"/>'; //ACCEPTE VERT
                    $class = 'vert';
                    break;
                case 4 :
                    $param = '<input type="submit" name="couleur" id="couleur" value="Refusé" class="coul_bt rouge"/>'; //REFUSE ROUGE
                    $class = 'rouge';
                    break;
                default :
                    $param = '<input type="submit" name="couleur" id="couleur" value="Cloturé" class="coul_bt bleu" />';
                    $class = 'bleu'; //cloturé
            }
            /* On va vérifier si on est toujours dans le même contrat ou bien dans un autre contrat : */
            if($id_contrat != $row_liste_client['NumCarteVeto'])
            {
                /* On change de contrat, donc si il y a des lignes de sinistres prêtes, on va fermer le bloc des contrats correspondant */

                /* On vérifie si on est toujours sur les contrats du même client ou d'un autre client */
                if($id_client != $row_liste_client['id']) // ATTENTION, vérifier l'index de l'identifiant du client, remplacer « id » au besoin.
                {
                    $id_client = $row_liste_client['id'];
                    //...
                }
                $id_contrat = $row_liste_client['NumCarteVeto'];
            }
            else
            {
                $sLignesSinistre .= setLigneSinistre($f, $row_liste_client, $onglet, $XSousFamilleSinistre, $param);
            }
            /* On stocke la ligne pour disposer au prochain tour des bon identifiants si nécessaire. */
            $aLignePrecedente = $row_liste_client;
        }
    }
    else
    {
        $sListeSinistres = <<<
        <p>{$onglet[127]} {$row_liste_client["NumCarteVeto"]} …</p>

    CODE_LISTE;
    }

J'ai ajouté quelques commentaires. Je te laisse analyser ça et tâcher d'en saisir le fonctionnement. L'idée de base, je pars de la dernière entité qui est la ligne où on traite le sinistre, puis je remonte pour traiter le contra et enfin je termine avec le client.

Là, je vais devoir m'absenter, retour pas prévu avant la fin d'après-midi. Essaye d'avancer dans cette voie, ça devrait bien avancer. Il manque des bouts notamment le code global construit à stocker dans une variable et à afficher APRÈS la boucle WHILE.

 
Par nanou  -  Le 21/02/2016 17:07  -  Haut de page  - 

Merci encore
Je n'ai pas réussi
Je vais sans doute devoir me rabattre sous les sous-requêtes.
J'y ai passé tant de temps que cela n'est pas raisonnable
Mais je suis frustrée car je suis sûre que je ne suis pas loin et que si j'y arrive pour ce sujet, je pourrai transposer cette méthode dans des cas très fréquents.
Les avantages que j'y voie: des requêtes performantes, faciles à maintenir, qui font remonter toutes les données nécessaires 1 x pour toutes
Ensuite le découpage et la présentation des résultats groupés ou non devrait être facilité par l'usage de jquery.
Je veux y arriver !!
merci en tous cas encore pour votre aide

 
Par Cyrano  -  Le 21/02/2016 17:29  -  Haut de page  - 

Dites-moi donc où ça a coincé.

Je suis bien conscient que ce n'est pas évident, mais là, il faut s'en remettre exclusivement à la logique.

Je vais tâcher de donner une explication visuelle.

On doit construire d'abord les lignes de sinistre. Chaque tour de boucle va donc stocker une nouvelle ligne de sinistre. On part sur l'alternative que c'est un nouveau client ou le premier (si id_client différent de $ligne['cli_id'], et en passant les bons paramètre à la fonction qui construit chacune des lignes de sinistre, ça va donner à terme ceci (simplifié à l'extrême pour une meilleure compréhension) :

   - Sinistre 1 ...
   - Sinistre 2 ...

Si on change de contrat, alors on va construire un bloc de contrat en lui passant la ligne de données et ce qu'on a enregistré précédemment en lignes de sinistres. On fait ça avec la fonction de construction de blocs de contrats, ce qui va nous retourner :

  - Contrat 1
    - Sinistre 1 ...
    - Sinistre 2 ...

À ce stade, il faut ré-initialiser la variable de stockage des lignes de sinistres pour les prochains blocs;

Si je change de client, alors je vais construire le bloc client avec la fonction de construction de bloc de client, en lui passant la ligne de données et les blocs de contrats stockés :

Client Xyz
  - Contrat 1
    - Sinistre 1 ...
    - Sinistre 2 ...

On réinitialise la variable de stockage des blocs de contrat et on continue.

Est-ce qu'il y a un point ou un autre qui ne serait pas clair ?

 
Par nanou  -  Le 21/02/2016 18:03  -  Haut de page  - 

J'avais trouvé une solution qui consistait simplement à
poser mes 3 variables
$NumCli = "";
$NumPol = "";
$NumSin = "";

ajouter une condition
if avec le test de ces 3 valeurs de rupture (
et affichage de chacune des 3 valeurs
si et seulement si différente mais bon ...
Ce qui évitait de passer par des fonctions complexes à mettre en oeuvre et à maintenir.

 
Par nanou  -  Le 21/02/2016 18:10  -  Haut de page  - 

...

<?php 
    while ($row_liste_client = mysql_fetch_array($liste_client))
    { if ($NumCli != $row_liste_client['NumCli'])
    { $NumCli = $row_liste_client['NumCli'];
    //echo "toto" .$NumCli."</br>";
    ?>

Cà ça marche ,( c'est un 1er pas) sans passer par un GROUP By, je n'affiche que les 12 clients au lieu de les afficher 38 x
mon affichage est totalement en vrac donc je regarde ce qui va pas

 
Par nanou  -  Le 02/03/2016 10:19  -  Haut de page  - 

Bonjour,
je reviens sur le sujet car je pense l'avoir résolu, dans l'idée de partager car vous avez passé du temps à regarder cette question :
voici le code que j'ai trouvé : le principe appliqué
initialiser mes 3 variables qui sont mes 3 rubriques clés (numcli, numpol, numsin)
puis à l'intérieur du while de ma requête avec jointure
poser les conditions "tant que différent de… et et tant que pas vide"
L'astuce consiste à intégrer les fins de div dans la conditions précédente
pour qu'elles se ferment au bon endroit

voici ce que cela donne. et merci encore pour votre aide

    while ($row_sinistre = mysql_fetch_assoc($sinistre)) {   
    if ($max > 0) {   
        if ($NumCli != $row_sinistre['NumCli']) {   
        if (!empty($NumCli)) {  
            echo "</div>";  
            echo "</div>";  
            }                  
            $NumCli = $row_sinistre['NumCli'];  
                echo "<h3>".$row_sinistre['Nom'];  
                echo "<div class='contenu_accordion'>";  
                echo "<div class='sin_acc'>";  
            } // FIN BOUCLE NumCli  

                if (($NumPol != $row_sinistre['NumPol'])) {                   
                $NumPol = $row_sinistre['NumPol'];  
                echo "</span><h4> ".$row_sinistre['che_nom'];                      
                }// FIN BOUCLE NumPol  

                    if ($NumSin != $row_sinistre['NumSin']){  
                    $NumSin = $row_sinistre['NumSin'];  
                    }// FIN BOUCLE SINISTRE      
            }// FIN
 
Par Cyrano  -  Le 02/03/2016 10:25  -  Haut de page  - 

À vue d’œil, c'est tout à fait ça.

Il manque la fin du code, mais je présume qu'il y a des fermetures de balises après la fin de la boucle while. À vérifier dans la source générée, mais globalement c'est ça. :)

 
Par nanou  -  Le 02/03/2016 11:29  -  Haut de page  - 

Maintenant j'aurai une question sur l'optimisation des requêtes avec jointure :
J'ai fait une requête qui joint 8 tables
cette solution me permet de remonter tous les éléments utiles en une seule fois
et ensuite de passer toutes mes variables en POST pour la navigation dans les différents résultats
sans devoir faire des sous-requêtes.
A six tables par LEF JOIN, la requête fonctionne correctement
à 8 je n'ai plus de résultat affiché…
Est-ce que l'usage de parenthèses permet d'optimiser?
J'ai fait un select * et je sais qu'il vaudrait mieux cibler sur les rubriques utiles pour que ce soit moins gourmand
mais il m'en manque toujours et l'affichage ne se fait pas :
voici ma requête
voyez-vous une façon de mieux la formuler?
SELECT *
FROM tb_sante_SinVetClin svc
LEFT JOIN tb_sante_clinique clin
ON svc.refNumClin = clin.NumClin
LEFT JOIN tb_sante_clients cli
ON svc.refNumCli = cli.NumCli
LEFT JOIN tb_sante_contrats con
ON svc.refNumPol = con.NumPol
LEFT JOIN tb_cheval che
ON svc.refNumChe = che.NumChe
LEFT JOIN tb_sante_sinistres sin
ON svc.refNumSin = sin.NumSin
LEFT OUTER JOIN tb_sante_factures fac
ON svc.refNumSin = fac.NumSin
LEFT OUTER JOIN tb_sante_paiements pai
ON svc.refNumSin = pai.NumSin
WHERE svc.refNumClin = '".$_SESSION["s_NumClin"]."' AND sin.NumCarteVeto !=''";

 

Ajouter une réponse à la discussion

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