Oui j'utilise bien var_dump() c'est ainsi que j'ai pu avoir le resultat que je t'ai donné. Le dump() pour ma part n'affiche rien.
Voici la requête SQL :
SELECT b0_.id AS id_0, b0_.identifiant_balise AS identifiant_balise_1, b0_.fonctionnel AS fonctionnel_2, count(b0_.loueur_id) AS sclr_3, b0_.loueur_id AS loueur_id_4 FROM balise b0_ LEFT JOIN location_balise l2_ ON b0_.id = l2_.balise_id LEFT JOIN location l1_ ON l1_.id = l2_.location_id WHERE (b0_.fonctionnel = 1 AND l1_.date_debut_loc NOT IN (?)) OR l1_.date_debut_loc IS NULL GROUP BY b0_.loueur_id
Ok, j'oublie le tableau mais il faut que je récupère toutes les infos pour ensuite les transformer en XML pour les envoyer à mon JS.
- Edité par ElodieMartin13 24 septembre 2019 à 11:05:22
Pour "l'erreur", vu que c'est tronqué, c'est difficile de savoir ce qu'il en est.
Quant au résultat, c'est un peu pareil, c'est tronqué et difficilement exploitable. Mais si je me souviens bien, tu devrais récupérer une liste de paires { 0: objet Balise, sclr_0: le résultat du `count()` } (sans garantie sur la partie sclr_0) mmm non, ç'aurait été correct si on comptait les balises. Il y a probablement cette histoire de paires quelque part, mais du coup j'aimerais bien la version "dans le code HTML" du var_dump() il y a l'indentation) ou le retour de dump() (qui formate de manière similaire, mais qui ne tronque pas).
Je ne vois absolument pas d'où peut venir cet index marker dans le résultat brut de la requête. Tu es certaine de ne pas avoir laissé la boucle de traitement, boucle qu'on va très probablement supprimer ?
Je serais très surpris que Doctrine ne fasse pas le ménage si c'était PDO qui retournait quelque chose du genre, et comme elle a fourni un bout de code dans le premier message qui contenait justement cet index… avec justement la valeur pour cet index, en plus…
Bon, tu pourrais nous fournir un jeu de données d'essai s'il te plaît ? Je vais voir pour une requête et la comparer avec ce que tu as, ensuite de quoi on se préoccupera du format retourné. Sans l'entier de la chose (que tu peux copier-coller comme du code, soit dit en passant), malheureusement, je ne trouve toujours pas cela clair.
OK, merci. Laisse encore le lien jusqu'à demain s'il te plaît.
Edit
Je reprends tout ça à tête reposée, et j'ai encore un peu de peine à comprendre. Tu cherches à compter le nombre de balises possédées par les divers loueurs, ou tu cherches à compter le nombre de loueurs qui ont loué les diverses balises ? Ce n'est clairement pas la même chose, et peut-être que tu n'as pas bien pensé tes relations entre entités.
Je vais partir du principe que tu veux le nombre de Location par Loueur et par Balise, vu que tu as une Many(Balise)ToMany(Location)ToOne(Loueur).
Première étape : récupérer les informations de toutes les balises, de toutes les locations pour ces balises et de tous les loueurs pour toutes ces balises. La requête SQL se présente ainsi :
SELECT
balise.id as balise_id,
loueur.id as loueur_id
FROM
balise
LEFT JOIN
location_balise
ON
location_balise.balise_id = balise.id
LEFT JOIN
location
ON
location.id = location_balise.location_id
LEFT JOIN
loueur
ON
loueur.id = location.loueurs_id
On récupère bien toutes les balises, même celles qui n'ont pas été louées.
Ensuite, on veut compter le nombre de loueurs par balise. On ajoute ce qu'on veut compter, et on n'oublie pas de dire que, comme on veut par balise, on doit regrouper par ID de balise.
SELECT
balise.id as balise_id,
loueur.id as loueur_id,
count(loueur.id) AS nb_loueurs
FROM
balise
LEFT JOIN
location_balise
ON
location_balise.balise_id = balise.id
LEFT JOIN
location
ON
location.id = location_balise.location_id
LEFT JOIN
loueur
ON
loueur.id = location.loueurs_id
GROUP BY
balise.id
Tu as des critères, comme celui de ne vouloir que les balises soit jamais louées, soit louées après une certaine date ? Ajoutons tout ça :
SELECT
balise.id as balise_id,
loueur.id as loueur_id,
count(loueur.id) AS nb_loueurs
FROM
balise
LEFT JOIN
location_balise
ON
location_balise.balise_id = balise.id
LEFT JOIN
location
ON
location.id = location_balise.location_id
LEFT JOIN
loueur
ON
loueur.id = location.loueurs_id
WHERE
location.date_debut_loc >= :dateDebutLoc
OR location.date_debut_loc IS NULL
GROUP BY
balise.id
Avec le jeu de données que tu nous as fourni, utilisons la date du 25 novembre dans la requête. Il y a 42 balises en tout, mais seulement 41 balises sortent avec cette dernière requête pour cette date : la balise 17, louée le 22, n'est effectivement pas dans les résultats. Attention : si tu souhaites que cette balise 17 sorte pour la même date, mais avec un nombre de loueurs de 0, le critère doit être déplacé sur la jointure, et c'est l'utilisation de LEFT JOIN qui fait en sorte de ne plus avoir besoin du critère qui nous permettait de récupérer les balises sans locations :
SELECT
balise.id as balise_id,
loueur.id as loueur_id,
count(loueur.id) AS nb_loueurs
FROM
balise
LEFT JOIN
location_balise
ON
location_balise.balise_id = balise.id
LEFT JOIN
location
ON
location.id = location_balise.location_id
AND location.date_debut_loc = :dateDebutLoc
LEFT JOIN
loueur
ON
loueur.id = location.loueurs_id
GROUP BY
balise.id
Maintenant, générons cette requête avec le QueryBuilder. Je pars du principe qu'on est dans BaliseDialRepository :
<?php
$qb ->createQueryBuilder('bal');
$qb ->leftJoin('bal.locations', 'loc')
->leftJoin('loc.loueurs', 'lou')->addSelect('lou')
->addSelect($qb->expr()->count('lou.id') . ' AS nb_loueurs')
->where($qb->expr()->gte('loc.dateDebutLoc', ':dateDebutLoc'))
->orWhere($qb->expr()->sNull('loc.dateDebutLoc'))
->groupBy('bal.id')
// Et la version avec la contrainte dans la jointure :
$qb ->createQueryBuilder('bal');
$qb ->leftJoin(
'bal.locations',
'loc',
\Doctrine\ORM\Query\Expr\Join::WITH,
$qb->expr()->gte('loc.dateDebutLoc', ':dateDebutLoc')
)
->leftJoin('loc.loueurs', 'lou')->addSelect('lou')
->addSelect($qb->expr()->count('lou.id') . ' AS nb_loueurs')
->groupBy('bal.id')
Bump, j'avais mis à jour ci-dessus au cas où. La seule chose qu'il faudra encore regarder, c'est la structure des résultats. Utilise dump(), tu pourras avoir un affichage un peu plus "pratique" (cf. la doc) en allant regarder les informations de débogage pour la requête.
J'ai eu un we bien chargé du coup je n'ai pas pu regardé tout cela avant. Je te remercie d'avoir pris le temps d'y penser. En fait, faut que j'arrive à faire la meme chose mais avec la table balise et pas location. Il faut que je trouve toutes les balises qui ne sont pas louées à une date donnée puis que je les regroupe par loueur afin de connaitre son stock à une date donnée.
Le résultat que je devrais avoir doit être (en ne prenant que les balises fonctionnelles) :
Id Loueur : 19 - 17 - 68 - 69 - 67 - 18- 20
Nb : 3 - 5 - 5 - 6 - 3 - 6 - 5
En requête SQL voici ce qu'il faudrait que j'obtienne :
SELECT bal.loueur_id, lou.nom, lou.adresse, lou.cp, lou.ville, count(bal.id) AS nb_balise
FROM location_balise lbd
RIGHT JOIN location loc ON loc.id = lbd.location_id
RIGHT JOIN balise bal ON bal.id = lbd.balise_id
RIGHT JOIN loueur lou ON lou.id = bal.loueur_id
WHERE bal.fonctionnel = true
AND loc.date_debut_loc NOT IN ("2019-10-05")
OR loc.date_debut_loc IS NULL
GROUP BY bal.loueur_id
Par contre le WHERE ne fonctionne pas, et pour la date de location, ca fonctionne une fois sur deux.
Par exemple la location du 05/10/2019 est pour le loueur 68 et la requête me l'a enlevé au loueur 18
- Edité par ElodieMartin13 24 septembre 2019 à 11:13:30
Je ne comprends pas ce NOT IN ('2019-10-05'). Tu exclus complètement ce qui se serait passé le 5 mai, mais donc inclus tout ce qu'il y aurait eu avant et après, tu es sûre que c'est ce que tu souhaites ?
Ta colonne nom dans le résultat que tu nous affiches, c'est le nom du "propriétaire" de la balise ou du loueur ? Dans le second cas, c'est normal que ce ne soit pas celui que tu attends, dans la mesure où, comme tu regroupes par loueur, ce sera le nom de l'un ou l'autre loueur.
Maintenant, ce passage est complètement différent de ce que j'avais compris (et heureusement que je demandais précision) :
ElodieMartin13 a écrit:
Il faut que je trouve toutes les balises qui ne sont pas louées à une date donnée puis que je les regroupe par loueur afin de connaitre son stock à une date donnée.
.
Je reviens d'ici cet après-midi pour mettre la réflexion.
Le hic, c'est que tu parles de loueur en tant qu'entité (et c'est OK qu'il n'en faut qu'une, seulement peut-être que le nom n'est pas super bien choisi), et ça peut être le loueur qui a fait une location comme le loueur qui "possède" la bouée, et actuellement, je ne suis toujours pas sûr duquel tu parles.
Un utilisateur fait une location auprès d'un loueur. Ce loueur possède un certains nombres de balises. Certaines sont dispo, d'autres sont louées et certaines ne sont plus fonctionnelles. Afin de pouvoir proposer un loueur à un particulier, j'ai besoin de connaître son stock de balises dispo (donc fonctionnelles et non louées à la date donnée).
OK, donc cette entité Loueur pourrait être nommée plutôt Utilisateur, ainsi un utilisateur possède des balises (en fait, vu que tu as une OneToOne dans ce cas, un utilisateur ne peut posséder qu'une seule balise) et loue d'autres balises, la différence se faisant au niveau des propriétés pour les relations
Tu as vraiment une table balise ? Elle n'apparaît pas dans le SQL que tu nous as fourni…
Edit
Après, peut-être qu'un loueur est un terme précis pour la société pour laquelle tu travailles, je ne sais pas, je suis Suisse
En fait, j'ai d'autres Entités, j'ai une entité utilisateur, une loueur, une balise et une location.
Alors un utilisateur prend une location auprès d'un loueur.
Un Loueur possède une ou plusieurs balise.
Une location est faite par un utilisateur auprès d'un seul loueur et peut concerner une ou plusieurs balise
EDIT : Voici ma requête SQL qui fonctionne ! Tu pourrais me l'écrire en DQL stp !
SELECT
*, count(bal_ok.balid)
FROM (SELECT
lou.id AS Louid,
lou.nom,
lou.cp,
lou.ville,
loc.date_debut_loc,
bal.id AS balid,
bal.fonctionnel
FROM
loueur lou
LEFT JOIN balise bal ON
lou.id = bal.loueur_id
LEFT JOIN location_balise lbd ON
bal.id = lbd.balise_id
LEFT JOIN location loc ON
loc.id = lbd.location_id
WHERE
bal.fonctionnel = TRUE
) AS bal_ok
WHERE
bal_OK.date_debut_loc NOT IN("2019-09-22") OR bal_OK.date_debut_loc IS NULL
GROUP BY bal_ok.louid
- Edité par ElodieMartin13 24 septembre 2019 à 11:13:55
Oublie pas d'enlever le lien vers ton jeu de données d'exemple
Et maintenant patience. Il faut "retourner" la requête vu que Doctrine ne connaît pas RIGHT JOIN. Pour l'instant, je ne vois pas trop comment faire, mais peut-être que d'ici-là, quelqu'un pourra expliquer.
J'oublie que mon avatar actuel le mentionne clairement
@ElodieMartin13 : il y a d'autres endroits que mon message et ton jeu de données d'essai où il est fait mention du nom que tu m'as demandé de cacher, à toi de repasser sur les messages pour les modifier en cas de besoin.
D'autre part, le souci est probablement que tu dois mettre des parenthèses autour des deux contraintes sur la date, cf. ce message
Alors comme tu as cité/repris certaines de mes requêtes, tu as aussi des trucs à y revoir
Maintenant, le résultat est comme je m'y attendais. Tu as un tableau contenant à l'indice 0 l'objet Loueur, et à l'indice nb_balises le nombre de balises. A voir si tu souhaites sérialiser différemment, ou si cette structure te convient. Au final, c'est juste un niveau en plus
A noter que maintenant, on pourrait se pencher sur la pertinence de récupérer toutes les informations des objets Loueur, et tu pourrais au besoin utiliser la syntaxe select('PARTIAL lou.{id,…}') où tu remplaces les points de suspension par les noms des propriétés qui t'intéressent (sans espace autour des virgules).
Ah cool ! justement j'étais en train de chercher comment ne pas tout récupérer...
Concernant la structure en fait c'est pas important car il faut que je prenne tout celà et que je crée un nouveau tableau au format XML avec des markers pour que mon JS puisse le lire.
De deux choses l'une : soit tu adaptes ton JavaScript pour qu'il puisse lire la structure actuelle, soit tu remets la boucle que tu avais précédemment en prenant compte de la structure du résultat de la requête.
En ce qui me concerne, j'adapterais le JavaScript et j'enverrais du JSON plutôt que du XML
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Keep It Simple Stupid - SF4 conf Swift - Cours 1/4 SF4 - Exceptions PDO - Formes Normales
Keep It Simple Stupid - SF4 conf Swift - Cours 1/4 SF4 - Exceptions PDO - Formes Normales
Keep It Simple Stupid - SF4 conf Swift - Cours 1/4 SF4 - Exceptions PDO - Formes Normales