IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bibliothèques et frameworks PHP Discussion :

Création d'un menu pseudo-fixe [CakePHP]


Sujet :

Bibliothèques et frameworks PHP

  1. #1
    Membre actif
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2007
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Gers (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Octobre 2007
    Messages : 282
    Points : 229
    Points
    229
    Par défaut Création d'un menu pseudo-fixe
    Bonjour à tous

    Je suis en train de faire un site internet qui remplacera un site codé par les pieds via wordpress.
    Je dispose d'une table respectant les conventions cakephp. Voici ma table:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    CREATE TABLE IF NOT EXISTS `pages` (
      `id` int(255) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
      `slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
      `content` longtext COLLATE utf8_unicode_ci NOT NULL,
      `lft` int(255) NOT NULL,
      `rght` int(255) NOT NULL,
      `parent_id` int(255) NOT NULL,
      `online` int(11) NOT NULL,
      `menu_id` int(11) NOT NULL,
      PRIMARY KEY (`id`),
      KEY `left` (`lft`),
      KEY `rght` (`rght`),
      KEY `parent_id` (`parent_id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
    Je souhaite concevoir un menu html de cette forme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <ul>
        <li><a>niveau 1</a></li>
        <li><a>niveau 2</a><ul>
            <li><a>niveau 2.1</a></li>
            <li><a>niveau 2.2</a></li>
        </ul>
        <li><a>niveau 3</a></li>
    </ul>
    En recherchant sur internet, j'ai trouvé une méthode mais cette dernière, est pour moi, un peu de bricolage. Voici comment je procède.
    Dans mon fichier PagesController.php:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <?php
    function index() {
        $d = array();
        $d['menu'] = $this->getMenu(
            $this->Page->find('all', 
                array(
                    'order' => array('Page.lft ASC'),
                    'conditions' => array('Page.menu_id' => 1),
                )
            )
        );
        $this->set('menu', $d['menu']);
        $this->render('index');
    }
     
    function getMenu($data) {
        $d = array();
        foreach($data as $cat) {
            if($cat["Page"]["parent_id"] == 0){
                $d['pages'][] = $cat["Page"];
            }else{
                $d['ss-pages'][] = $cat["Page"];
            }
        }
        return $d;
    }
    ?>
    Dans ma vue index du model page:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <?php
        $ci = 0;  
        $pages = $menu['pages'];  
        $ss_pages = $menu['ss-pages'];
        foreach($pages as $cat):  
            if($ci != $cat["id"]):
                $ci = $cat["id"];
                echo "<li><a href=\"\">";  
                echo $cat['name']."</a>";
                echo "<ul class=\"ssmenu\">";
                foreach($ss_pages as $ssC):
                    if($cat["id"] == $ssC["parent_id"]):
                    echo "<li><a href=\"#\">".$ssC['name']."</a>";
                    endif;
                endforeach;
                echo "</ul>";
                echo "</li>";                    
            endif;
        endforeach;
    ?>
    Dans mon layout, j'appelle mon menu de cette manière:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <?php
         echo $this->requestAction(array('controller' => 'pages', 'action' => 'index'));              
    ?>
    Cela marche, mais je trouve que cette méthode est un peu "moche" à mon goût.

    J'ai trouvé qu'il existe un helper treehelper sur le net: https://github.com/CakeDC/utils/blob...TreeHelper.php qui permet de récupérer la même structure html, sauf pas de système de lien. J'ai fait de essaie avec ces codes sources suivantes:
    Fonction nav de mon controller pages:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php
    function nav(){
        $pages = $this->Page->find('all', 
            array(
                'order' => array('Page.lft ASC'),
                'conditions' => array('Page.menu_id' => 1),
            )
        );
        return $pages;
    }
    ?>
    Mon element nav.ctp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <?php $pages = $this->requestAction(array('controller' =>'pages', 'action'=>'nav', 'admin'=>false)); ?>
    <?php echo $this->Tree->generate($pages, 
        array(
            'model'=>'Page',
            'type'=>'ul',
        )
    );
    ?>
    et dans mon layout:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <?php echo $this->element('nav'); ?>
    Auriez vous un helper ou des astuces à me conseiller dans le but de réaliser ma structure html que je souhaite?
    Merci d'avance.
    lemirandais

  2. #2
    Membre expert
    Avatar de Spartacusply
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2011
    Messages
    1 723
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2011
    Messages : 1 723
    Points : 3 274
    Points
    3 274
    Par défaut
    Bonjour à toi,

    dans les deux cas, que mettrais-tu dans l'attribut "href" de tes balises "a" ?

    Remarque dans ta première méthode, tu fais une entorse au modèle MVC, de manière générale on ne doit jamais appeler une méthode d'un contrôleur à partir d'un contrôleur (que ce soit le même ou un autre d'ailleurs). Ta fonction getMenu devrait se trouver dans la fonction index elle-même, dans le modèle (rassembler avec le findAll du coup pour rester logique) ou dans un composant (mais moins pertinent vu qu'elle ne sera appelé qu'à cet endroit là à priori).

    Autrement, cela est faisable sans problème. Pour améliorer la qualité du code, quand il s'agit d'une arborescence, toujours penser récursivité, donc méthode recursive (qui s'appelle elle-même).

    D'ailleurs si tu regardes le code du treeHelper, c'est ce qui est fait. Par contre je le vois difficilement applicable avec des liens, parce que justement quoi mettre dans les "href" ?
    Un message utile vous a aidé ? N'oubliez pas le

    www.simplifions.fr - Simplifier vos comptes entre amis !

  3. #3
    Membre actif
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2007
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Gers (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Octobre 2007
    Messages : 282
    Points : 229
    Points
    229
    Par défaut
    Merci pour cette réponse, Spartacusply.

    La première méthode que j'ai utilisé est du bricolage comme j'ai dit. Même si cela fonctionne, je trouve vraiment la méthode "dégueulasse".

    Concernant les urls, je n'y ai pas vraiment réfléchi.
    A l'heure actuelle, mes urls pour les articles d'actualité sont de la forme news/id/titre.html (oui, je tiens beaucoup à l'extension).
    Niveau référencement, je ne me suis pas posé la question.
    Vu que mon site aura 2 niveaux, je pensais peut-être à des urls de cette forme:
    Niveau 1 ndd/slug-de-la-page.html
    pour les Niveau 2 ndd/slug-de-la-page-parente_slug-de-la-page-fille.html

    Quand penses-tu? Je ne suis pas un pro du référencement.

    Merci en tout cas.
    lemirandais

  4. #4
    Membre expert
    Avatar de Spartacusply
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mai 2011
    Messages
    1 723
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2011
    Messages : 1 723
    Points : 3 274
    Points
    3 274
    Par défaut
    La première méthode que j'ai utilisé est du bricolage comme j'ai dit. Même si cela fonctionne, je trouve vraiment la méthode "dégueulase".
    Oui elle est pas propre je suis d'accord mais elle ne l'est pas parce qu'elle n'est pas codée de manière recursive ! En effet, si tu souhaites faire un menu de plus de deux niveau, tout ton mécanisme s'écroule (ce qui en fait un mauvais mécanisme) mais l'idée à la base est une bonne idée.

    Tu n'a surement pas vu que Cake possède une méthode de recherche imbriquée en la présence de find('threaded'), ce qui lui permet en gros de faire ta méthode "getMenu" de manière extrêmement propre et sur un nombre de niveau illimité.

    Quand penses-tu? Je ne suis pas un pro du référencement.
    L'url telle quelle sera affichée à l'écran n'a aucune importance. Du moins ce n'est pas ici qu'il faut s'en préoccuper, ici il faut uniquement penser en terme de contrôleur, d'action et de paramètres. Ensuite, tout se passe dans la classe Routing (tout est bien expliqué et documenté) pour transformer tout ça en une url compréhensible par l'utilisateur et bien référéncé par google. Mais toi tu dois toujours indiqué controleur/action/paramètres, et cake se chargera lui-même (en paramétrant toi-même la classe router comme tu le souhaites) d'afficher lui-même ce que tu lui a paramétré

    Au final, voici une manière simple et élégante de faire ce que tu souhaites :

    Class PagesController :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class PagesController extends AppController {
     
        public $helpers = array('Menu');
     
        public function index($idMenu) {
            $pages = $this->Page->find('threaded', array(
                'conditions' => array('menu_id' => $idMenu),
                'fields' => array(
                    'Page.id',
                    'Page.name',
                    'Page.parent_id'
                ),
                'order' => array('Page.lft ASC'),
            ));
            $this->set('pages', $pages);
        }
     
    }
    Page index.ctp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // C'est plus propre de passer par un helper pour faire de la récursivité
    echo $this->Menu->create($pages);
    Class MenuHelper :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class MenuHelper extends AppHelper {
     
        public $helpers = array('Html');
     
        public function create($pages, $level = 1) {
            $res = "<ul>";
            foreach ($pages as $page) {
                $res .= "<li  class='level$level'>" . $this->Html->link($page['Page']['name'], array('controller' => 'news', 'action' => 'view', $page['Page']['id']));
                if (!empty($page['children'])) {
                    //Appel de la même méthode pour les enfants
                    $res .= $this->create($page['children'], $level + 1);
                }
                $res .= "</li>";
            }
            $res .= "</ul>";
     
            return $res;
        }
     
    }
    Rendu Html final :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <ul>
        <li class="level1"><a href="/news/view/1">Level 1</a></li>
        <li class="level1"><a href="/news/view/2">Level 2</a>
            <ul>
                <li class="level2"><a href="/news/view/4">Level 2.1</a></li>
                <li class="level2"><a href="/news/view/5">Level 2.2</a></li>
            </ul>
        </li>
        <li class="level1"><a href="/news/view/3">Level 3</a></li>
    </ul>
    Un message utile vous a aidé ? N'oubliez pas le

    www.simplifions.fr - Simplifier vos comptes entre amis !

  5. #5
    Membre actif
    Homme Profil pro
    Développeur Web
    Inscrit en
    Octobre 2007
    Messages
    282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Gers (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Octobre 2007
    Messages : 282
    Points : 229
    Points
    229
    Par défaut
    Merci beaucoup Spartacusply.
    Cela fonctionne exactement comme je le souhaite. Je vais un peu modifier le menuhelper afin d'ajouter quelques fonctionnalités supplémentaire.
    Merci beaucoup.

    Je marque en résolu.


    J'ai apporté quelques modifications lié à mon projet, mais je pense que cela pourra aider pas mal de monde, et même évolué. J'ai posté un gist sur github, en citant le code d'origine qui a été conçu par toi Spartacusply: https://gist.github.com/leknoppix/11408543.

    Bonne soirée.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Inno Setup] Création d'un menu d'install "propre"
    Par gizmo2 dans le forum Autres langages
    Réponses: 1
    Dernier message: 18/01/2006, 16h27
  2. Menu vertical fixe
    Par batmat86 dans le forum Général JavaScript
    Réponses: 15
    Dernier message: 10/01/2006, 02h54
  3. Création d'un menu (de langue) dynamiquement
    Par neb-toi dans le forum Langage
    Réponses: 7
    Dernier message: 21/11/2005, 15h27
  4. Création d'un menu
    Par gros bob dans le forum OpenGL
    Réponses: 3
    Dernier message: 15/01/2004, 08h43
  5. [Flash 5] Création d'un menu
    Par WriteLN dans le forum Flash
    Réponses: 4
    Dernier message: 09/10/2003, 13h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo