Partage
  • Partager sur Facebook
  • Partager sur Twitter

Doctrine - Mauvais résultats

7 août 2019 à 23:11:15

Bonjour, j'utilise doctrine avec un site symfony 3.4 et parfois le résultat des requêtes doctrine n'est pas le bon... Est-ce qu'il y en a parmi vous qui ont déjà eu ce genre de problèmes ? Ou c'est moi qui l'utilise mal... ?

Ceci arrive quand j'ai des conditions complexe...

Merci

  • Partager sur Facebook
  • Partager sur Twitter
8 août 2019 à 7:35:30

Bonjour,

Je pense que vu le niveau de maturité de Doctrine c'est sans doute toi qui l'utilise mal.

A+

  • Partager sur Facebook
  • Partager sur Twitter
7 septembre 2019 à 1:39:21

C'est ce que j'ai pensé aussi... Mais je ne crois pas et je t'explique pourquoi :

J'ai un site qui permet de gérer les inscriptions d'évènements en plus de permettre le paiement en ligne. Le problème survient lors du paiement. Pour effectuer son paiement, l'utilisateur a trois étapes a passer. 1- Page qui résume le total avec bouton Paypal pour initier le paiement, 2- Page qui résume encore une fois le total avec bouton qui demande de valider le paiement, 3- Confirmation du Paiement avec résumé du total. Entre l'étape 2 et 3, il y a un procédé côté serveur qui communique avec paypal pour faire le paiement (On va l'appeler étape 2.5).

De l'étape 1 à 2.5, il y a une seule et unique méthode du répository qui est appeler pour sortir le résumé de l'inscription. Lorsque deux utilisateurs différents créaient une inscription chaque et que l'un deux arrivait à l'étape 2.5, l'inscription de l'autre utilisateur apparaît dans le résumé alors qu'elle n'était pas là aux premières étapes.... J'ai réussi à reproduire le bug en local et j'ai rien trouvé qui peut l'expliquer...

Est-ce qu'il y aurait une notion de doctrine que j'aurais looper ? Merci
  • Partager sur Facebook
  • Partager sur Twitter
7 septembre 2019 à 6:50:00

Pour ma part impossible d'essayer d'avancer une piste avec si peu d'infos.

Tu te focalises sur Doctrine mais est-ce bien la cause ?

- tu as débugger ta requête ?

- utilises-tu les sessions ?

- etc.

A+

  • Partager sur Facebook
  • Partager sur Twitter
7 septembre 2019 à 14:28:55

Non j'ai pas débugger ma requête puisque je devais patcher le bug au plus vite donc j'ai simplement refiltrer dans le code php (Je sais ce n'est pas une bonne façon de faire lol) J'utilise le DQL pour batir mes requêtes. Présentement, je me cherche un profiler pour MySql pour voir la requête qui est envoyer. Si je ne trouves rien, je vais essayer avec du SQL Natif... Je vous tiens informé des avancements
  • Partager sur Facebook
  • Partager sur Twitter
9 septembre 2019 à 1:08:12

Bon, j'ai réussi a voir les requêtes qui sont envoyées à MySql par doctrine lorsque le bug se produit. Doctrine fait plusieurs requêtes pour rebâtir l'objet et les requêtes ne sont pas aussi précise que je l'espérais (WHERE). J'ai décidé de réécrire mes conditions de DQL avec les fonctions de expr(). Je me suis dit qu'il comprenait peut-être mal mes conditions et qu'il valait mieux utiliser les méthodes faites pour cela, mais ça n'a rien changé...

Je vous met les deux fonctions qui sont utilisés pour batir le DQL.

public function getEvenementPourCheckout($idEvenement, $idSession = null, $User = null)
    {
        $query = $this->baseQueryPourCheckout($idEvenement);
        if(isset($User))
        {
            $query->andWhere('inscriptions.user = :user OR e_inscriptions.user = :euser')
                  ->setParameter('user', $User)
                  ->setParameter('euser', $User);
            
           
        }
        else if(isset($idSession))
        {
//            $query->andWhere($query->expr()->orX($query->expr()->eq('inscriptions.idSession', '?1'), 
//                    $query->expr()->eq('e_inscriptions.idSession', '?1')));
//            $query->setParameter(1, $idSession);  
               $query->andWhere('inscriptions.idSession = :idSession OR e_inscriptions.idSession = :eidSession')
                ->setParameter('idSession', $idSession)
                ->setParameter('eidSession', $idSession);
                     
        }
        else
        {
            return null;
        }
        
        $query->andWhere('inscriptions.uidPayment IS NULL AND e_inscriptions.uidPayment IS NULL');
//        $query->andWhere($query->expr()->andX($query->expr()->isNull('inscriptions.uidPayment'), 
//                $query->expr()->isNull('e_inscriptions.uidPayment')));
        $t = $query->getQuery();
        return $query->getQuery()->getOneOrNullResult();
    }


public function baseQueryPourCheckout($idEvenement)
    {
        $query =  $this->createQueryBuilder('Evenement')
                       ->innerJoin('Evenement.gestionClasses', 'gestionClasses')
                       ->addSelect('gestionClasses')
                        
                       ->leftJoin('gestionClasses.inscriptions', 'inscriptions')
                       ->addSelect('inscriptions')
                       ->leftJoin('gestionClasses.equipes', 'equipes')
                       ->addSelect('equipes')
                       ->leftJoin('equipes.inscriptions', 'e_inscriptions')
                       ->addSelect('e_inscriptions')
                       ->andWhere('(Evenement.id = :id)')
                       ->setParameter('id', $idEvenement);
        //$query->andWhere($query->expr()->eq('Evenement.id', '?2'))->setParameter(2, $idEvenement);
        return $query;
    }


Voici la requête DQL qui en ressort :

SELECT Evenement, gestionClasses, inscriptions, equipes, e_inscriptions FROM QcRaces\EvenementsBundle\Entity\Evenement Evenement INNER JOIN Evenement.gestionClasses gestionClasses LEFT JOIN gestionClasses.inscriptions inscriptions LEFT JOIN gestionClasses.equipes equipes LEFT JOIN equipes.inscriptions e_inscriptions WHERE (Evenement.id = :id) AND (inscriptions.idSession = :idSession OR e_inscriptions.idSession = :eidSession) AND (inscriptions.uidPayment IS NULL AND e_inscriptions.uidPayment IS NULL)


J'ai aussi essayer le SQL Natif et là requête faite à MySql est exactement la même et retourne les bonnes données, mais puisqu'il faut Binder les données manuellement à l'objet, ça risque d'être une tâche beaucoup trop longue changer tous le DQL par du Natif... Ce n'est vraiment pas l'option que je préfère... L'option qu'il me reste, c'est de garder seulement les conditions simple et refiltrer les données avec du PHP dans les Repository. Ainsi, je m'assurerais de toujours avoir les bonnes données.

Sinon j'espère que vous allez voir un erreur dans ma requête qui cause ce bug ?

Merci pour votre aide et vos propositions :p

  • Partager sur Facebook
  • Partager sur Twitter
9 septembre 2019 à 6:04:39

Cela me semble bizarre le OR dans ta requête :

$query->andWhere('inscriptions.user = :user OR e_inscriptions.user = :euser')

Je mettrai plutôt une clause andWhere suivie d'une clause orWhere.

https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/query-builder.html

A+

  • Partager sur Facebook
  • Partager sur Twitter
9 septembre 2019 à 14:00:30

J'ai tenté ceci et le bug ce produit toujours. À noter qu'il ne rentre pas dans la première section du if

$query = $this->baseQueryPourCheckout($idEvenement);
        if(isset($User))
        {
            $query->andWhere('inscriptions.user = :user OR e_inscriptions.user = :euser')
                  ->setParameter('user', $User)
                  ->setParameter('euser', $User);
            
           
        }
        else if(isset($idSession))
        {
//            $query->andWhere($query->expr()->orX($query->expr()->eq('inscriptions.idSession', '?1'), 
//                    $query->expr()->eq('e_inscriptions.idSession', '?1')));
//            $query->setParameter(1, $idSession);  
               $query->andWhere('inscriptions.idSession = :idSession')->orWhere('e_inscriptions.idSession = :eidSession') //OR e_inscriptions.idSession = :eidSession')
                ->setParameter('idSession', $idSession)
                ->setParameter('eidSession', $idSession);
                     
        }
        else
        {
            return null;
        }
        
        $query->andWhere($query->expr()->isNull('inscriptions.uidPayment'))
                ->andWhere($query->expr()->isNull('e_inscriptions.uidPayment'));
  • Partager sur Facebook
  • Partager sur Twitter
9 septembre 2019 à 14:18:50

Salut !

Je pense qu'il pourrait n'y avoir qu'un souci de priorités. Actuellement, tu as quelque chose comme A et B ou C, en algèbre booléenne, on aurait A * B + C ≡ AB + C. Or, à mon avis, tu aimerais A et (B ou C), A * (B + C) ≡ AB + AC.

Dans ce dernier cas, au niveau Doctrine, dans tes "branches de if", il faudrait que tu aies andWhere('B OR C') en remplaçant B et C par respectivement ce qu'il y a dans andWhere et dans orWhere.

-
Edité par Ymox 9 septembre 2019 à 14:19:47

  • Partager sur Facebook
  • Partager sur Twitter
9 septembre 2019 à 18:50:01

Ymox a écrit:

Salut !

Je pense qu'il pourrait n'y avoir qu'un souci de priorités. Actuellement, tu as quelque chose comme A et B ou C, en algèbre booléenne, on aurait A * B + C ≡ AB + C. Or, à mon avis, tu aimerais A et (B ou C), A * (B + C) ≡ AB + AC.

Dans ce dernier cas, au niveau Doctrine, dans tes "branches de if", il faudrait que tu aies andWhere('B OR C') en remplaçant B et C par respectivement ce qu'il y a dans andWhere et dans orWhere.

-
Edité par Ymox il y a environ 4 heures

Et comment je m'y prends pour faire ça "andWhere('B OR C')" en utilisant les fonctions ? J'inclus les where un dans l'autre ?

  • Partager sur Facebook
  • Partager sur Twitter
9 septembre 2019 à 21:15:12

De la même manière que tu n'utilises pas de fonction quand tu fais inscriptions.idSession = :idSession , tu peux très bien mettre OR dans une condition.  ^^

Après, si tu souhaites utiliser tout le potentiel du QueryBuilder, inscriptions.idSession = :idSession serait aussi remplaçable par une fonction. Dans la mesure ou les requêtes sont mises en cache, ça ne change pas grand chose il me semble.

-
Edité par Ymox 9 septembre 2019 à 21:16:59

  • Partager sur Facebook
  • Partager sur Twitter
10 septembre 2019 à 1:05:26

Ymox a écrit:

De la même manière que tu n'utilises pas de fonction quand tu fais inscriptions.idSession = :idSession , tu peux très bien mettre OR dans une condition.  ^^

Après, si tu souhaites utiliser tout le potentiel du QueryBuilder, inscriptions.idSession = :idSession serait aussi remplaçable par une fonction. Dans la mesure ou les requêtes sont mises en cache, ça ne change pas grand chose il me semble.

-
Edité par Ymox il y a environ 3 heures


C'est déjà ce que je fais dans le premier post.. J'ai meme mis la requête DQL générer...

Edit : J'ai tenté un getDoctrine()->resetManager(); des fois qu'il y aurait eu un problème interne avec Doctrine, mais ça n'a rien changé au résultat

Edit 2 : J'ai enlever la deuxième section du OR pour n'y laisser que la première et toujours le même bug...

$query->andWhere('inscriptions.idSession = :idSession')// OR e_inscriptions.idSession = :eidSession)')


-
Edité par typoc 10 septembre 2019 à 2:23:02

  • Partager sur Facebook
  • Partager sur Twitter
10 septembre 2019 à 8:36:27

Avec l'ExpressionBuilder, il faut faire $query->expr()->orX(), et les arguments sont les expressions qui serviront d'alternative.

Tu aurais la requête SQL qui te retourne les bons résultats ?

  • Partager sur Facebook
  • Partager sur Twitter
10 septembre 2019 à 13:48:20

Ymox a écrit:

Avec l'ExpressionBuilder, il faut faire $query->expr()->orX(), et les arguments sont les expressions qui serviront d'alternative.

Tu aurais la requête SQL qui te retourne les bons résultats ?

Déjà essayer...

$query->andWhere($query->expr()->orX($query->expr()->eq('inscriptions.idSession', '?1'), 
                    $query->expr()->eq('e_inscriptions.idSession', '?1')));
            $query->setParameter(1, $idSession);

Non je n'ai pas la requête, j'ai déjà essayer de l'avoir avec les logs de MySql et ce que j'ai réussi a trouver c'est que doctrine fait 3-4 requêtes pour réussi à hydrater l'objet...


  • Partager sur Facebook
  • Partager sur Twitter
10 septembre 2019 à 14:40:50

Je te demande celle que tu aurais faite, pas celle générée  ;)

Parce que là, manifestement, c'est un souci d'utilisation de l'outil de construction si tu as la bonne requête SQL quelque part qu'on pourra "traduire".

  • Partager sur Facebook
  • Partager sur Twitter
10 septembre 2019 à 18:00:55

Non je n'ai pas faite de requête SQL de base. Je vais t'en écrire une ce soir. Je vais aussi tenter de changer de version de doctrine (Monter à la version 3, question de voir si ça change quelque chose).

Edit : J'ai seulement réussi à monter à la version 2.7 et le problème est toujours là lorsque le paiement s'exécute...

Pour ce qui est de la requête, voici celle que j'avais utiliser lorsque j'avais essayer avec du SQL Natif

SELECT e.id as event_id, e.nom as event_nom, classe_inscription.nom as classe_nom, classe_inscription.id as classe_id, 
                i.id as i_id, i.classe_inscription_id, i.dateheure AS i_dateheure, i.dateheuremodification AS i_dateheuremodif, i.equipe_id, i.idSession AS i_idsession, 
                i.informations_participant_id, i.numero_id, i.Prix AS i_prix, i.uidPayment AS i_uidPayment, i.user_id, i.vehicule_id 
                FROM evenement AS e 
                INNER JOIN classe_inscription ON e.id = classe_inscription.evenement_id 
                 LEFT JOIN inscription as i ON classe_inscription.id = i.classe_inscription_id 
                 LEFT JOIN equipe ON classe_inscription.id = equipe.classe_inscription_id 
                 LEFT JOIN inscription as ei ON equipe.id = ei.equipe_id 
                 WHERE e.id = :idEvent AND (i.idSession = :idSess OR ei.idSession = :idSess) AND i.uidPayment IS NULL AND ei.uidPayment IS NULL;
        


L'idée c'est que doctrine doit m'hydrater l'objet "Evenement" Selon les conditions. L'objet Evenement est constitué comme-ci : Evenement peut contenir de 0 à * classes et classe peut contenir soit des inscriptions ou des équipes. Équipes contient aussi des inscriptions.

Je me demande si c'est pas ma "logique" qui pourrait causer problème, mais je serais surpris...

-
Edité par typoc 11 septembre 2019 à 3:11:08

  • Partager sur Facebook
  • Partager sur Twitter
11 septembre 2019 à 21:34:47

Désolé, tu avais édité ton message, et du coup ça n'a pas fait remonter le sujet (une des raisons qui pousse à répondre soit pour clore le sujet, soit pour fournir de nouveaux éléments, mais pas juste pour dire "Je vais le faire" et revenir éditer  :p )

Si ta requête native te retourne vraiment ce que tu souhaites, il ne devrait plus être trop difficile de la "traduire en QueryBuilder".

Je note au passage que ma première intervention était dans le bon sens, étant donné que tu as bien des parenthèses autour de deux expressions et du OR, chose que tu n'avais pas dans ta première version  ^^

Normalement, quand Symfony est en "mode dev", tu as un onglet Doctrine dans la barre de débogage, et cet onglet te permet de regarder les requêtes effectuées, tant DQL que SQL. Je pense que ça te sera utile pour continuer.

J'ai un peu de peine à me retrouver entre les noms de tes tables/colonnes et les noms de tes entités/propriétés, mais je vais tenter ça. J'ai volontairement fait des requêtes sur tous les champs des tables pour éviter une syntaxe particulière avec le QueryBuilder.

SELECT
    ev.*,
    cl.*,
    icl.*
FROM    evenement ev
    INNER JOIN
        classe_inscription cl
        ON      ev.id = cl.evenement_id
    LEFT JOIN
        inscription icl
        ON      cl.id = icl.classe_inscription_id
    LEFT JOIN
        equipe
        ON      cl.id = equipe.classe_inscription_id
    LEFT JOIN
        inscription ieq
        ON      equipe.id = ieq.equipe_id
WHERE
        ev.id = :idEvent
    AND ( icl.idsession = :idSess
        OR  ieq.idsession = :idSess )
    AND icl.uidpayment IS NULL
    AND ieq.uidpayment IS NULL;
$qb ->createQueryBuilder('ev');
$qb ->innerJoin('ev.gestionClasses', 'cl')->addSelect('cl')
	->leftJoin('cl.inscriptions', 'icl')->addSelect('icl')
	->leftJoin('cl.equipes', 'eq')
	->leftJoin('eq.inscriptions', 'ieq')
	->where($qb->expr()->eq('ev.id', ':idEvent')
	->andWhere($qb->expr()->orX(
		$qb->expr()->eq('icl.idSession', ':idSess'),
		$qb->expr()->eq('ieq.idSession', ':idSess'),
	)
	->andWhere($qb->expr()->isNull('icl.payment'))
	->andWhere($qb->expr()->isNull('ieq.payment'))

Si on part du principe que ta requête te retournait bien ce que tu attendais, en adaptant les noms d'entités et de propriétés dans le PHP, on devrait avoir la même requête SQL de générée. Si ce n'est pas le cas, il faudra comparer la tienne et celle générée avec cette séquence QueryBuilder.

  • Partager sur Facebook
  • Partager sur Twitter
12 septembre 2019 à 14:08:25

Ymox a écrit:

Je note au passage que ma première intervention était dans le bon sens, étant donné que tu as bien des parenthèses autour de deux expressions et du OR, chose que tu n'avais pas dans ta première version  ^^

Non, mais la requête finale en avait ;) Le query builder les ajoutes :p

La requête que tu m'as écrit revient exactement à une requête que j'avais déjà essayer et qui me causait quand même le bug lors du paiement avec paypal.


Je ne savais pas que je pouvais voir les requêtes générées dans la barre de débogage (Merci tu m'as appris dequoi :) )

J'ai tester les requêtes directement dans sql et j'ai les bons résultats...

Je te les mets ici des fois que tu verrais quelque choses. Sinon ce soir je vais étudier les requêtes du update...

Sinon est-ce que ça pourrait être une mauvaise config dans mes entités ?

ELECT e0_.id AS id_0, e0_.Nom AS Nom_1, e0_.Description AS Description_2, e0_.DateEvenement AS DateEvenement_3, e0_.DateFinEvenement AS DateFinEvenement_4, e0_.DateAjoutEvenement AS DateAjoutEvenement_5, e0_.DateModificationEvenement AS DateModificationEvenement_6, e0_.DateDebutAffichage AS DateDebutAffichage_7, e0_.adresse_site_web AS adresse_site_web_8, e0_.page_facebook AS page_facebook_9, e0_.ToggleNumero AS ToggleNumero_10, e0_.fraisTransactionPayerParParticipant AS fraisTransactionPayerParParticipant_11, e0_.telephoneOrganisateur AS telephoneOrganisateur_12, e0_.prenomOrganisateur AS prenomOrganisateur_13, e0_.nomOrganisateur AS nomOrganisateur_14, e0_.isApproved AS isApproved_15, p1_.ClientId AS ClientId_16, p1_.secret AS secret_17, p1_.id AS id_18, e0_.categorie_id AS categorie_id_19, e0_.adresse_id AS adresse_id_20, e0_.stripe_id AS stripe_id_21, e0_.paypal_id AS paypal_id_22, e0_.gestion_numero_id AS gestion_numero_id_23 FROM evenement e0_ INNER JOIN paypal p1_ ON e0_.paypal_id = p1_.id WHERE e0_.id = ?

Parameters:

[▼ ▼
  "12"
]



SELECT t0.id AS id_1, t0.Nom AS Nom_2, t0.NbreInscription AS NbreInscription_3, t0.PrixInscription AS PrixInscription_4, t0.DateDebutInscription AS DateDebutInscription_5, t0.DateFinInscriptions AS DateFinInscriptions_6, t0.Description AS Description_7, t0.evenement_id AS evenement_id_8, t0.gestion_inscription_id AS gestion_inscription_id_9, t10.id AS id_11, t10.DateHeure AS DateHeure_12, t10.DateHeureModification AS DateHeureModification_13, t10.Prix AS Prix_14, t10.FraisTransactionPaye AS FraisTransactionPaye_15, t10.idSession AS idSession_16, t10.uidPayment AS uidPayment_17, t10.classe_inscription_id AS classe_inscription_id_18, t10.equipe_id AS equipe_id_19, t10.user_id AS user_id_20, t10.informations_participant_id AS informations_participant_id_21, t10.numero_id AS numero_id_22, t10.vehicule_id AS vehicule_id_23 FROM classe_inscription t0 LEFT JOIN inscription t10 ON t10.classe_inscription_id = t0.id WHERE t0.evenement_id = ? ORDER BY t0.id ASC

Parameters:

[▼ ▼
  12
]

SELECT t0.id AS id_1, t0.Prenom AS Prenom_2, t0.Nom AS Nom_3, t0.Courriel AS Courriel_4, t0.Telephone AS Telephone_5, t0.adresse_id AS adresse_id_6, t7.id AS id_8, t7.NoCivique AS NoCivique_9, t7.Appartement AS Appartement_10, t7.Route AS Route_11, t7.Ville AS Ville_12, t7.Province AS Province_13, t7.CodePostal AS CodePostal_14, t7.Pays AS Pays_15, t7.location_id AS location_id_16 FROM informations_participant t0 LEFT JOIN adresse t7 ON t0.adresse_id = t7.id WHERE t0.id IN (?)

Parameters:

[▼ ▼
  [▼ ▼
    11
    8
    12
    13
    14
    15
    16
    18
    19
    20
    21
    22
    23
    26
    27
    28
    29
  ]
]

SELECT e0_.id AS id_0, e0_.Nom AS Nom_1, e0_.Description AS Description_2, e0_.DateEvenement AS DateEvenement_3, e0_.DateFinEvenement AS DateFinEvenement_4, e0_.DateAjoutEvenement AS DateAjoutEvenement_5, e0_.DateModificationEvenement AS DateModificationEvenement_6, e0_.DateDebutAffichage AS DateDebutAffichage_7, e0_.adresse_site_web AS adresse_site_web_8, e0_.page_facebook AS page_facebook_9, e0_.ToggleNumero AS ToggleNumero_10, e0_.fraisTransactionPayerParParticipant AS fraisTransactionPayerParParticipant_11, e0_.telephoneOrganisateur AS telephoneOrganisateur_12, e0_.prenomOrganisateur AS prenomOrganisateur_13, e0_.nomOrganisateur AS nomOrganisateur_14, e0_.isApproved AS isApproved_15, c1_.id AS id_16, c1_.Nom AS Nom_17, c1_.NbreInscription AS NbreInscription_18, c1_.PrixInscription AS PrixInscription_19, c1_.DateDebutInscription AS DateDebutInscription_20, c1_.DateFinInscriptions AS DateFinInscriptions_21, c1_.Description AS Description_22, i2_.id AS id_23, i2_.DateHeure AS DateHeure_24, i2_.DateHeureModification AS DateHeureModification_25, i2_.Prix AS Prix_26, i2_.FraisTransactionPaye AS FraisTransactionPaye_27, i2_.idSession AS idSession_28, i2_.uidPayment AS uidPayment_29, e3_.id AS id_30, e3_.NomEquipe AS NomEquipe_31, i4_.id AS id_32, i4_.DateHeure AS DateHeure_33, i4_.DateHeureModification AS DateHeureModification_34, i4_.Prix AS Prix_35, i4_.FraisTransactionPaye AS FraisTransactionPaye_36, i4_.idSession AS idSession_37, i4_.uidPayment AS uidPayment_38, e0_.categorie_id AS categorie_id_39, e0_.adresse_id AS adresse_id_40, e0_.stripe_id AS stripe_id_41, e0_.paypal_id AS paypal_id_42, e0_.gestion_numero_id AS gestion_numero_id_43, c1_.evenement_id AS evenement_id_44, c1_.gestion_inscription_id AS gestion_inscription_id_45, i2_.classe_inscription_id AS classe_inscription_id_46, i2_.equipe_id AS equipe_id_47, i2_.user_id AS user_id_48, i2_.informations_participant_id AS informations_participant_id_49, i2_.numero_id AS numero_id_50, i2_.vehicule_id AS vehicule_id_51, e3_.classe_inscription_id AS classe_inscription_id_52, i4_.classe_inscription_id AS classe_inscription_id_53, i4_.equipe_id AS equipe_id_54, i4_.user_id AS user_id_55, i4_.informations_participant_id AS informations_participant_id_56, i4_.numero_id AS numero_id_57, i4_.vehicule_id AS vehicule_id_58 FROM evenement e0_ INNER JOIN classe_inscription c1_ ON e0_.id = c1_.evenement_id LEFT JOIN inscription i2_ ON c1_.id = i2_.classe_inscription_id LEFT JOIN equipe e3_ ON c1_.id = e3_.classe_inscription_id LEFT JOIN inscription i4_ ON e3_.id = i4_.equipe_id WHERE (e0_.id = ?) AND (i2_.idSession = ? OR i4_.idSession = ?) AND i2_.uidPayment IS NULL AND i4_.uidPayment IS NULL ORDER BY c1_.id ASC, e3_.NomEquipe ASC

Parameters:

[▼ ▼
  "12"
  "n4pscqlvua92mpma4q7i3ct1md"
  "n4pscqlvua92mpma4q7i3ct1md"
]



  • Partager sur Facebook
  • Partager sur Twitter
12 septembre 2019 à 15:42:42

La requête que tu m'as écrit revient exactement à une requête que j'avais déjà essayer et qui me causait quand même le bug lors du paiement avec paypal.

Précision s'il te plaît : la requête SQL ou la requête avec le QueryBuilder ?

Le truc, c'est que je n'ai pas les correspondances entre tes entités/propriétés et tes tables/colonnes, ça n'aide pas trop.

Les requêtes que tu me donnes sous forme de code, elles viennent d'où ? Elles sont bonnes ou pas ?

  • Partager sur Facebook
  • Partager sur Twitter
14 septembre 2019 à 4:44:31


La requête DQL que tu as fait à partir de mon SQL.

Les requêtes que je t'ai données à mon dernier post, je l'ai pris dans l'onglet Doctrine de la barre de débogage

Jte donne mes classes, mais je t'avertis ça peut être melant un peu hhaha

/**
 * Evenement
 * @ORM\HasLifecycleCallbacks()
 * @ORM\Table(name="evenement")
 * @ORM\Entity(repositoryClass="QcRaces\EvenementsBundle\Repository\EvenementRepository")
 * 
 */

// @ORM\HasLifecycleCallbacks() Attention les lettres minuscules et majuscule sont importantes
class Evenement
{

    /**
    * @ORM\ManyToOne(targetEntity="QcRaces\EvenementsBundle\Entity\Categorie")
    * @ORM\JoinColumn(nullable=false)
    */
    private $categorie;
    
      /**
     * @ORM\ManyToMany(targetEntity="QcRaces\EvenementsBundle\Entity\Tag", inversedBy="evenements")
     * @ORM\JoinTable(name="evenement_tag", 
     * joinColumns={@ORM\JoinColumn(name="evenement_id", referencedColumnName="id")}, 
     * inverseJoinColumns={@ORM\JoinColumn(name="tag_id", referencedColumnName="id")}) 
     */
    private $tags;
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="Nom", type="string", length=255)
     * @Assert\NotBlank()
     * @Assert\Length(min=3, minMessage="Le nom de l'évènement doit contenir au moins 3 caractères.")
     */
    private $nom;

    /**
     * @var string
     *
     * @ORM\Column(name="Description", type="text")
     * @Assert\NotBlank()
     * @Assert\Length(min=20, minMessage="La description doit contenir au moins une phrase.")
     */
    private $description;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="DateEvenement", type="datetime")
     * @Assert\NotBlank()
     * @Assert\GreaterThanOrEqual("today", message="Cette valeur doit être supérieure ou égale à la date d'aujourd'hui.", groups={"registration"})
     */
    private $dateEvenement;

    /**
     * @var \DateTime
     * @ORM\Column(name="DateFinEvenement", type="datetime")
     * @Assert\NotBlank()
     * @Assert\GreaterThanOrEqual("today", message="Cette valeur doit être suprieure ou égale à la date d'aujourd'hui.", groups={"registration"})
     */
    private $dateFinEvenement;
    /**
     * @var \DateTime
     *
     * @ORM\Column(name="DateAjoutEvenement", type="datetime")
     * 
     */
    private $dateAjoutEvenement;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="DateModificationEvenement", type="date", nullable=true)
     * 
     */
    private $dateModificationEvenement;

    /**
     * @var string
     *
     * @ORM\OneToOne(targetEntity="QcRaces\EvenementsBundle\Entity\Adresse", cascade={"persist"})
     * @Assert\Valid()
     */
    private $adresse;
    

    
    /**
     *
     * @var \DateTime
     */
    private $dateReporte;
    
    /**
     *
     * @var bool
     */
    private $annule;
            
   
    /**
     * @var bool
     */
    private $NumeroUniqueEvenement;
    
    /**
     *
     * @ORM\OneToMany(targetEntity="image", mappedBy="evenement", cascade={"persist", "remove"})
     * @Assert\Valid()
     */
    private $images;
    
    /**
     *
     * @ORM\OneToMany(targetEntity="PDF", mappedBy="evenement", cascade={"persist", "remove"})
     * @Assert\Valid()
     */
    private $pdfs;
    
    /**
     *
     * @var \DateTime
     * @ORM\Column(name="DateDebutAffichage", type="date", nullable=false)
     * @Assert\NotBlank()
     * @Assert\GreaterThanOrEqual("today", message="Cette valeur doit être supérieure ou égale à la date d'aujourd'hui.", groups={"registration"})
     */
    private $dateDebutAffichage;
    
    /**
     *
     * @var type String
     * @ORM\Column(type="text", nullable=true)
     * @Assert\Url(protocols = {"http", "https"})
     */
    private $adresseSiteWeb;
   
    /**
     *
     * @var type String
     * @ORM\Column(type="text", nullable=true)
     * @Assert\Url(protocols = {"http", "https"})
     */
    private $pageFacebook;
    
    /**
     *
     * @ORM\OneToMany(targetEntity="InfoBillet", mappedBy="evenement", cascade={"persist", "remove"})
     * @Assert\Valid()
     */
    private $infoBillet;
    
    /**
     *
     * @ORM\OneToOne(targetEntity="QcRaces\EvenementsBundle\Entity\Stripe", cascade={"persist", "remove"})
     */
    private $stripe;
    
    /**
     *
     * @ORM\OneToOne(targetEntity="QcRaces\EvenementsBundle\Entity\Paypal", cascade={"persist", "remove"})
     */
    private $paypal;
    
    /**
     * @ORM\OneToMany(targetEntity="QcRaces\EvenementsBundle\Entity\ClassesInscription", mappedBy="evenement", cascade={"persist", "remove"}, fetch="EAGER")
     * @ORM\OrderBy({"id" = "ASC"})
     */
    //
    private $gestionClasses;
    
    public $toggleClasses = true; // Doit tjrs être a true;
    
    /**
     * @var bool
     *
     * @ORM\Column(name="ToggleNumero", type="boolean")
     * @Assert\Type("bool", message="Cette valeur doit être un boolean")
     */
    public $toggleNumero;
    /**
     *
     * @ORM\OneToOne(targetEntity="QcRaces\GestionInscriptionBundle\Entity\GestionNumero", cascade={"persist", "remove"})
     * @ORM\JoinColumn(nullable=true) 
     * @Assert\Valid()
     */
    private $gestionNumero;
    
    /**
     *
     * @ORM\Column(name="fraisTransactionPayerParParticipant", type="boolean")
     * @Assert\Type("bool", message="Cette valeur doit être un boolean")
     */
    private $fraisTransactionsPayerParParticipant = false;
    
    
    /**
     * @var string
     *
     * @ORM\Column(name="telephoneOrganisateur", type="string", length=15, nullable=true)
     * @Telephone
     */
    private $telephone;

    
    /**
     *
     * @ORM\Column(name="prenomOrganisateur", type="string", length=100, nullable=true)
     * @var type string
     */
    private $prenomOrganisateur;
    
    
    /**
     *
     * @ORM\Column(name="nomOrganisateur", type="string", length=100, nullable=true)
     * @var type string
     */
    private $nomOrganisateur;
    
    /**
     *
     * @var type boolean
     * @ORM\Column(name="isApproved", type="boolean", nullable=false)
     */
    private $isApproved;
}
/**
 * 
 *@ORM\HasLifecycleCallbacks()
 * @ORM\Table(name="classe_inscription")
 * @ORM\Entity(repositoryClass="QcRaces\EvenementsBundle\Repository\ClassesInscriptionRepository")
 */
