Salut à tous,
je rencontre actuellement un petit problème sur les relations HABTM.
J'ai mis en place sur mon blog le plugin Taxonomy pour la gestion de tag et j'aimerais lister tous mes posts qui possèdent un tag précis.
J'ai donc créé une fonction qui permet cela mais je n'arrive pas à filtrer les enregistrements...
Voici la structure des mes tables :
Table term :

  • id
  • name
  • slug
  • type

Table term_relationships :

  • id
  • ref -> stocke le nom du model
  • ref_id -> stock l'id de l'enregistrement (post,...) lié au model stocké dans "ref"
  • term_id

    Voici la liaison HABTM présente dans le TaxonomyBehavior.php :

    public function setup(Model $model, $options = array()){
        $model->hasAndBelongsToMany['Term'] = array(
            'className' => 'Taxonomy.Term', 
            'associationForeignKey' => 'term_id',
            'with' => 'Taxonomy.TermR', 
            'foreignKey' => 'ref_id',
            'joinTable' => 'term_relationships',
            'conditions' => 'ref = "'.$model->name.'"'
        );
        $this->settings = array_merge($this->_defaults, $options);
    }

    et la fonction dans mon controller Posts qui permet de lister les articles en fonction des tags :

    public function listTags($slug){
    // Permet de récuperer le tag correspondant au slug
        $tag = $this->Post->Term->find('first', array(
            'conditions' => array('slug' => $slug)
        ));
        if(empty($tag))
            throw new NotFoundException('Aucun mot clé ne correspond à ce nom');
        // Une "solution" que j'ai vu sur internet et qui semble fonctionner à moitié
        $this->paginate = array(
            'conditions' => array('Terms.term_id' => $tag['Term']['id'], 'Post.online' => 1),
            'joins' => array(
                array(
                    'alias' => 'Terms',
                    'table' => 'term_relationships',
                    'type' => 'INNER',
                    'conditions' => 'Post.id = Terms.ref_id'
                )
            ),
            'limit' => 10,
            'order' => 'Post.created DESC'
        );
        $posts = $this->Paginate('Post');
    
        $this->set('posts', $posts);
        $this->render('index');
    }

    Cette methode me renvoie l'ensemble des articles alors que je souhaiterais n'avoir que les articles qui contiennent uniquement le tag sélectionné...
    Avez-vous une meilleure solution à me proposer ? J'avoue que je commence à être pommé au niveau de cette requête...

1 réponse


Romano83
Auteur
Réponse acceptée

Une fois de plus, je m'autorépond ^^
En fait, c'était tout simple mais il suffisait d'attaquer directement les modèles liés et faire quelques requêtes pour trouver plus facilement les articles...
Au cas où, voici la fonction si une personne se retrouve avec le même problème :

    public function listTags($slug){
        $tag = $this->Post->Term->find('first', array(
            'conditions' => array('slug' => $slug)
        ));
        if(empty($tag))
            throw new NotFoundException('Aucun mot clé ne correspond à ce nom');
        $listPosts = $this->Post->TermR->find('all', array(
            'conditions' => array('term_id' => $tag['Term']['id'], 'ref' => 'Post')
        ));
        $posts_id = Set::Combine($listPosts, '{n}.TermR.ref_id', '{n}.TermR.ref_id');
        $posts = $this->Paginate('Post', array('Post.online' => 1, 'Post.id' => $posts_id));        
        $this->set('posts', $posts);
        $this->render('index');
    }