Module de commentaires [cakephp 3]

Par Flitflit, il y a 9 ans


Bonjour,

J'aimerai coder un module de commentaires pour un site, et le plus gros du boulot est fait, mais je bute sur plusieurs points :

En théorie, je pourrais faire un $this->comments->find()->contain(['Comments.Comments.Comments'])->all();
Quelque chose comme ça, mais je limite la récupération des données à 3 (dans mon exemple), alors que j'aimerai trouver un moyen de créer une requête réellement récursive.

Une idée ?

15 réponses

Lartak, il y a 9 ans

Bonsoir.

Je n'ai pas l'impression que le framework soit pensé pour faire ça, non seulement pour récupérer les données dans le controller, mais aussi pour gérer la suppression en cascade (si jamais un comm est supprimé par son auteur, il faut supprimer les réponses et réponses de réponses)

Bien sûr que si qu'il est tout à fait capable de faire ceci et même très facilement.Est-ce que tu utilises le Behavior Tree ?

Pour preuve :

Il est courant de vouloir stocker des données hiérarchisées dans une table de base de données. Des exemples de ce type de données pourrait être des catégories sans limite de sous-catégories, les données liées à un système de menu multi-niveau ou une représentation littérale de la hiérarchie

Source : TreeBehavior

Flitflit, il y a 9 ans

woaw, merci, et pourtant j'ai parcouru la doc en long en large et en travers...

Flitflit, il y a 9 ans

ça a l'air parfait mais j'ai ce message d'erreur dans ma console:
Could not find package Kareylo/CakePHP-Comments at any version matching your PHP version 5.5.12.0

pourtant ta doc indique du 5.4 minimum

suis-je bête ?

Kareylo, il y a 9 ans

Je dois penser à changer le README. Les dernières versions de cake demandent la 5.6 minimum. Au pire, inspire toi du code pour faire ton propre module.

Flitflit, il y a 9 ans

Oui merci, c'est ce que je suis en train de faire. J'ai épluché ton code c'est tellement bien fait que j'ai foutu en l'air tout ce que j'avais fait pour repartir de zero avec le tiens.
Du coup j'ai une question : le findComments du behavior fonctionne niquel mais il retourne tous les résultats, as tu une idée de comment on peut greffer paginator dessus ? soit pour faire un systeme de chargement en ajax "afficher plus de comm" soit pour l'utiliser sur une page de forum par exemple, avec une limite de 20 réponses principales par page.
Je pense trouver tout seul, mais vu comment tu as l'air de gérer le framework, j'aimerai bien voir ta solution pour ça, ne serait-ce que pour améliorer ton propre plugin.

Kareylo, il y a 9 ans

Je pense que j'utiliserais le finder personnalisé dans les options de paginate.

public $paginate = ['finder' => 'comments' ];

Après, je ne connais pas plus que ça le framework, le plugin vient d'une envie d'apprendre le framework via la création de plugins, ce qui permet de faire profiter la communauté.

Edit : je te redirige vers la doc de pagination : https://book.cakephp.org/3.0/fr/controllers/components/pagination.html

Flitflit, il y a 9 ans

ok, j'en profite pour te signaler une erreur (je crois) dans le commentableBehavior, tu as écris une option "dependant" mais c'est "dependent" avec un e.
j'ai aussi remarqué que le countercache fonctionne bien sur l'ajout d'une donnée, mais pas sur sa supression (après j'ai pas copier/coller tout ton code donc ça peut venir de moi)

Kareylo, il y a 9 ans

Hésite pas à mettre une issue sur le github, je pourrai voir ça en rentrant du boulot.
Mais pour le dependent, oui, possible que j'ai fait une petite erreur de frappe.

Flitflit, il y a 9 ans

j'essaye de créer d'autres finder dans le behavior, par exemple, récupérer seulement les 5 premiers commentaires, et tous les enfants imbriqués, j'ai une piste qui donne ça :

public function findFiveComments(Query $query, $options = []) { $data = $query->contain([ 'Comments' => function (Query $q) use ($options) { return $q->contain( ['Children'=> function (Query $q) use ($options) { return $q->find('threaded')->contain(['Users'=>['fields'=>['id','username']]]); }, 'Users'=>['fields'=>['id','username']]]) ->where(['parent_id IS NULL'])->order(['Comments.id'=>'asc'])->limit(5); } ]); return $data; }

Tout fonctionne sauf... le threaded dans les enfants, il récupère le premier niveau d'enfants, mais pas les enfants d'enfants....
( j'ai renommé le hasmany(ChildComments) en (Children) par soucis de simplicité, car le finder threaded renomme en children dans les résultats)
Une idée du problème ? J'imagine même pas pour faire un paginate...

Kareylo, il y a 9 ans

Tu cherches un poil loin :

public function findFiveComments(Query $query, $options = []) { return $query->contain([ 'Comments' => function (Query $q) use ($options) { return $q->find('threaded')->contain(['Users'=>['fields'=>['id','username']]]); } ])->limit(5); }
Flitflit, il y a 9 ans

haha merci de ta réponse, mais c'est le premier truc que j'ai essayé. Il ignore totalement le limit il n'apparait même pas dans le sqllog. Je crois que c'est impossible vu le fonctionnement de threaded, il a besoin de tout charger pour ensuite dispatcher les enfants par id...

Kareylo, il y a 9 ans

J'ai essayé et ça fonctionne...
Bon. Par contre, pour faire de la pagination comme ça, bonne chance...

J'ai ça comme code :

public function findComments(Query $query, $options = []) { return $query->contain(['Comments' => function (Query $q) use ($options) { return $q->find('threaded')->contain('Users')->limit(2); }]); }

Et ça comme requête SQL :

SELECT Comments.id AS `Comments__id`, Comments.content AS `Comments__content`, Comments.ref AS `Comments__ref`, Comments.ref_id AS `Comments__ref_id`, Comments.ip AS `Comments__ip`, Comments.parent_id AS `Comments__parent_id`, Comments.user_id AS `Comments__user_id`, Comments.created AS `Comments__created`, Comments.modified AS `Comments__modified`, Users.id AS `Users__id`, Users.username AS `Users__username`, Users.password AS `Users__password`, Users.email AS `Users__email`, Users.role AS `Users__role`, Users.posts_count AS `Users__posts_count`, Users.created AS `Users__created`, Users.modified AS `Users__modified` FROM comments Comments LEFT JOIN users Users ON Users.id = (Comments.user_id) WHERE ( Comments.ref = 'Posts' AND Comments.ref_id in (1) ) LIMIT 2

Je suis pas certain que c'est le résultat que tu veux, par contre

Flitflit, il y a 9 ans

bizarre... j'essaye un milliard de combinaison j'ai jamais quelque chose de convenable... je trouverai ;)

Arbi, il y a 6 ans

@Kareylo le plugin est bien fait mais il manque la suppression