Bonjour à tous, je développe actuellement un site web utilisant le framework Cakephp. J'ai créé un système de catégories multiples pour les articles grâce à la relation hasAndBelongsToMany, mais un problème persiste.

Je souhaiterais créer une fonction category($slug) affichant les articles appartenant à la catégorie choisie (récupérée grâce au slug).

function category($slug){
        $cat = $this->Post->Category->find('first',array(
            'conditions' => array('slug' => $slug)
        ));
        $this->loadModel('CategoriesPost');
        $catpost = $this->CategoriesPost->find('all',array(
            'conditions' => array('category_id' => $cat'Category']'id'])
        ));
        foreach ($catpost as $c){
            $this->Post->create();
            $d'posts'] = $this->Post->find('all',array(
                'conditions' => array('id' => $c'CategoriesPost']'post_id'])
            ));
            debug($d);
        }
        $this->set($d);
        $this->render('index');
    }

Lorsque je fais un debug de $d, je récupère bien les bons articles, mais lorsque je fais le foreach dans ma vue, je n'en récupère qu'un seul..

<?php foreach ($posts as $post): ?>
    <div style="overflow:hidden;">
    <div id="post">
        <img src="/img/bookmark.png" alt="" class="bookmark">
            <div class="title">
                <h2>
                    <a href="<?php echo $this->Html->url($post'Post']'link']); ?>"><span><?php echo $post'Post']'name']; ?></span></a>
                </h2>
            <div id="meta"><span class="date">Écrit le <?php echo $this->Date->french($post'Post']'created']); ?></span> <span class="author">Par <a href="/profil/<?php echo $post'User']'username']; ?>"><?php echo $post'User']'username']; ?></a></span></div>
            <a href="<?php echo $this->Html->url($post'Post']'link']); ?>#comments"><div class="comment"><span>COMMENTAIRES</span></div></a>
          </div>
        <div class="content">
            <img src="<?php echo $post'Post']'img']; ?>" alt="<?php echo $post'Post']'name']; ?>" class="img" />

            <?php echo $this->Text->truncate($post'Post']'content'],250,array('exact'=>false,'html'=>true)); ?>
            <a href="<?php echo $this->Html->url($post'Post']'link']); ?>"><div class="readmore"></div></a>
        </div>
    </div>
</div>
    <div class="clear"></div>
<?php endforeach ?>

Je cherche une solution à ce problème depuis ce matin, si vous pourriez m'aider, je vous en serait très reconnaissant. Je continu les recherches de mon côté, en attente d'une réponse ;)

11 réponses


justclara42
Réponse acceptée

salut, ok, alors le soucis dois venir de ta boucle foreach dans ta fonction.

test:
dans tes deux model Post et CategoriesPost, tu as bien ceci? si non ajoute le.

public $actsAs = array('Containable');

ensuite dans ton Post contrôler utilise cette fonction:

function category($slug){
        $this->loadModel('CategoriesPost');
        $this->CategoriesPost->recursive = 0; 
        $this->Post->contain('CategoriesPost','Category');
        $this->CategoriesPost->contain('Category','Post'); 
                $cats = $this->Paginate('CategoriesPost',array(
            'Category.slug'=>$slug
        ));
        $post_ids = Set::Combine($cats,'{n}.CategoriesPost.post_id','{n}.CategoriesPost.post_id');
        $d'posts'] = $this->Post->find('all',array(
            'conditions' => array('Post.id'=>$post_ids)
        ));
        $this->set($d);
        $this->render('index'); 
    }

et met un debug de $d ;)

EDIT:
en fait j'avais pas calculé, mais c'est le meme principe que pour les Tags dur mon blog.

si c'est bien ça, je peux te passer les code de mes 3 controller, et 3 modela.

Mon Blog

Essais avec ca :

function category($slug){

    $cat = $this->Post->Category->find('first',array(
        'conditions' => array('slug' => $slug)
    ));
    $this->loadModel('CategoriesPost');
    $catpost = $this->CategoriesPost->find('all',array(
        'conditions' => array('category_id' => $cat'Category']'id'])
    ));
    $d = array();
    foreach ($catpost as $c){
        $this->Post->create();
        $d'posts']] = $this->Post->find('all',array(
            'conditions' => array('id' => $c'CategoriesPost']'post_id'])
        ));
        //debug($d);
    }
    $this->set($d);
    $this->render('index');
}
Mtd
Auteur

