EntityListener qui fait la sourde oreille

L’auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonsoir !

Une fois n’est pas coutume, je viens vers vous pour un détail qui m’aurait échappé…

J’essaie de mettre en place un EntityListener pour automatiser des traitements par lots. J’ai une bibliothèque de partitions, et j’aimerais mettre en place de quoi gérer les prêts. Pour ça, il y a une entité Lending (pas trouvé de mot plus approprié) qui est en ManyToMany avec une entité Piece. L’idée étant qu’à la création d’un Lending, le statut des objets Piece soit mis à jour.

J’ai tenté de lier le listener dans les mappings, et de suivre la documentation officielle avec des paramètres supplémentaires que j’avais trouvés je-ne-sais-plus comment avec une version précédente de Symfony (tout en utilisant la possibilité de déclarer ses services de manière plus compacte). Au final, j’ai ce que je vous propose ci-dessous.

<?php

namespace YSoft\InstrumBundle\Listener;

use YSoft\InstrumBundle\Entity\Lending;

class LendingListener
{
    public function prePersist(Lending $lending, $eventArgs)
    {dump('Meuh');
        $this->changeLendingPiecesStatus($lending, $eventArgs);
    }

    public function preUpdate(Lending $lending, $eventArgs)
    {dump('Hi-han');
        $this->changeLendingPiecesStatus($lending, $eventArgs);
    }

    private function changeLendingPiecesStatus(Lending $lending, $eventArgs)
    {dump($eventArgs);
    exit();
        if ($lending->isOurs()) {
            $statusId = $lending->getEnd() ? 'unverified' : 'lent';
        } else {
            $statusId = $lending->getEnd() ? 'returned' : 'unverified';
        }
        $status = $eventArgs->getEntityManager()->getRepository('YSoftInstrumBundle:Status')->find($statusId);

        /** @var $piece \Ysoft\InstrumBundle\Entity\Piece */
        foreach ($lending->getPieces() as &$piece) {
            $piece->setStatus($status);
        }
    }
}
YSoft\InstrumBundle\Listener\LendingListener. J’ai mis les méthodes prePersist() et preUpdate() parce que ces noms devraient faire qu’elles soient automatiquement appelées si les tags ne sont pas reconnus
services:
  YSoft\InstrumBundle\Listener\LendingListener:
    tags:
      - { name: doctrine.orm.entity_listener, entity: YSoft\InstrumBundle\Entity\Lending, event: preUpdate, method: changeLendingPiecesStatus }
      - { name: doctrine.orm.entity_listener, entity: YSoft\InstrumBundle\Entity\Lending, event: prePersist, method: changeLendingPiecesStatus }
services.yml
YSoft\InstrumBundle\Entity\Lending:
  type: entity
  table: null
  repositoryClass: YSoft\InstrumBundle\Repository\LendingRepository
  entityListeners:
    YSoft\InstrumBundle\Listener\LendingListener:
      prePersist: [ changeLendingPiecesStatus ]
      preUpdate: [ changeLendingPiecesStatus ]
Extrait de Lending.orm.yml
  • La version déclarée uniquement dans les mappings n’est pas reconnue (impossible de voir le service avec la commande debug:container --show-private, et mes instructions de débogage ne sont pas déclenchées) ;
  • Si je déclare à la fois dans les mappings et comme service :

    • Si les tags sont spécifiés dans services.yml, j’ai une erreur pour avoir défini deux fois le service ;
    • Si j’enlève les tags, rien ne fonctionne.
  • Avec la déclaration dans services.yml, il est bien reconnu par Symfony :
Information for Service "YSoft\InstrumBundle\Listener\LendingListener"  
===================================================================================

 ---------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Option           Value                                                                                                                                                                                         
 ---------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
  Service ID       YSoft\InstrumBundle\Listener\LendingListener                                                                                                                                                  
  Class            YSoft\InstrumBundle\Listener\LendingListener                                                                                                                                                  
  Tags             doctrine.orm.entity_listener (entity: YSoft\InstrumBundle\Entity\Lending, event: preUpdate, method: changeLendingPiecesStatus)  
                   doctrine.orm.entity_listener (entity: YSoft\InstrumBundle\Entity\Lending, event: prePersist, method: changeLendingPiecesStatus)                     
  Public           yes                                                                                                                                                                                           
  Synthetic        no                                                                                                                                                                                            
  Lazy             no                                                                                                                                                                                            
  Shared           yes                                                                                                                                                                                           
  Abstract         no                                                                                                                                                                                            
  Autowired        no                                                                                                                                                                                            
  Autoconfigured   no                                                                                                                                                                                            
 ---------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Résultat de la commande debug:container YSoft\InstrumBundle\Listener\LendingListener

Seulement, aucune de mes instructions de débogage n’est appelée, et les modifications attendues ne sont pas effectuées. J’ai ajouté les paramètres entity, event et method parce qu’apparemment j’en avais eu besoin pour une autre application avec une version moins récente de Symfony (je suis en 3.3.12 avec Doctrine 2.6, j’étais en 3.3.1 et aucune idée de la version de Doctrine alors).

Quelqu’un arriverait à avoir le recul que je n’arrive pas à avoir ?

Merci d’avance  :)

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0

Salut,

As-tu essayé en mettant doctrine.event_listener à la place de doctrine.orm.entity_listener (et en modifiant les arguments) ? Lien.

Perso c’est ça que j’utilise sur mes entités, et ça fonctionne très bien.

Édité par John

Développeur Symfony

+1 -0
Auteur du sujet

Il y a eu des mises à jour depuis que j’ai posté cette question. J’ai notamment passé de doctrine/doctrine-bundle 1.6.11 à 1.8.0. Maintenant, mon listener fonctionne, et je n’ai même plus d’erreur si je le déclare en double. En revanche, je l’ai laissé dans les mappings, les paramètres de tags method ne sont apparemment pas/plus pris en compte.

Alors je n’ai pas le fin mot de l’histoire, mais c’est fonctionnel, donc je clos le sujet (et non clôture, seuls les modérateurs le peuvent).

Edit

En fait, je pense que je n’avais tout simplement pas vidé le cache. Je pense maintenant que je ne l’avais peut-être pas fait, parce que dès que j’ajoutais le service, je le voyais déclaré. Seulement, comme il est lié aux métadonnées des entités, il fallait qu’il y ait une trace là-bas… Forcément, la mise à jour des composants fait une purge du cache  :ange:

Mais ça reste que j’utilise la solution Doctrine et non Symfony au problème. Si un jour quelqu’un passe par là et a l’explication, je la lirai volontiers.

Edit 2

J’ai oublié ce sujet, mais avec Symfony 5.0, je peux ne faire que déclarer mes services dans services.yaml et plus besoin des mappings. Ne pas oublier de vider le cache expressément cependant, cela ne fait pas partie des choses qui sont surveillées et mises en cache automatiquement à chaque modification apparemment.

Édité par Ymox

Evitez qu’on vous dise de les lire : FAQ PHP et SymfonyTutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte