Bonjour, voici mon soucis :
Je veux pouvoir ajouter ou modifier des articles qui ont un ou plusieurs tags. Tout fonctionne à merveille jusqu'à se que je m'occupe des tags.
Je les récupère bien de la BDD pour pouvoir les sélectionnés sous forme de checkbox.

<?= $this->Form->select('tags_id', $options, array('multiple' => 'checkbox')); ?>

Or quand j'envois l'update ou l'ajout d'un article rien ne s’effectue au niveau des tags

voici le code de mon controller

public function admin_index() {
        $this->loadModel('Blog', 'Category', 'Author', 'Tag');
        $posts = $this->paginate('Blog');
        $this->set(compact('posts'));
    }
    public function admin_addposts($id = null){
        if(!empty($this->request->data)){
            $this->loadModel('Blog', 'Category', 'Author', 'Tag');
            $this->Blog->save($this->request->data);
            $this->Session->setFlash("L'article a bien été ajouter", 'flash', array('class' => 'success'));
            return $this->redirect(array('action' => 'index'));
        }else if ($id) {
            $this->loadModel('Blog', 'Category', 'Author', 'Tag');
            $posts = $this->paginate('Blog');
            $categories = $this->Blog->Category->find('list');
            $tags = $this->Blog->Tag->find('list');
            $authors = $this->Blog->Author->find('list');
            $this->set(compact('posts','categories', 'authors', 'tags'));
            $this->request->data = $this->Blog->findById($id);

        }
    }

Cordialement,

Xander

20 réponses


Bonsoir.
C'est normal, depuis ton controller tu envoies la liste sous la variable $tags, alors que dans ta vue tu mets la variable $options.
Il te faut mettre :

<?= $this->Form->select('tags_id', array('options' => $tags, 'multiple' => 'checkbox')); ?>
xander
Auteur

oui mais je déclaré dans le formulaire que <?php $options = $tags;?> , j'avais oublier de le mentionné, parce que j'avais suivis la doc
quand je test ta méthode je ne récupère plus les tags sous forme de checkbox mais plutôt un select vide

Edit: au faite autan me corrigé aussi : voici ce que j'ai mis en enlevant $options

<?= $this->Form->select('tags_id', $tags, array('multiple' => 'checkbox')); ?>

qui fonctionne aussi lors de la récupération mais lors de la save sa n'update pas les tags

Sauf que tu le met en dehors du array() des options du champ et si tu ne nous met que le champ du input sans cette information, on ne peut pas deviner.
Dans tous les cas, ça devrait fonctionner comme je te l'ai mis.
Même si tu défini une variable $options comme tu l'as fait, ça ne peut pas fonctionner comme tu l'as mis, il t'aurait fallu mettre ceci :

<?php $options = $tags; ?>
<?= $this->Form->select('tags_id', array('options'=>$options, 'multiple' => 'checkbox')); ?>

Qui est une perte de temps.
Tu ne crois pas ?

Si tes modèles tag et blog n'ont pas de relations définies dans tes modèles, c'est normal.

xander
Auteur

Ils sont liée voici leur relation :
Model Tag :

<?php
class Tag extends AppModel{
    public $hasAndBelongsToMany = array('Blog');
}
?>

et TagR

<?php
class TagR extends AppModel{
    public $useTable = 'posts_tags';
    public $belongsTo = array('Blog', 'Tag');
}
?>

et Blog

<?php
class Blog extends AppModel{
    public $useTable = 'posts'; // me permet d'utilisé la table posts pour mes article
    public $actsAs = array('Containable', 'Slug');
    // création de l'url des posts (lire la suite)
    public function afterFind($results, $primary = false){
        foreach($results as $k => $result){
            if(
                isset($result'Blog']'id']) &&
                isset($result'Blog']'slug'])
            ){
                $results$k]'Blog']'url'] = array(
                    'controller' => 'blog',
                    'action' => 'view',
                    'id' => $result'Blog']'id'],
                    'slug' => $result'Blog']'slug']
                );
            }
        }
        return $results;
    }
    //function qui servira a faire les associations (ici belongsTo relation de type 1:N et hasMany relation de type N:1)
    public $belongsTo = array(
        'Author',
        'Category' => array(
            'counterCache' => true // counterCache me permet de compté combien d'article par categories
        )
    );
    // function qui servira a faire l'associastion entre les tags et les articles (ici relation de type N:N conc j'utilise le hasAndBelongsToMany)
    public $hasAndBelongsToMany = array('Tag');
    public $hasMany = array('TagR');
}
?>

