Partage
  • Partager sur Facebook
  • Partager sur Twitter

Event Doctrine Symfony

Sujet résolu
29 mars 2020 à 19:09:54

Bonjour,

Je suis en train de développer une application web avec Symfony.

Cependant, je voudrais faire quelque chose mais je ne sais pas quelle est la meilleure façon de le faire.

J'ai une entité Car qui a un attribut "int emplacement".

J'aimerais, avant de sauvegarder mon objet Car en base de donnée, vérifier qu'il n'y ait pas d'autre Car sur l'emplacement.

Du coup, j'ai pensé aux évènements prePersist ou preflush. 

L'évènement en question va regarder les Car en base de donnée et suivant si l'emplacement est vide ou pas, il va bloquer l'enregistrement en base ou non.

Pourriez vous me dire lequel est le plus adapté et comment mettre en place ce système ?

Merci d'avance pour votre réponse.

Cordialement

  • Partager sur Facebook
  • Partager sur Twitter
30 mars 2020 à 7:05:21

Bonjour,

La question qui me vient : pourquoi permettre de choisir une place éventuellement prise puis au moment de l'enregistrer faire le contrôle. Ne serait-il pas plus pertinent de ne pas montrer les places prises ?

Pour ta question, sans trop connaître le contexte, tu peux utiliser ce qui est le plus en amont donc le prePersist.

A+

  • Partager sur Facebook
  • Partager sur Twitter
30 mars 2020 à 11:27:45

Bonjour,

C'est pas plus simple de rendre le champ emplacement unique ?

  • Partager sur Facebook
  • Partager sur Twitter
30 mars 2020 à 12:38:55

@jmsche : De ce que j'ai cru comprendre, il y a des emplacements de parking. Il veut mettre des voitures dessus. Il permet de choisir au départ n'importe quel emplacement et  avant d'enregistrer il regarde si l'emplacement choisi n'est pas déjà occupé. ... si c'est cela bonjour l'expérience client qui doit recommencer ... et recommencer ... 

D'où ma proposition de ne pas montrer les places de parking déjà occupées.

Je ne vois pas trop en mettant le champ emplacement unique ce que cela résout ? si tu peux détailler.

A+

  • Partager sur Facebook
  • Partager sur Twitter
30 mars 2020 à 13:28:28

Bonjour,

Le problème est si 2 personnes enregistrent leur voiture en même temps, il va y avoir conflit car les 2 voitures vont pouvoir être enregistrée sur le même emplacement.

C'est pour cela que je fais une vérification avant d'enregistrer. D'ailleurs, je me demande si le fait de faire la vérification dans le preflush permet de faire la vérification d'une requête avant l'autre et pas les 2 en même temps ?

De plus, j'avais fais une procédure stockée avant d'utiliser Symfony et ca me permettait de faire exactement ce que je voulais. Cependant, je ne retrouve pas l'équivalence en Symfony (Peut être le preflush ?)

  • Partager sur Facebook
  • Partager sur Twitter
30 mars 2020 à 13:36:08

Tu ne réponds pas sur l'argument de ne présenter que les places libres ... ce qui me semble essentiel pour l'expérience client.

Ensuite certes le conflit d'accès concurrent pourrait exister ... mais as tu beaucoup d'utilisateurs simultanés ?

Avec Symfony les procédures stockées ce n'est pas le paradigme à mon avis.

Si lors du prePersist tu vérifies que la place n'est plus libre alors tu as résolu ton problème, non ?

A+

  • Partager sur Facebook
  • Partager sur Twitter
30 mars 2020 à 14:00:07

Le champ unique permet de 1) ne pas avoir de doublons en DB et 2) d'avoir une exception précise lors de la sauvegarde (gérée soit via la contrainte UniqueEntity, soit manuellement, en fonction du besoin).

A priori il veut faire ça lors de la sauvegarde, donc ce n'est pas un problème.

  • Partager sur Facebook
  • Partager sur Twitter
30 mars 2020 à 14:49:08

@jmsche

Je comprends l'intérêt de la contrainte unique dont je me sers assez souvent et je suppose qu'il l'a mis en oeuvre pour que chaque place de parking soit unique mais il me semble que son problème c'est qu'à un instant t une place de parking ne peut-être occupée que par une seule voiture. Et là je ne vois pas comment utiliser la contrainte unique.