class ClassesInscription
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="Nom", type="string", length=255)
     * @Assert\NotBlank()
     */
    private $nom;

    /**
     * @var int
     *
     * @ORM\Column(name="NbreInscription", type="integer")
     * @Assert\Type(type="integer", message="Cette valeur doit être un nombre entier valide.")
     * @Assert\GreaterThan(0)
     * @Assert\LessThan(10000)
     * @Assert\NotNull(message="Cette valeur ne peut pas être vide")
     * @Assert\NotBlank()
     */
    private $nbreInscription;
    
    private $nbreActuelInscription; // Sert seulement pour le form. La valeur est mise dans un hidden
    


    /**
     * @var string
     *
     * @ORM\Column(name="PrixInscription", type="decimal", precision=10, scale=2)
     * @Assert\Type("real", message="Cette valeur doit être une valeur décimal (xx,xx)")
     * @Assert\GreaterThanOrEqual(0)
       @Assert\LessThan(10000)
     * @Assert\NotBlank()
     */
    private $prixInscription;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="DateDebutInscription", type="datetime")
     * @Assert\NotBlank()
     * @Assert\GreaterThanOrEqual("today", message="Cette valeur doit être supérieure ou égale à la date d'aujourd'hui.", groups={"registration"})
     */
    private $dateDebutInscription;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="DateFinInscriptions", type="datetime")
     * @Assert\NotBlank()
     * @Assert\GreaterThanOrEqual("today", message="Cette valeur doit être supérieure ou égale à la date d'aujourd'hui.", groups={"registration"})
     */
    private $dateFinInscriptions;

    /**
     * @var string
     *
     * @ORM\Column(name="Description", type="text", nullable=true)
     */
    private $description;



    /**
     *
     * @ORM\ManyToOne(targetEntity="QcRaces\EvenementsBundle\Entity\Evenement", inversedBy="gestionClasses")
     * @ORM\JoinColumn(nullable=false) 
     * 
     */
    private $evenement;
    
    public $toggleInscription = true; // Va permettre de vérifier gestionInscription
    //, inversedBy="classeInscription")
    /**
     *
     *  @ORM\OneToOne(targetEntity="QcRaces\GestionInscriptionBundle\Entity\GestionInscription", cascade={"persist", "remove"})
     *  @ORM\JoinColumn(nullable=false) 
     * 
     */
    private $gestionInscription;
    
    /**
     * @ORM\OneToMany(targetEntity="QcRaces\InscriptionBundle\Entity\Inscription", mappedBy="classeInscription", cascade={"persist", "remove"}, fetch="EAGER")
     * 
     */
    private $inscriptions;
    
    /**
     *
     * @ORM\OneToMany(targetEntity="QcRaces\InscriptionBundle\Entity\Equipe", mappedBy="classeInscription", cascade={"persist", "remove"}) 
     * @ORM\OrderBy({"nomEquipe" = "ASC"})
     */
    private $equipes;
}
/**
 * Inscription
 *
 * @ORM\Table(name="inscription")
 * @ORM\Entity(repositoryClass="QcRaces\InscriptionBundle\Repository\InscriptionRepository")
 * @ORM\HasLifecycleCallbacks()
 */
