Bonjour,
Je suis actuellement entrain de creer un blog sous Cakephp.
J'ai fait le systeme de categories grace a TreeBehavior.
J'ai bien mes multi categories mais la ou je bloque c'est lorsque j'assigne un article sur la categorie 3 (Telephone) je ne vois pas comment je le recupere si je clique sur la categorie
1 en suite 2 puis 3 qui elle m'affiche directement l'article en rapport avec la categorie 3.

Cat 1:
Technologie
Cat 2:
Telephone
Cat 3:
iPhone | Android | BlackBerry

L'idee c'est lorsque je rentre dans la cat 1 je poursuit sur la cat 2 et puis la cat 3 qui elle va sme permettre de consulter que les articles sur Android par exemple.
Voici mon controller

<?php

class CategoriesController extends AppController{

    public $name = 'Categories';

    public function index(){

        $Categorylist = $this->Category->generateTreeList(null,null,null, ' - ');

        $this->set(compact('Categorylist'));

    }

    public function allCategory(){

        return  $this->Category->find('all',array(
            'recursive' => -1
        ));

    }

}

Mon model:

<?php

class Category extends AppModel{

    public $name = 'Category';
    public $actsAs = array('Tree');

}

et la vu

<h1>Categories</h1>

<?php
 $menu =  $this->requestAction(array('controller' => 'Categories', 'action' => 'allCategory'));
         foreach($Categorylist as $key => $value){

echo "<li>".$this->Html->link($value,array('controller' => 'categories', 'action' => ''))."</li>";

}
echo "</ul>";?>

Je vous remercie d'avance de votre aide

Danny,

29 réponses


Bonjour.
Il n'y aurait pas un petit problème dans les catégories que tu nous montre ?
Ta catégorie 3, elle s'appelle comment exactement ?
iPhone, Android et BlackBerry, ce ne serait pas plutôt des sous-catégories ?

donny
Auteur

Bonjour Lartak,

En effet, la categorie 2 et 3 sont bien des sous categories de la categories 1

Donc la catégorie 2 est une sous-catégorie de la catégorie 1.
Mais dans Catégorie 3 tu as : iPhone, Android et BlackBerry, ce sont des sous-catégorie de quoi, vu que tu as mis 3 noms ?
Des sous-catégories de la catégorie 2 ?

donny
Auteur

Voila un schema:
-Technologie
-- Mobile
--- Android
--- iPhone
--- Blackberry

Le but est que je passe d'abord par technologie, en suite mobile et puis je choisie Android et la je tombe que sur des articles qui parlent d'Android par ex

D'accord.
Et donc, l'aide que tu veux, concerne ta fonction allCategory qui agit sur ton requestAction ?
Tu voudrais qu'au fur et à mesure que tu rentres dans une catégorie qu'il ne liste que ses sous-catégories ?

donny
Auteur

Oui voila, je vois pas comment je peux faire en sorte que lorsque je clique sur Technologie j'arrive sur "mobile" et en suite je rentre dans Android et que la je show tout les articles concernant Android
(C'est pour ca que mon action je l'ai laisser vide)

echo "<li>".$this->Html->link($value,array('controller' => 'categories', 'action' => ''))."</li>";

Tu peux créer une fonction show ou view, tu peux même l'appeler comme tu veux, il n'y a pas de convention pour ça, tu peux par exemple l'appeler categorie, dans ton controller en rapport avec les articles (posts ou articles), par exemple :

public function categorie($id =null) {
    if (isset($id)):
        $post = $this->Post->find('first', [
            'conditions' => [
                'Post.category_id' => $id
            ]
        ]);
        $this->set(compact('post'));
    endif;
}

Puis sur la vue correspondante, tu affiches ton post.
Ce n'est qu'un exemple.

donny
Auteur

Merci pour l'exemple mais je ne vois toujours pas comment je navigue entre les sous categories en partant de la premiere tu vois?

Regardes ici tu verras un exemple et je t'y ai affiché une partie du code qui a servi : Exemple » catégories.

donny
Auteur

Merci beaucoup pour ton exemple Lartak !
Ca m'aide enormement, juste c'est possible de voir aussi comment tu affiche les categories precetente dans la navbar par exemple:
Mobile -> iPhone -> titre de l'article?
Mais aussi l'article apparait selon les categories

c'est possible de voir aussi comment tu affiche les categories precetente dans la navbar par exemple:

Tu veux parler dans le fil d'ariane (breadcrumb) ?
Si oui, c'est avec la méthode getPath du TreeBehavior.

J'ai rajouté les codes de la fonction index des catégories qui transmet également les articles liés aux catégories et la partie breadcrumb).

donny
Auteur

Oui je parlais bien du breadcrumb.
Ca fonctionne nickel, tu pense que le mieux c'est d'afficher mes postes depuis mon Controller categories ou bien PostController ?
Je pense que le plus logique c'est dans categories mais j'ai un doute sur l'affiche comment tu t'es pris pour l'affichage de ton article ?