Si tu as fait toutes les relations nécessaires, pourquoi fais-tu des loadModel sur ton controller ?

xander
Auteur

car je suis dans le controller UsersController du coup pour récupéré mes données je fait un loadModel es ce une erreur ?

xander
Auteur

petit up svp je n'arrive toujours pas à update les tags d'un post

Regarde la du coté de saveAll cela pourrait t aider je penses :
http://book.cakephp.org/2.0/fr/models/saving-your-data.html#sauvegarder-les-donnees-de-model-lie-habtm-hasandbelongstomany

"car je suis dans le controller UsersController du coup pour récupéré mes données je fait un loadModel es ce une erreur ?" <<==
Tout dépend si dans ton model User tu as fais des associations avec les models en question. Si c est le cas pas besoin de faire un loadModel en faisant $this->User->Blog par exemple tu recupere les données normalement.

xander
Auteur

Merci je vais voir cela après avoir mis de l'ordre dans mes controllers et models, j'ai remarqué que je fesais beaucoup de requêtes inutiles, saveAll m'a l'air d'être une bonne solution je te tien au courant ^^

xander
Auteur

Alors me re voila ^^ donc toujours le même souci je récupère bien toute les infos que je veut lors de l'édition / ajout d'un article hormis lorsque sa concerne les tags =_= ces fameux tags qui me tourmente.

Voici mon code auxquelles j'ai apporté quelque correction et amélioration de performance finis les requêtes inutiles (enfin j'espère que c'est propre) ^^

BlogController.php

// page index des posts me permettra de listé les articles dans un array et de décidé lequel supprimé modifier ou voir ajouté un nouvel article
    public function xander_posts(){
        $posts = $this->Blog->find('all', array('contain' => array('Category', 'Tag', 'Author'), 'order' => array('created' => 'desc')));
        $this->set(compact('posts'));
    }
    // function add et edit des posts me sert a éditer ou ajouter des articles
    public function xander_addeditposts($id = null){
        // ici je récupére l'id de l'article voulus
        if($id){
            $postsid = $this->Blog->find('first', array(
                'conditions' => array('Blog.id' => $id)
            ));
            if(empty($postsid)){
                $this->Session->setFlash("Impossible d'editer cet article", 'flash', array('class' => 'info'));
                return $this->redirect(array('action' => 'posts')); 
            }
        }
        // Des données ont été postées
        if(!empty($this->request->data)){
            $this->request->data'Blog']'id'] = null;
            if(isset($postsid)){
                $this->request->data'Blog']'id'] = $postsid'Blog']'id'];
            }
            if($this->Blog->saveAll($this->request->data)){
                $this->Session->setFlash("L'article a bien été ajouter/modifier", 'flash', array('class' => 'success'));
                return $this->redirect(array('action' => 'posts'));
            }
        }else if($id){
            $this->request->data = $postsid;
        }
            $posts = $this->Blog->find('all', array('conditions' => array('Blog.id' => $id), 'recursive' => 1));
            $categories = $this->Blog->Category->find('list');
            $tags = $this->Blog->Tag->find('list');
            $authors = $this->Blog->Author->find('list');
            $this->set(compact('posts', 'categories', 'tags', 'authors'));
            }

Mon debug($posts); die(); qui me comfirme que je récupère toute les infos liés à l'article que je demande

Mon Model Blog.php

