Bonjour amis de Grafikart :)

J'essaye de faire un blog.
Mon problème c'est que je n'arrive pas a lier des membres aux commentaires, je m'explique :

J'en suis à la partie ou quand je clic sur un article de mob blog, ça dirige vers une page où l'on peut lire l'article en entier.

Dans cette page représenté par ma fonction voir() dans mon PostsController, je voudrais donc lier trois tables qui sont les suivantes :

1 table users
1 table posts
1 tables comments

Pour que je puisse afficher dans ma vue voir.ctp

le pseudo de l'utilisateur lié au post affiché, les commentaires lié au post et pour finir, <u><strong>les users lié aux commentaires</strong></u>.

J'ai crée ces trois models

<?php
class Post extends AppModel{
    public $belongsTo = array('Category', 'User');
    public $hasMany = 'Comment';
}
?>

<?php
class Comment extends AppModel{
    public $belongsTo = array('Post', 'User');

}
?>

<?php
class User extends AppModel{
    public $hasMany = array('Comment', 'Post');
}
?>

Je pense pas m'etre trompé de ce coté là

Ensuite dans mon post controller j'ai écrit ça pour la fonction voir

<?php
function voir($id){
            $this->layout = 'default';
            $b = $this->Post->find('first', array('conditions' => array('Post.id' => $id)
            ));
            $d = $this->Post->Comment->User->find('all', array('conditions' => array('User.id' => 'Comment.user_id')
            )); //cette instruction je l'ai rajouté pour vous montrer ce que je tente de faire mais ça ne change rien que 
                            //je la mette ou non.
            $this->set('article', $b, $d);
        }?>

Voila pour finir quand je fais un débug voilà ce qui va s'afficher, quasiment tout sauf les users lié aux commentaires c'est ca mon probleme

Array
(
    [Post] => Array
        (
            [id] => 21
            [titre] => Helper Mark it up
            [contenu] => Ici le contenu de mon article.

            [created] => 2011-12-14 18:24:01
            [category_id] => 1
            [user_id] => 21
        )
    [Category] => Array
        (
            [id] => 1
            [titre] => Javascript
        )
    [User] => Array
        (
            [id] => 21
            [username] => tapesec
            [mail] => ******** @gmail.com
            [password] => 6450618408daa4c956a2a18abc0d1720838f9341
            [created] => 2012-01-05 07:16:13
            [lastlogin] => 2012-01-14 08:14:42
            [active] => 1
        )
    [Comment] => Array
        (
            [0] => Array
                (
                    [id] => 3
                    [post_id] => 21
                    [user_id] => 21
                    [contenu] => Voici un premier commentaire
                    [created] => 2012-01-12 00:00:00
                )
                  //j'aurai aimé afficher l'user auteur du commentaire 
            [1] => Array
                (
                    [id] => 4
                    [post_id] => 21
                    [user_id] => 22
                    [contenu] => voici un seconde commentaire 
                    [created] => 2012-01-12 00:00:00
                )
                //ici pareil
        )
)

26 réponses


Salut,

Essaye avec un recursive à 2.

tapesec
Auteur

J'ai du mal à comprendre a quoi sert et comment fonctionne recursive

tapesec
Auteur

Je ne sais pas où mettre le recursive partout où j'essaye ça donne des erreurs

Le récursive se mets comme ça :

$b = $this->Post->find('first', array(
        'conditions' => array('Post.id' => $id),
        'recursive' => 2
    ));

En gros c'est un niveau de profondeur.

A+

tapesec
Auteur

ça ne fonctionne pas ca marque SQLSTATE[42S22]: Column not found: 1054 Unknown column 'User.user_id' in 'field list'
je comprends pas

Essaye de mettre : posts.id pour le premier
Et : comments.id et users.id pour l'autre.

tapesec
Auteur

Non du tout ca marche pas puis comme je te dit la seconde ligne ne sert a rien ca fonctionne pas comme ca apparemment mais merci quand même de l'aide :)

Bon on abandonne le recursive, on va utiliser le comportement Containable :

On change Post :

<?php 
class Post extends AppModel{

    public $actsAs = array('Containable');
    public $belongsTo = array('Category', 'User');
    public $hasMany = 'Comment';

}
?>

Puis dans le find on fait:

$b = $this->Post->find('first', array(
        'conditions' => array('Post.id' => $id),
        'contain' => array(
            'Comment' => array('User')
        )
    ));

A+