tu pense que le mieux c'est d'afficher mes postes depuis mon Controller categories ou bien PostController ?

Par rapport à l'exemple, j'affiche la liste des articles selon la catégorie sélectionnée via la fonction index du controller Categories et j'affiche un article en particulier via la fonction index du controller Posts.

comment tu t'es pris pour l'affichage de ton article ?

Pour l'affichage d'un article en particulier (Lire l'intégralité de l'article), je l'ai mis dans la fonction index du controller Posts, vu que l'id du post est passé par les paramètres de l'url, il me suffit de la récupérer, de faire le find dessus et d'envoyer la variable du post à la vue.

donny
Auteur

Merci pour tes reponses Lartak,
juste deux derniere question, voila si jamais je souhaite afficher chaque categories et ses sous categories dans des colonnes specifique par exemple:

Telephone

  • Mobile
  • Fixe
  • Faxe

Ordinateur

  • Portable
  • Salon

As-tu une idee de comment je peux m'y prendre ?

Et la seconde question c'est imaginon que je souhaite faire un arbre sur le cote ou j'affiche que les categories 1 et une fois que je passe ma souris dessus (hover) j'affiche que les sous categories de la categorie 1 ?
Comment est-ce possible avec Cake?
J'ai l'idee de faire plusieurs requette pour chaque categories et de sctocker le resultat dans des variables, mais a long terme c'est pas fiable

Bonjour.

si jamais je souhaite afficher chaque categories et ses sous categories dans des colonnes specifique

J'ai un peu de mal à te suivre, que veux-tu dires par colonnes spécifiques ?
Si je m'en réfère à ton exemple, tu voudrais afficher les catégories et ses sous-catégories directes, sous forme de liste incrémentielle, comme si tu faisais un GROUP BY sur les catégories parentes pour afficher ses sous-catégories et ne pas avoir seulement les catégories d'un seul niveau de listées, c'est ça ?

donny
Auteur

En effet, je me suis mal expliquee.
Imagine dans la page /categories
J'ai un front qui contient 2 div
Une div qui porte le nom de "mobile" elle vas contenir en titre "Telephone" et on affiche bien "Portable, Fixe" par exemple
et a gauche j'ai une autre div au nom de PC
Qui elle fonctionne dans le meme systeme que la div "mobile" sauf que les noms de categories/sous-categories seront different.
Oui c'est comme un sorte de GROUP BY sur les categories parents

Si je comprends bien donc, ce que tu veux faire c'est ce que j'ai fais comme modification sur l'exemple.
Tu verras deux comportements différents, l'un dans la navbar et l'autre en tant que sidebar.

donny
Auteur

Bonsoir,
Desole pour le temps de reponse.
Oui en effet, c'est bien ce dont je veux faire de pouvoir afficher toutes les categories dans plusieurs div' sachant que je peux avoir environs 10 categories differente

Bonjour.

public function allCategories($id = null) {

    $_params = [
        'fields' => [
            'Category.name'
        ],
        'contain' => [
            'Children' => [
                'fields' => [
                    'id', 'name', 'slug'
                ],
                'order' => [
                    'name' => 'ASC'
                ]
            ]
        ]
    ];

    if (isset($id)):

        $params = [
            'conditions' => [
                    'Category.id' => $id
            ]
        ];

    else:

        $params = [
            'conditions' => [
                'Category.parent_id' => 0
            ]
        ];

    endif;

    $params = array_merge($_params, $params);

    return $this->Category->find('threaded', $params);
}

Et pour la sidebar :

<?php
$id = isset($this->request->params['category_id']) ? $this->request->params['category_id'] : null;
$categories = $this->requestAction(['controller' => 'categories', 'action' => 'allCategories', (isset($id) ? $id : null)]);

if (isset($categories) && !empty($categories)):

    foreach ($categories as $categorie): ?>
    <div class="list-group">
        <h4><?= $categorie['Category']['name'] ?></h4>
        <?php foreach ($categorie['Children'] as $children): ?>
            <?= $this->Html->link($children['name'],
                [
                    'controller' => 'categories',
                    'action' => 'index',
                    'category_id' => $children['id'],
                    'slug' => $children['slug']
                ],
                [
                    'class' => 'list-group-item',
                    'escapeTitle' => false
                ]
            ) ?>
        <?php endforeach ?>
    </div>
    <?php endforeach;
endif; ?>

Il faut bien sûr que dans ton modèle Category que tu aies :

public $hasMany = [
    'Children' => [
        'className' => 'Category',
        'foreignKey' => 'parent_id'
    ],
    'Post'
];
donny
Auteur

Bonsoir,
Merci pour ton aide,
avant de clos le sujet, j'ai juste deux questions