class Inscription
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="DateHeure", type="datetime")
     */
    private $dateHeure;

    /**
     * @var \DateTime|null
     *
     * @ORM\Column(name="DateHeureModification", type="datetime", nullable=true)
     */
    private $dateHeureModification;

    /**
     * @var string
     *
     * @ORM\Column(name="Prix", type="decimal", precision=10, scale=2)
     */
    private $prix;

    /**
     * @var bool
     *
     * @ORM\Column(name="FraisTransactionPaye", type="boolean")
     */
    private $fraisTransactionPaye;

    /**
     * @var \stdClass
     *
     * @ORM\ManyToOne(targetEntity="QcRaces\EvenementsBundle\Entity\ClassesInscription", inversedBy="inscriptions")
     * @ORM\JoinColumn(nullable=true)
     * 
     */
    private $classeInscription;

    /**
     * @var \stdClass|null
     *
     * 
     * @ORM\ManyToOne(targetEntity="QcRaces\InscriptionBundle\Entity\Equipe", inversedBy="inscriptions")
     * @ORM\JoinColumn(nullable=true)
     * 
     */
    private $equipe;

    /**
     * @var \stdClass|null
     *
     * @ORM\ManyToOne(targetEntity="UserBundle\Entity\User", inversedBy="inscriptions")
     * @ORM\JoinColumn(nullable=true)
     */
    private $user;

    /**
     * @var \stdClass
     *
     * @ORM\OneToOne(targetEntity="QcRaces\InscriptionBundle\Entity\InformationsParticipant", cascade={"persist", "remove"}, fetch="EAGER")
     * @ORM\JoinColumn(nullable=true, onDelete="CASCADE") 
     * 
     */
    private $informationsParticipant;

    /**
     * @var \stdClass|null
     *
     * @ORM\OneToOne(targetEntity="QcRaces\InscriptionBundle\Entity\Numero", cascade={"persist", "remove"}, fetch="EAGER")
     * @ORM\JoinColumn(nullable=true, onDelete="CASCADE") 
     * 
     */
    private $numero;

    /**
     * 
     *
     * 
     */
    private $options;

    /**
     * @var \stdClass|null
     *

     * @ORM\OneToOne(targetEntity="QcRaces\InscriptionBundle\Entity\Vehicule", cascade={"persist", "remove"}, fetch="EAGER")
     * @ORM\JoinColumn(nullable=true, onDelete="CASCADE") 
     * 
     */
    private $vehicule;

    
    /**
     *
     * @ORM\Column(name="idSession", type="string", nullable=true)
     */
    private $idSession;
    
    /*
     * @ORM\Column(name="isConfirmed", type="boolean", nullable=false)
     */
    //private $isConfirmed;
    
    /**
     *
     * @ORM\Column(name="uidPayment", type="guid", nullable=true)
     * @var type 
     */
    private $uidPayment;
}

