Bonjour,

Le countercache c'est super. On aime ça. Mais je rencontre un problème qu'on peut tous avoir :

j'ai un module de commentaire permettant de commenter à peu près tout et n'importe quoi sur mon site. ex : commenter sur le blog, sur le forum, commenter un commentaire... etc
Pour faire les associations belongsTo, j'ai donc (dans ma table commentaire) créé un champs parent id qui prendra la clé étrangère du contenu commenté, et un champ type pour savoir si le commentaire concerne un parent de type forum, blog, etc...
dans mon model ça donne :

        $this->belongsTo('Forums', [
            'foreignKey' => 'parent_id',
            'joinType' => 'LEFT OUTER',
            'conditions'=>['type'=>'forum'],
        ]);

        $this->belongsTo('Blogs', [
            'foreignKey' => 'parent_id',
            'joinType' => 'LEFT OUTER',
            'conditions'=>['type'=>'blog'],
        ]);     

Aucun problème jusque la.
Les ennuis commencent avec le countercache. Pour enregister le nombre de commentaire dans la table parent associé je fais :

        $this->addBehavior('CounterCache', 
            ['Users' => ['comment_count'],
            'Blogs' => ['comment_count'=> ['conditions' => ['Comments.type' => 'blog']]],
            'Forums' => ['comment_count'=> ['conditions' => ['Comments.type' => 'forum']]],
            'Comments' => ['comment_count'=> ['conditions' => ['Comments.type' => 'comm']]]
            ...etc
            ]);

Le code fonctionne et le countercache est bien effectué. Le problème c'est qu'il exécute sa routine (le count suivi du update nécessaire au countercache) pour chaque parent défini dans le model :
Imaginez qu'un utilisateur laisse un commentaire sur un article du blog à l'ID n° 45, le framework va faire un count de commentaire avec le parent id 45 pour le type blog, suivi d'un update dans la table parent si nécessaire. Mais il va aussi le faire pour tous les autres types, ce que je ne souhaite pas.
Techniquement le code fonctionne, mais à chaque fois qu'on laisse un commentaire, il y a une insertion dans la BDD, suivi de 8 count et autant d'update... c'est lourd.

Une idée ?

4 réponses


faut fixer une condition pour ton count avec Scope pour dire à quel moment faire le count ou définir des callbacks qui vont s'affecctuer après un save ou un update

Flitflit
Auteur

dans la definition du behavior lui même ?
parce qu'il semble que le scope ai disparu dans cake3 dans les options de counterCache. Regarde le code je mets déjà une conditions dans chaque behavior pour qu'il fasse l'update correctement, mais mon problème n'est pas la.

Par contre j'ai essayé d'utiliser le callback comme ça :

            'Blogs' => [ 'comment_count' => function ($event, $entity, $table) {                
                if($entity->type != 'blog'){
                    return false;
                }
            }],
            ...etc

L'idée était sympa : si le type ne correspond pas, alors annule le counterCache, mais sans succès, le callback ne s'attend pas à un return false comme indiqué dans la doc en bas "Cette méthode retourne la valeur du compteur à stocker".

effectivement le counterScope n'existe plus sur cakephp3 mais tu peux créer des conditions like :

$this->addBehavior('CounterCache', [
    'Articles' => [
        'comment_count' => [
            'conditions' => ['Comments.spam' => false]
        ]
    ]
]);
Flitflit
Auteur

Oui, je sais, je le fais dans le code que j'ai présenté au début. Il me permet de faire le counterCache comme il faut ça marche bien oui oui merci mon problème n'est pas la :)