1)
J'ai l'impression que escape => False dans mon cas ne fonctionne pas :
<li>
<?= $this->Html->link(
$this->Html->tag('span',array('class' => 'arrow')),
$categorie['Category']['name'],
[
'controller' => 'categories',
'action' => 'index',
'category_id' => $categorie['Category']['id'],
'slug' => $categorie['Category']['slug'],
],['class' => 'category_link'],['escape' => false]
); ?>
</li>

2) Si jamais demain je souhaite creer une page qui vas avoir comme URL /article-perso

Dedans je vais avoir 2 div

<div class="icon-special1">
{content}
</div>

<div class="icon-special2">
{content}
</div>

Comment je peux placer le nom de la categorie dans la div dedie, car la div 1 aura une icon differente de la div 2
?

Bonsoir.
Le paramètres escape est dans les options et donc dans le second tableau *(avec class dans ton exemple.

Ensuite, dans la méthode tag le deuxième argument est de type string pour le texte du tag et non pour un tableau.

2) Si jamais demain je souhaite creer une page qui vas avoir comme URL /article-perso

Dedans je vais avoir 2 div

Je ne comprends pas là.

donny
Auteur

Bonjour,

Meme en mettent les bons params, j'ai toujours le souci

<li>
                                <?= $this->Html->link(
                                $this->Html->tag('span','',array('class' => 'arrow')),
                                $categorie['Category']['name'],
                                [
                                'controller' => 'categories',
                                'action' => 'index',
                                'category_id' => $categorie['Category']['id'],
                                'slug' => $categorie['Category']['slug'],
                                ],['class' => 'category_link','escape' => false]
                                ); ?>
                            </li>

Ca me retourne:

<li>around<a marked="1" href="/pages/Articles et Test" controller="categories" action="index" category_id="1" slug="article-test" onclick="if (confirm({&quot;class&quot;:&quot;category_link&quot;,&quot;escape&quot;:false})) { return true; } return false;">&lt;span class="arrow"&gt;&lt;/span&gt;</a></li>

J'essaye de debug mais sans success :/

Sinon pour la deuxieme question voici un petit schema:
http://image.noelshack.com/fichiers/2015/40/1443444953-capture-d-ecran-2015-09-28-a-14-54-34.png

Le but c'est de pouvoir place chaque categorie dans une div specifique par exemple Mobile vas avoir en icone un telephone, un ordinateur pour la div Informatique

Bonsoir.
Remplaces par :

<li>
    <?= $this->Html->link(
        $this->Html->tag('span','',array('class' => 'arrow')) . $categorie['Category']['name'],
        [
            'controller' => 'categories',
            'action' => 'index',
            'category_id' => $categorie['Category']['id'],
            'slug' => $categorie['Category']['slug'],
            ], [
            'class' => 'category_link', 
            'escape' => false
            ]
    ); ?>
</li>

C'est sur que si tu met le label de ton lien en second argument, les paramètres de l'url seront considérés comme des attributs du lien étant donné que l'url est situé en troisième argument.
Pour rappel :

$this->Html->link($name, $url, $params)
donny
Auteur

Bonjour,
Merci pour l'aide, cela fonctionne.
As-tu une idee comment je peux m'y prendre pour la 2eme question?

Le but c'est de pouvoir place chaque categorie dans une div specifique par exemple Mobile vas avoir en icone un telephone, un ordinateur pour la div Informatique

Je t'ai déjà montré comment faire pour afficher chaque catégorie dans une div différente, je ne vois donc pas quelle peut être ta question.
Dans l'image que tu montres, il y a simplement les catégories dans des blocs différents, tout comme l'exemple que je t'avais montré, si tu veux une icone spécifique différente pour chaque catégorie, il te suffit par exemple d'ajouter un champ dans ta table de catégories et d'y saisir l'icône voulu pour la catégorie.
Ensuite il te suffira d'afficher l'icône pour la catégorie dans la boucle.

donny
Auteur

Bonjour merci pour l’aide c’est OK pour les div je stocke les icons en DB et les affiches selons les cas.
Par curiosité comment as-tu fait en sorte d’avoir la navbar (en haut) et lorsqu’on clique on affiche les sous-catégories ?

J'ai simplement fait le même code que pour la sidebar, sauf forcément les éléments html qui changent un peu et je ne fais pas la vérification si l'id est transmise par l'url, étant donné que je n'affiche que les catégories qui n'ont pas de parents et leurs enfants directs.
Il est bien sûr inutile de faire fonctionner les deux systèmes, un seul suffit, c'était juste pour te montrer qu'avec le même code (à un détail prêt) que tu peux faire deux affichages différents, pour deux utilisations différentes également.

donny
Auteur

En fait ce que je cherche a faire c'est lorsque je passe la souris sur une categorie j'ai une autre div qui s'affiche en hover montrant ses enfants.
J'ai essayer avec le code de la slidebar mais je n'arrive pas a le faire correctement

donny
Auteur

Bonjour, j'essaye toujours de resoudre le probleme que j'ai explique plus haut.
C'est donc pour cela que je me permet un petit UP.