/**
 * Equipe
 *  @ORM\HasLifecycleCallbacks()
 * @ORM\Table(name="equipe")
 * @ORM\Entity(repositoryClass="QcRaces\InscriptionBundle\Repository\EquipeRepository")
 */
class Equipe
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="guid")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="UUID")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="NomEquipe", type="string", length=255)
     * @Assert\NotBlank
     */
    private $nomEquipe;

    /**
     * @var \stdClass
     *
     * @ORM\ManyToOne(targetEntity="QcRaces\EvenementsBundle\Entity\ClassesInscription", inversedBy="equipes")
     * @ORM\JoinColumn(nullable=false) 
     */
    private $classeInscription;
    
   

    /**
     * @var array|null
     *
     * @ORM\OneToMany(targetEntity="QcRaces\InscriptionBundle\Entity\Equipe_Couleur", mappedBy="Equipe", cascade={"persist", "remove"}, fetch="EAGER")
     * @ORM\OrderBy({"id" = "ASC"})
     */
    private $equipecouleurs;

    private $nbreCouleursAurorises;

    /**
     *
     * @var type 
     * @ORM\OneToMany(targetEntity="QcRaces\InscriptionBundle\Entity\Inscription", mappedBy="equipe", cascade={"persist", "remove"}, fetch="EAGER") 
     * 
     * @Assert\Count(min=1, max=1000, minMessage = "L'équipe doit avoir au minimum {{ limit }} participant.", 
     * maxMessage = "L'équipe ne peut pas avoir plus de {{ limit }} participants.", groups={"Ajout"})
     */
    private $inscriptions;
    
    private $nbreInscriptionsAutorises;
}