Merci pour ta réponse zkiller. Mais ça ne fonctionne pas.

Mtd
Auteur

Pas d'idées?

salut, tu veux récupérer tous le posts d'une catégorie, via le slug de la catégorie, mais sans passer l'id de la catégorie c'est bien ça?

je comprend pas par contre pourquoi du passe de ta table category, a CategoriesPost, pour finir par Posts?

tu peux pas récupérer directement ton id de catégorie dans Post?

Désolé, j'essais de comprendre les fonctionnement de tes différentes table la ;)

Mtd
Auteur

Je ne peux pas récupérer l'id de la catégorie dans Post car un post peut avoir plusieurs catégories. J'ai une table posts, un table categories et une table de liaison.

La raison pour laquelle je récupère la table Category, est que par un soucis de facilité pour les visiteurs, j'utilise le slug et non l'id pour accéder à la page (/blog/lacategorie au lieu de /blog/lacateogie-124).

CategoriesPost étant la table de liaison, composée des colonnes "post_id ; category_id", j'aimerais pouvoir afficher tous les posts qui ont pour catégorie, la catégorie appelé par l'utilisateur.

Si tu fais toutes les jointures de hasmany, belongsto et HABTM, tu as juste à faire une recherche sur la catégorie et faire une recursive à 2 ou 3 suivant les infos que tu veux.

Du coup tu as même pas besoin de loadmodel si tu as toutes tes relations.

test ceci alors:

function category($slug){

    $cat_id = $this->Post->Category->find('first',array(
        'fields' => 'id',
        'conditions' => array('slug' => $slug)
    ));
    $this->set($cat_id);
    $this->loadModel('CategoriesPost');
    $catpost = $this->CategoriesPost->find('all',array(
        'fields' => 'post_id',
        'conditions' => array('category_id' => $cat_id)
    ));
    $this->set($catpost);
    $d = array();
    foreach ($catpost as $c){
        $this->Post->create();
        $d'posts'] = $this->Post->find('all',array(
            'conditions' => array('id' => $c)
        ));
    }
    $this->set($d);
    $this->render('index');
}

en récupérent uniquement les id, et non toute les données d'un champ, tu évite des soucis comme avec ton:

$c'CategoriesPost']'post_id']

et active les donnée avec

$this->set($cat_id);

j'avais déjà eu des soucis a se niveau.

tiens au courant si ça marche, et si non, poste les debug de $cat_id, $catpost, $d

Mtd
Auteur

J'ai testé ton code mais cela reviens au même. Par contre $cat_id renvoi un tableau et non l'id directement, je suis donc obligé de mettre $cat_id'Category']'id'].

Quand je debug $d, j'ai bien mes deux articles correspondant à la bonne catégorie.

/app/Controller/PostsController.php (line 159)
array(
    'posts' => array(
        (int) 0 => array(
            'Post' => array(
                'id' => '13',
                'name' => 'Le titre',
                'slug' => 'le-slug',
                'content' => 'contenu',
                'type' => 'post',
                'created' => '2013-03-11 09:39:00',
                'online' => '1',
                'difficulty' => false,
                'user_id' => '7',
                'featured' => false,
                'img' => '',
                'thematic' => '',
                'comment_count' => '1',
            )
        )
    )
)
/app/Controller/PostsController.php (line 159)
array(
    'posts' => array(
        (int) 0 => array(
            'Post' => array(
                'id' => '14',
                'name' => 'Le titre',
                'slug' => 'le-slug-2',
                'content' => 'contenu',
                'type' => 'post',
                'created' => '2013-03-14 10:05:00',
                'online' => '1',
                'difficulty' => false,
                'user_id' => '7',
                'featured' => false,
                'img' => '',
                'thematic' => '',
                'comment_count' => '0',
            )
        )
    )
)

Le problème est qu'il ne m'affiche pas les deux résultat dans un seul tableau. Il me sépare les deux résultats, ce qui explique que si je fais un foreach de $posts, il ne m'affiche que le premier.

Mtd
Auteur

Excellent! Ça fonctionne parfaitement! J'ignorais l'existence de la fonction Combine.

Merci pour ton aide justclara42 ;)

de rien Mtd, je l'avais oublié aussi lol
on cherchais compliqué alors qu'il y avais plus simple ;)

Bonne continuation ;)