Car pour moi il doit vérifier pour la place de parking donnée si la relation avec voiture existe déjà donc dans ce cas la place est occupée.

C'est pour cela que ta réponse m'intéresse si on peut faire ce genre de vérification de règle de gestion avec une simple annotation, j'apprendrai quelque chose.

A+

-
Edité par monkey3d 30 mars 2020 à 14:51:53

  • Partager sur Facebook
  • Partager sur Twitter
30 mars 2020 à 15:03:09

La description du problème n'est pas assez claire pour pouvoir émettre un avis clair dessus :)

Grosso modo :

  • Si on part dans l'optique d'un système de parking d'entreprise (dont chaque voiture a son emplacement), on peut mettre une contrainte d'unicité sur l'emplacement
  • Dans le cas d'une gestion de parking plus complexe (avec réservation d'un emplacement par jour pour exemple), on pourrait mettre une contrainte d'unicité sur le couple de champs emplacement-jour

Dans les deux cas, Doctrine permet d'ajouter cette contrainte d'unicité, et l'annotation UniqueEntity peut catcher l'exception dans le cas d'un formulaire ou l'utilisation plus basique du Validator.

  • Partager sur Facebook
  • Partager sur Twitter
30 mars 2020 à 15:47:00

@jmsche

Ok. Moi j'étais partie sur la gestion selon ton point 2 et j'ai pensé que son besoin était dynamique. Du style j'arrive il me faut une place mais il n'y a pas de réservation préalable.

Attendons qu'il précise son besoin.

A+

  • Partager sur Facebook
  • Partager sur Twitter
30 mars 2020 à 16:22:36

En fait, c'est de ma faute. J'ai mal expliqué le problème. J'ai voulu simplifier en mettant un emplacement en int. Mais en fait je me rend compte que cela induit en erreur.

En fait l'emplacement est géré avec des coordonnées (X,Y) et les dimensions de la voiture (width, height).

Bien entendu, je ne montre que les places disponibles aux utilisateurs. Le fait de vérifier avant de sauvegarder permet d'être sûr d'éviter les conflits lorsque 2 requêtes sont envoyées en même temps. (ceci est super rare, mais je préfère quand même vérifier)

Du coup, j'avais pensé utiliser un évènement Doctrine (prépersist ou preflush, d'ailleurs je ne vois pas trop la différence). Cet évènement va regarder en base de donnée si l'emplacement est bien disponible (en faisant des calculs avec les largeurs, hauteurs, et tout ...) :

 - Si l'emplacement est dispo, on enregistre la voiture

 - Si l'emplacement n'est pas dispo, on bloque l'enregistrement 

  • Partager sur Facebook
  • Partager sur Twitter
30 mars 2020 à 16:46:34

Finalement moi j'utiliserai plutôt l'event preUpdate car en fait c'est juste avant la mise à jour que tu regardes si la place est occupée ou non.

La doc pour la signification des events :

https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/events.html#lifecycle-events

A+

  • Partager sur Facebook
  • Partager sur Twitter
1 avril 2020 à 17:58:14

Ok, et du coup comment je ferai pour stopper le flush si jamais la place est déja prise ?
  • Partager sur Facebook
  • Partager sur Twitter
2 avril 2020 à 6:36:05

Le flush il est dans ton contrôleur ?

A+

  • Partager sur Facebook
  • Partager sur Twitter
2 avril 2020 à 13:03:08

Je n'ai pas testé ... mais je mettrai une valeur dans le preUpdate qui fait qui fait que le form n'est pas valide ...

A+

  • Partager sur Facebook
  • Partager sur Twitter
2 avril 2020 à 17:48:53

J'ai trouvé une solution en lançant une exception.

Mais n'y aurait-il pas une meilleure solution ?

Je ne trouve rien qui en parle sur Internet

  • Partager sur Facebook
  • Partager sur Twitter
2 avril 2020 à 17:52:56

Ce que je t'avais proposé me semblait être une solution ... mais l'exception me semble aussi une bonne solution.

A+

  • Partager sur Facebook
  • Partager sur Twitter