Alors moi je simplifierais.
D'un côté un find sur Post pour récupérer l'article (recursive 0 pour avoir l'utilisateur lié)
Un autre find sur Comment avec la condition sur post_id et (recursive 0 pour avoir l'utilisateur lié)

tapesec
Auteur

Ca donnerai quoi ?

<?php
function voir($id){
            $this->layout = 'default';
            $b = $this->Post->find('first', array('conditions' => array('Post.id' => $id), 'recursive' => 0));
            $c = $this->Post->Comment->find('all', array('conditions' => array('Comment.post_id' => $id), 'recursive' => 0)); 
            $this->set('article', $b, $c);
        }
?>

SI c'est ca cela ne fonctionne pas mais je me doute que j'ai faux

tapesec
Auteur

Avec le comportement containable de extrarox ca me sort rien, enfin le même contenu que mon premier message sans les users de mes commentaires.
Franchement je me demande si j'ai bien fait ma base de donnée.

Dans ma table comment j'ai un champ post_id et un champ user_id j'ai bien fait non ?

Oui c'est bon, mais ta table c'est comment ou comments? Parce que c'est comments.

tapesec
Auteur

comments

Ta requête s'affiche quand tu exécutes la page via la fonctionnalité de cake? Si oui, ça affiche quoi?

tapesec
Auteur

J'ai donc cette fonction dans PostsController

function voir($id){
            $this->layout = 'default';
            $b = $this->Post->find('first', array('conditions' => array('Post.id' => $id), 'contain' => array('Comment' => array('User')
            )
            )); 
            $this->set('article', $b);
        }

Et quand je fais dans voir.ctp

echo debug($article);

ça m'affiche ceci :

Array
(
    [Post] => Array
        (
            [id] => 21
            [titre] => Helper Mark it up
            [contenu] => Amis du FriendBlog bonsoir,
  Ce soir je vais vous parler d'un helper pour integrer le célèbre plugin Jquery nommé "Mark it up".

            [created] => 2011-12-14 18:24:01
            [category_id] => 1
            [user_id] => 21
        )
    [Category] => Array
        (
            [id] => 1
            [titre] => Javascript
        )
    [User] => Array
        (
            [id] => 21
            [username] => tapesec
            [mail] => lionel.dupouy@gmail.com
            [password] => 6450618408daa4c956a2a18abc0d1720838f9341
            [created] => 2012-01-05 07:16:13
            [lastlogin] => 2012-01-14 08:14:42
            [active] => 1
        )
    [Comment] => Array
        (
            [0] => Array
                (
                    [id] => 3
                    [post_id] => 21
                    [user_id] => 21
                    [contenu] => Do your layouts deserve better than Lorem Ipsum? Apply as an art director and team 
                    [created] => 2012-01-12 00:00:00
                )
            [1] => Array
                (
                    [id] => 4
                    [post_id] => 21
                    [user_id] => 22
                    [contenu] => turpis. Curabitur id nibh mi, eu consectetur lacus. 
                    [created] => 2012-01-12 00:00:00
                )
        )
)

Ce que tu me montres n'a pas pris en compte le containable, tu as bien mis le actsAs dans ta class Post?

tapesec
Auteur

oui monsieur

<?php
class Post extends AppModel{
    public $actAs = array('Containable');
    public $belongsTo = array('Category', 'User');
    public $hasMany = 'Comment';
}
?>

C'est actsAs, il y a un "s"^^

tapesec
Auteur

oh punaise ça marche ce boulet ! merci infiniment ^^ tu es trop fort !

tapesec
Auteur

Attends mince du coup j'ai plus ma table category ...

EDIT : Ah c'est bon j'ai réussi à la rajouter dans la fonction (ca commence à rentrer).

Par contre j'aurai été curieux de savoir comment marche la maniere "plus simple" de grafikart, est ce que le comportement containable ne ralentit pas l'application inutilement ?

non , enfin pour ma part je trouve cela bien plus optimisé, tu devrais spécifier les champs que tu veux pour optimiser au mieux la recherche
du genre :

$data = current($this->Operation->find('all',array(
            'conditions' => array(
                'Operation.nb' => $nb,
                'Operation.user_id' => $this->Auth->user('id'),
                'Operation.compte_nb'   => $co
                ),
            'contain' => array(
                'Compte' => array(
                    'conditions' => array(
                        'Compte.nb' => $co,
                        'Compte.user_id' => $this->Auth->user('id')),
                    'fields' => array('Compte.slug','Compte.nb','Compte.name')
                    ),
                'Category' => array(
                    'conditions' => array(
                        'Category.user_id' => $this->Auth->user('id'))  
                        )
                )   
            )
        )
        );

Tu choisis directement les champs nécessaires

tapesec
Auteur

Merci pour ces précisions.

Je me heurte maintenant a un autre probleme c'est celui de la validation des données de mon formulaire commentaire.

J'ai un seul champ c'est le contenu, vu que seul un membre connecté peut écrire un commentaire et que j'ai pas mis de titre à ce commentaire.

J'ai fait ça dans mon modele commentaire :

<?php
class Comment extends AppModel{
    public $belongsTo = array('Post', 'User');

    /* public $validate = array(
        'contenu' => array(
            'alphaNumeric' => array(
                'rule' => 'alphaNumeric',
                'allowEmpty' => false,
                'required' => true,
                'message' => 'Que des caractères alphanumérique'
            ),
            'length' => array(
                'rule' => array('minLength', '3'),
                'message' => 'Minimum 3 caractères'
            )
        )
    );
}
?>

et dans mon controller :

<?php
function voir($id){
    if(!empty($this->request->data)){
    if($this->Post->Comment->validates()){
        $this->Post->Comment->save($this->request->data);
            $this->Session->setFlash("Votre commentaire a bien été enregistré !", "notif"); 
    }else{
        $this->Post->Comment->validationErrors();
    }
    }   
    $this->layout = 'default';
    $b = $this->Post->find('first', array('conditions' => array('Post.id' => $id), 'contain' => array('Comment' => array('User'), 'Category'
    )
    )); 
    $this->set('article', $b);

    }?>

Ca me fait un erreur de syntaxe dans ma base de données un truc un peu abominable, je me demande si ca vient pas du fait que je travaille sur une fonction voir qui traite le modele Comment dans le controller Post. Ca m'embrouille grave je suis pas encore suffisament à l'aise avec cakePhP pour m'en sortir. Tu aurais un indice ? ;)

J'abuse un peu de ta gentillesse .

tu peux poster l'erreur sql ?

tapesec
Auteur

Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'validationErrors' at line 1.

La voici, étrange non ?

tu peux avoir la requette en cliquant sur l'erreur non ?

tapesec
Auteur

Salut xcid je rentre du travail désolé de pas avoir répondu plutôt.

Non je ne peux pas cliquer dessus.
Je vais recreer un post pour reposer ma question au propre ca sera peut être mieux :)