<?php
class Blog extends AppModel{
    public $useTable = 'posts'; // me permet d'utilisé la table posts pour mes article
    public $actsAs = array('Containable', 'Slug');
    // création de l'url des posts (lire la suite)
    public function afterFind($results, $primary = false){
        foreach($results as $k => $result){
            if(
                isset($result'Blog']'id']) &&
                isset($result'Blog']'slug'])
            ){
                $results$k]'Blog']'url'] = array(
                    'controller' => 'blog',
                    'action' => 'view',
                    $result'Blog']'id']
                );
            }
        }
        return $results;
    }
    //function qui servira a faire les associations (ici belongsTo relation de type 1:N et hasMany relation de type N:1)
    public $belongsTo = array(
        'Author',
        'Category' => array(
            'counterCache' => true // counterCache me permet de compté combien d'article par categories
        )
    );
    // function qui servira a faire l'associastion entre les tags et les articles (ici relation de type N:N conc j'utilise le hasAndBelongsToMany)
    public $hasAndBelongsToMany = array('Tag');
    public $hasMany = array('TagR');
}
?>

Ma fonction addeditposts.ctp + screen de se que sa me retourne

<section class="add">
    <?= $this->Form->create('Blog'); ?>
        <?= $this->Form->input('id'); ?>
        <?= $this->Form->input('title', array('label' => 'Titre de l\'article')); ?><br>
        <?= $this->Form->input('category_id', array('label' => 'Category')); ?><br>
        <?= $this->Form->input('img', array('label' => 'Image')); ?><br>
        <p>Image actuel : <br>
                        <?php 
                        // je vérifie si un id existe en fesant un get de l'url si oui j'affiche l'image concerné par l'id sinon je n'affiche rien
                            if(isset($this->request->data'Blog']'id'])){                            
                                echo '<img class="imgpostsmin" src='.$this->request->data'Blog']'img'].' alt="" >';
                            }else{
                                echo 'aucune image';
                                }

                        ?>
        </p>
        <br>
        <?= $this->Form->input('content', array('label' => 'Content')); ?><br>
        <?= $this->Form->input('slug', array('label' => 'Slug')); ?><br>
        <?= $this->Form->select('tag_id', $tags, array('multiple' => 'checkbox')); ?><br>
        <?= $this->Form->input('author_id', array('label' => 'Author')); ?><br>
        <?= $this->Form->checkbox('onoff', array('label' => 'Online or Offline')); ?><br>
    <?= $this->Form->end('Ajouter'); ?><br>
</section>

Voila merci pour votre aide d'avance

Bonjour.
Ce n'est pas étonnant.
Pour commencer, tu défini ton input en select puis tu fais de ton listing de données des checkbox.
Il faut que tu connaisses la différence entre le selects et les checkbox.
Dans ton cas il faut plutôt un muti-select, vu que tu veux pouvoir joindre des données à ton enregistrement.
Bref, je ne vais pas te faire un cours la dessus. :p
Ensuite, sans vouloir te vexer, ton code dans l'action de ton controller et un peu bordélique quand même.

xander
Auteur

Effectivement merci du rappel ^^ aussi tu ne me vexe pas je suis la pour apprendre ;) je vais voir se que donne un multi select et voir comment structuré encore mieux mon controller

C'est surtout que si un moment donné tu as un retour d'une vingtaine de tags, tu vas te retrouver avec un vingtaine de checkbox, ce qui sera loin d'être pratique comparé à un multi-select.
En checkbox ça peut aller si par exemple ce sont des catégories, tu en aura peut être 5 ou 6 au plus, alors que des tags tu peux en avoir des tonnes, alors je ne te racontes pas si tu te retrouves avec une 50 aine de checkbox pour les tags un moment donné. :)

xander
Auteur

effectivement ^^ par contre quand tu dis un multiple select c'est le fait de pouvoir sélectionné plusieurs valeur dans un select ? ? car je trouve pas les paramètres dans la documentation

As tu regardé ce tuto ?
Tutoriel CakePHP : Système de Tags, HasAndBelongsToMany

Tu trouveras sans doute ta réponse

EDIT:
Un plus:
Tutoriel CakePHP : Taxonomy

xander
Auteur

WOOOOOOOO Merci mikachu ! ca va surement m'aider à comprendre mieux comment gérer les tags

Il y a aussi un Plugin de Taxonomy fait pas Grafikart.

xander
Auteur

Merci les gas vous assurés ;)