J'ai pas mis les méthodes pour ne pas surcharger...

Je pense pas mal avoir fait le tour des possibilités en ce qui concerne le bug... Je commence a avoir mis beaucoup de temps pour le trouver et bientôt je vais probablement juste ajouter des validations dans les repo pour m'assurer de toujours avoir les bonnes données...

  • Partager sur Facebook
  • Partager sur Twitter
14 septembre 2019 à 11:20:53

Pour ne pas surcharger, tu aurais pu ne mettre que les propriétés qui étaient impliquées dans les relations utilisées  ;)

Malheureusement, la requête SQL que tu m'as transmise sept messages avant et celle qui est générée par le QueryBuilder m'ont l'air équivalentes, à ceci près que je ne liste pas les champs explicitement et que je n'ai pas mis les clauses de tri, et sous réserve que j'aie loupé un détail. Tu es certain que la requête SQL que tu avais fournie pour exemple fonctionnait comme tu t'y attendais ?

-
Edité par Ymox 14 septembre 2019 à 11:21:15

  • Partager sur Facebook
  • Partager sur Twitter
14 septembre 2019 à 15:15:38

oui j'obtenais les bonnes données... Sérieusement je crois vraiment que le problème c'est doctrine... Une même requête devrait toujours retourner le même résultat... et lorsque j'arrive au paiement ce n'est plus le même résultat. Et oui j'ai déjà vérifier les paramètres qu'elle reçoit.
  • Partager sur Facebook
  • Partager sur Twitter
