Site Overlay

Comment se passer de Gedmo dans Symfony

Symfony propose de nombreuses fonctionnalités et Doctrine en ajoute également beaucoup. Au fur et à mesure que la standardisation de Symfony avance, les liasses les moins utiles et les plus consommateurs sont remplacés par des bribes efficaces. Avec l’utilisation de Doctrine comme ORM, on a souvent besoin de Gedmo pour gérer le Soft Delete. Je me suis posé quelques minutes pour mettre en place un système similaire dans le but de limiter les dépendances de mon application.

Vous voulez supprimer un objet. Plutôt que de directement le supprimer, vous voulez l’archiver de manière à ce qu’il puisse être restauré plus tard. Cet objet archivé pourra être réellement supprimé par la suite. Pour cela, nous ajoutons un champs deletedAt sur notre entité. Si le champs est nul, l’objet est disponible. Au contraire si le champs est complété de la date de suppression effective ( &lt ; maintenant), l’article est supprimé.

Intégration à Doctrine

Nous voulons mettre en place le même système que ce que Gedmo peut nous proposer. Le seul comportement que nous devons surcharger est la méthode supprimer de l’responsable d’entité.

La deuxième partie consiste à cacher les objets qui ont été supprimés.

1

2

3

4

5

6

7

8

9

10

$em = $this->container->get( » doctrine.orm.default_entity_manager « ) ;

$object = $em->getRepository( » NamespaceMyBundle:Entity « )->find(1) ;

$em->remove($object) ;

$object = $em->getRepository( » NamespaceMyBundle:Entity « )->find(1) ;

Codons bien, codons efficace

Préparons notre entité

Notre entité doit posséder un attribut de type date (datetime).

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

<?php

espace de noms Espace de nomsMyBundleEntité;

utilisation DoctrineORMCartographie comme ORM;

classe Entité

{

* @var datetime $deletedAt

*

* @ORMColonne(name= « deletedAt « , type= « datetime « , nullable=true)

*/

privé $deletedAt ;

* Set deletedAt

*

* @param DateTime $deletedAt

* @return Plan

*/

public fonction setDeletedAt($deletedAt)

{

$this->deletedAt = $deletedAt ;

retour $this;

}

* Obtenir deletedAt

*

* @return DateTime

*/

public fonction getDeletedAt()

{

retour $this->deletedAt ;

}

}

Implémentation du listener

Un listener va être nécessaire pour venir corrompre le fonctionnement classique de Doctrine.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

<?php

espace de noms Espace de nomsMyBundleÉcouteur;

utilisation DoctrineORMÉvénementPreFlushEventArgs;

classe DoctrineListener

{

public fonction preFlush(PreFlushEventArgs $event) {

$em = $event->getEntityManager() ;

foreach ($em->getUnitOfWork()->getScheduledEntityDeletions() comme $object) {

if (method_exists($object,  » getDeletedAt « )) {

if ($object->getDeletedAt() instanceof Datetime) {

continuer;

} autre {

$object->setDeletedAt(nouveau DateTime()) ;

$em->merge($object) ;

$em->persist($object) ;

}

}

}

}

}

Détaillons rapidement le fonctionnement de cet écouteur d’événements. Pour chaque objet faisant partie de la liste de suppressions, si l’objet ne possède pas de date dans son champs deletedAt on ajoute le date actuelle. Dans le cas contraire, on doit effectuer une réelle suppression et on ne change pas le traitement en cours.

Ce traitement a été déporté dans un auditeur mais il aura été tout à fait possible d’affecter un événement de type PreRemove dans l’entité et d’effectuer le même traitement.

Enregistrer le listener

1

2

3

4

5

6

7

services :

kernel.listener.doctrine :

class : NamespaceMyBundleListenerDoctrineListener

public : faux

tags :

{ name : doctrine.event_listener, event : preFlush, method : preFlush }

Créer un filtre

Le filtre va nous permettre de facilement cacher les objets supprimés. Ce filtre activé, effectuer un trouver sur un élément supprimé ne retournera rien. La requête SQL initialement préparé est simplement complété d’une comparaison sur le champs deletedAt.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

<?php

espace de noms Espace de nomsMyBundleRéférentielFiltres;

utilisation DoctrineORMCartographieClassMetaData;

utilisation DoctrineORMRequêteFiltreSQLFilter;

classe DeletedFilter s’étend SQLFilter

{

public fonction addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)

{

si ($targetEntity->hasField( » deletedAt « )) {

$date = date( » A-m-d h:m:s « ) ;

retour $targetTableAlias. » .deletedAt &lt ; ‘ « .$date. » ‘ OR  » .$targetTableAlias. » .deletedAt IS NULL « ;

}

retour  » « ;

}

}

Ce script est valable pour une base de donnée MySQL mais les changements pour le faire fonctionner avec un autre SGBD comme PostgreSQL, SQL Server et autres.

Configurer le filtre Doctrine pour se lancer systématiquement

Tout est mis en place mais le filtre Doctrine présenté juste au dessus, doit encore être activé volontairement. Puisque supprimer des objets définitivement (supprimer des objets déjà supprimés) est une action que l’on réalise moins souvent, nous voulons activer ce filtre de manière systématique.

1

2

3

4

5

6

7

doctrine :

orm :

filtres :

supprimé :

classe : ‘NamespaceMyBundleRepositoryFiltersDeletedFilter’ (Espace de nomsMonBundleRepositoryFiltresDeletedFilter)

activé : vrai

Utiliser facilement notre système de Soft Delete

Par défaut, le comportement expliqué dans Intégration à Doctrine est permanente. Si vous voulez toutefois chercher toutes les entités supprimées, voici la manipulation à suivre.

1

$this->container->get( » doctrine.orm.default_entity_manager « )->getFilters()->disable( » supprimé « ) ;

Avec cette action, le filtre est désactivé et vous pouvez récupérer n’importe quel objet. Une fois un objet récupérer, si celui-ci possède une date dans deletedAt, vous pourrez le supprimer définitivement.

Conclusion

Implémenter son propre Effacement progressif est facile à réaliser, facile à comprendre. Cela vous permettra entre autre de limiter l’ajout d’une dépendance à votre projet ! Attention tout de même, la méthode présentée au-dessus couvre 99% des besoins que vous aurez. Gedmo apporte quant à lui la possibilité d’appliquer plus finement (mais également plus couteux) les règles à utiliser. Dans notre cas et avec une code identique à celui présenté, toutes les entités possédant un champs deletedAt ainsi que des accesseurs se verront appliqués une  » suppression douce « .

Lire  Le Nest Hub de Google est-il toujours le meilleur écran intelligent ?

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *