Bonjour à tous,

J'utilise le système de TreeBehavior sur CakePHP. Voici mon code dans ma sidebar sur mon front qui me permet de lister les catégories.

Post/index.ctp

<h3 class="module-title">Catégories</h3>
                <?php $categories = $this->requestAction(array('action' => 'catlist' )); ?>
                <ul class="nav nav-list">
                    <?php foreach($categories as $k => $v): $v = current($v); ?>
                        <li>
                            <?php echo $this->Html->link($v'path'],$v'link'],array('escape' => false)); ?>
                        </li>
                    <?php endforeach; ?>
                </ul>

PostController -> catlist()

function catlist()       
            $categories = $this->Category->generateTreeList(null,null,null,"    ");
            $categories_array = array();
            foreach($categories as $k => $v)
            {
                $categories_array$k] = $this->Category->find('first', array(
                    'conditions' => array('Category.id' => $k),
                    'fields' => array('Category.id','Category.name','Category.slug','Category.modified')
                    ));
                $categories_array$k]"Category"]"path"] = $v;
            }

            return $categories_array;
       }

Ce code fonctionne très bien. Par contre, j'ai l'impression que lorsque j'aurai vraiment beaucoup de catégorie, les requetes SQL seront très nombreuses a force de faire un find à chaque fois. :(

A votre avis, comment pourrais-je alléger cela ?

Merci à vous!

Amicalement,
Ilan

10 réponses


Salut, si tu veux tu peut toujours stocker le résultat de ton find dans une variable de session. Ensuite au moment de l'affichage tu vérifie si cette variable existe et si elle existe, tu récupère le contenu plutôt que d'appeler catlist();

Ilan
Auteur

Bonjour, Merci pour votre réponse.? En faisant quelques petites recherche, j'ai finalement opté pour la solution "threaded" qui niveau requêtes, n'en fait plus qu'une ce qui allège agréablement le site. PostController.php [code]function catlist() { $categories_array = $this->Category->find('threaded', array( 'conditions' => array('Category.online' => 1), 'fields' => array('Category.id','Category.name','Category.slug', 'Category.online', 'Category.post_count', 'Category.parent_id') )); return $categories_array; }[/code] Par contre, ma liste dans la vue c'est un peu la gadou... Post/index.ctp [code]

Catégories

<?php $categories = $this->requestAction(array('action' => 'catlist' )); ?>
<?php foreach($categories as $k => $v): ?> - params['slug']) && $cat['id']==$v['Category']['id']) { echo "class='active'"; } ?>> <?php echo $this->Html->link($v['Category']['name'].' ('.$v['Category']['post_count'].')',$v['Category']['link']); ?>
<?php foreach($v['children'] as $kk => $vv): ?> - <?php echo $this->Html->link($vv['Category']['name'].' ('.$vv['Category']['post_count'].')',$vv['Category']['link'],array('escape' => false)); ?>
<?php foreach($vv['children'] as $kkk => $vvv): ?> - <?php echo $this->Html->link($vvv['Category']['name'].' ('.$vvv['Category']['post_count'].')',$vvv['Category']['link'],array('escape' => false)); ?>
<?php endforeach; ?>
<?php endforeach; ?>
<?php endforeach; ?>[/code] Si vous avez des suggestions pour l'optimiser, je suis tout ouvert ;) J'ai aussi un petit problème au niveau du counterCache. Au niveau de la BDD, tous ce passe bien, par contre au niveau de l'affichage, c'est moins bon... Voici un exemple : Web (1 article) |-- Google (2 articles) |-- Mobile (3 articles) Sport (2 articles) ** J'aimerai bien qu'au niveau du controller, il comptabilise dans la categorie parente, le nombre d'article de lui même et celle de ses "children". Donc que Web affiche 6 et non pas 2... Merci encore d'avance pour votre aide ;) Cordialement, Ilan

A mon avis après s'est à toi de calculer toi même avec les résultats de ta requête, je ne vois que sa, mais je ne maîtrise pas totalement le counterCache donc, peut être qu'il y a mieux.

Ilan
Auteur