16 septembre 2019 à 0:21:33

Et tu ne veux évidemment pas tenter toi-même de créer ta requête avec le QueryBuilder histoire de voir comment ça se passe, maintenant que tu sais où aller voir la requête SQL résultante ?

J'ai trop souvent réussi à demander ce que je voulais avec Doctrine pour oser croire que ce soit cette bibliothèque le problème, depuis le temps que celle-ci existe. Et ton cas est au final relativement simple.

  • Partager sur Facebook
  • Partager sur Twitter
16 septembre 2019 à 3:57:03

Ymox a écrit:

Et tu ne veux évidemment pas tenter toi-même de créer ta requête avec le QueryBuilder histoire de voir comment ça se passe, maintenant que tu sais où aller voir la requête SQL résultante ?

C'est déjà ce que j'ai fais non ? À moins que tu parles d'une autre type de requête ?

J'ai trop souvent réussi à demander ce que je voulais avec Doctrine pour oser croire que ce soit cette bibliothèque le problème, depuis le temps que celle-ci existe. Et ton cas est au final relativement simple.

Oui c'est simple ! Et oui je pensais comme toi au début, mais le résultat change lors du paiement. La requête DQL que je t'ai fournis et qu'on a modifier est appeler à 4 endroits différents ! Les 3 premières fois, aucun problème, mais la 4eme fois j'ai des données en trop... Et oui j'ai bien revérifier les paramètres passées et les requêtes faites à MySql... Au début, je pensais que c'était une mauvaise utilisation, mais après avoir relu la doc + demander de l'aide ici et d'avoir essayer des nouvelles façon d'écrire le DQL, j'arrive toujours au même résultat... Donc oui je commence à croire qu'il peut y avoir un bug... D'habitude, avec des problèmes comme ça, on fini par tomber sur une piste après quelques tests... Là c'est vraiment pas le cas.




  • Partager sur Facebook
  • Partager sur Twitter
16 septembre 2019 à 10:48:20

Tu parles d'appel à 4 endroits et de 3 premières fois, ça correspond à quoi ?

Si vraiment bug il y a, quelles sont les autres requêtes pour chacune des trois quatre fois ?

-
Edité par Ymox 16 septembre 2019 à 10:49:09

  • Partager sur Facebook
  • Partager sur Twitter