J'ai bien compris mais j'ai du mal avec le foreach et le threaded. Voici ce que j'ai commencé à developper : [code]$categories_array = $this->Category->find('threaded', array( 'conditions' => array('Category.online' => 1), 'fields' => array('Category.id','Category.name','Category.slug', 'Category.online', 'Category.post_count', 'Category.parent_id') )); foreach($categories_array as $k => $v) { if ($v['children']!=null) { foreach($v['children'] as $kk => $vv) { $v['Category']['post_count'] = $v['Category']['post_count'] + $vv['Category']['post_count']; } } $categories_array[$k] = $v; }[/code] Donc le calcul se fait bien mais l'effet ARBRE n'est pas pris en compte. Enfaite, si j'ai une sous-sous-catégorie dans une sous-catégorie, ca ne va pas être pris en compte dans le calcul. Voici l'output : Web (TotalCount - 6) (PostCount - 1) |-- Google (PostCount - 2) |-- Mobile (PostCount - 3) |-- |-- iPhone (PostCount - 4) Sport (2) ** Normalement, le TotalCount de Web devrait être à 10... Aussi je devrais ajouter un TotalCount à Mobile mais j'y arrive pas du tout :/

Ilan
Auteur

Bon, j'ai encore avancé (et je commence à avoir très mal à la tête !!!)

Pour vous partager un peu ce que j'ai fais, j'ai crée une function recursive. Je ne sais pas si c'est la meilleur chose à faire mais voilà, ca fonctionne!

Voilà les functions dans le PostController :

function catlist() {  
            $categories_array = $this->Category->find('threaded', array(
                'conditions' => array('Category.online' => 1),
                'fields' => array('Category.id','Category.name','Category.slug', 'Category.online', 'Category.post_count', 'Category.parent_id')
            ));

            $categories_array = $this->catTraverseArray($categories_array);

            return $categories_array;
       }

       function catTraverseArray( $items, $level = -1 ) {

            $level++;

            foreach($items as $k => $v) {
                $v'Category']'total_count'] = $v'Category']'post_count'];

                if ( is_array( $v'children'] ) && !empty( $v'children'] ) ) {
                    foreach($v'children'] as $kk => $vv) {
                        if ($v'Category']'parent_id'] == null) {
                            $v'Category']'total_count'] = $v'Category']'total_count'] + $vv'Category']'post_count'];
                        } else {
                            $v'Category']'total_count'] = $v'Category']'total_count'] + $vv'Category']'post_count'];
                        }
                    }
                    $v'children'] = $this->catTraverseArray($v'children'], $level);

                    if ($v'Category']'parent_id'] == null) {
                        $v'Category']'total_count'] = $v'Category']'total_count'] + $v'Category']'post_count'];
                    }
                }

                $items$k] = $v;
            }

            return $items;
        }

Il me reste un dernier truc à régler avant de finaliser complétement mon système de blog, le routing!!!

Voilà comment il est fait :

//Index du Blog (Listes des Derniers Articles
Router::connect('/actualites', array('controller' => 'posts', 'action' => 'index'));
//Les catégories 
Router::connect('/:catslug', 
                    array('controller' => 'posts', 'action' => 'category'),
                    array('pass' => array('catslug'), 'catslug' => '[a-z0-9\-]+') 
                );
//Les articles
Router::connect('/:catslug/:slug-:id', 
                    array('controller' => 'posts', 'action' => 'show'),
                    array('pass' => array('id','slug'), 'id' => '[0-9]+', 'slug' => '[a-z0-9\-]+') 
                );

Tous fonctionne très bien sauf au niveau de la pagination. Quand je suis dans l'index du controller post et que je veux voir la deuxième page, je tombe sur l'adresse : /posts/index/page:2
Pareil quand je suis dans les catégories, je tombe sur /posts/category/web/page:2

Comment faire pour garder mon système de Routing et en ayant des liens du style
/actualites/page/2
pour la page index et pour les categories
/web/page/2

Merci d'avance pour votre précieuse aide !
Ilan

Bon courage pour la suite.

Ilan
Auteur

Merci à toi. ;)
Aurais-tu une petite idée pour mon problème de Routing ? :)

Je pense qu'il suffit que tu reprenne la même logique, avec ceci sa devrait fonctionner :

Router::connect('/:actualites/page/:page', 
                    array('controller' => 'posts', 'action' => 'catlist'),
                    array('pass' => array('page'), 'page' => '[0-9]+') 
                );

Je n'ai pas testé mais je pense que sa doit être bon.

Ilan
Auteur

Non, ça fonctionne pas :/
L'URL est bien formaté mais la pagination ne passe plus :/

alors je ne sais pas trop la désolé.