C'est parce qu'il faut mettre un antislash devant, sinon il cherche dans l'espace de nom courant, (Il me semblait pourtant qu'il remontait automatiquement jusqu'à la racine en cas de besoin…)
Tu ne peux pas modifier cette requête, c'est Doctrine qui s'occupe de la générer quand tu effectues persist($location); flush(). Comme l'ordre importe peu, il faudra plus se concentrer sur le fait qu'apparemment il y a une valeur mal renseignée dans ton objet.
Alors il ne me récupère pas le nombre de balises louées, est-ce que cela vient du fait que j'ai fait un input normal au lieu de prendre celui de Twig ?
J'ai fait un input normal car j'avais besoin de lui donner un name pour récupérer l'information et la comparer à la valeur que je récupère avec ma requête.
Apparement il ne récupère pas l'id du loueur que je sélectionne. Ce qui est normal vu que je ne l'ai pas géré.
Je crée ma liste en js de cette façon :
function choiceList() {
var table = document.getElementById("liste");
for (var k = 0; k < listeObjects.length; k++) {
var id = listeObjects[k].id;
var nom = listeObjects[k].nom;
var cp = listeObjects[k].cp;
var ville = listeObjects[k].ville;
var distance = listeObjects[k].distance;
var nbDispo = listeObjects[k].nb;
var row = table.insertRow(k);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
cell1.innerHTML = '<input type=radio name=choiceLoueur[] id=choiceLoueur value=' + id + '>';
cell2.innerHTML = '<label for=' + id + '>' + nom + '<br>' + cp + ' ' + ville + ' - ' + nbDispo + ' dispo' + '<br></label>';
}
}
Et dans mon twig :
<table >
<tbody id="liste">
</tbody>
</table>
Je dois gérer ou la selection ?
Et pour la valeur du dernier élément, elle s'incrémente toute seule donc j'en déduis que c'est bien l'id de l'utilisateur
- Edité par ElodieMartin13 2 octobre 2019 à 14:13:12
Alors il ne me récupère pas le nombre de dial loués, est-ce que cela vient du fait que j'ai fait un input normal au lieu de prendre celui de Twig ?
Oui. Le nom donné par Symfony au champ de formulaire est prévu pour pouvoir récupérer correctement la donnée lors de handleRequest(). Il vaudrait mieux que tu adaptes ton JavaScript à ce nom qu'adapter le HTML à ton JavaScript.
Juste une chose : quand tu vois qu'il y a eu des réponses après que tu aies édité ton message pour ajouter des informations, supprime-les du message que tu as édité et mets-les dans une nouvelle réponse, c'est pas facile de suivre ensuite — surtout si tu changes carrément la réponse, auquel cas il faudrait revenir au message tel qu'il était avant qu'on lui réponde…
ElodieMartin13 a écrit:
Je viens de remarquer que la requête enregistre l'id du client mais je n'ai pas vu de paramètres pour les infos du client.
Si c'est un client existant pour la location, ça me paraît normal, un client est représentable par son ID, c'est d'ailleurs ce qui est utilisé par Doctrine pour les relations entre entités.
Si en revanche c'est pour un nouveau client, attention, le traitement devra être différent.
ElodieMartin13 a écrit:
Est-ce que je dois faire un truc comme ca ?
Pas nécessairement. Si tu ne souhaites pas devoir mettre à la main $location->setDateDebutLoc(…) et ainsi de suite pour chaque champ du formulaire (ce qui pourrait être la solution la plus simple, mais pas celle qui utiliserait tirerait le plus parti des outils de Symfony), oui, il faudrait faire un truc comme ça. Seulement, il faudra que les données de la requête soient envoyées "avec la bonne architecture".
Oui ce sont de nouveaux clients. Le système n'a pas été pensé pour des clients existants étant donné qu'il n'y a pas d'enregistrement de clients ni de système de connexion à un espace client.
Comment doit être fait le traitement ?
Et dans le cas ou je souhaite utiliser les outils de symfony comme j'ai fait pour créer une nouvelle location. Comment je fais pour créer un nouvel utilisateur ? Je pensais que ca se ferait tout seul étant donné que j'ai inclu l'utilisateur dans le formulaire location. C'est un formulaire qui inclu deux entités.
Le hic, c'est que le formulaire qui est généré par Symfony puis affiché avec Twig possède des attributs name précis, faisant que lors de la soumission les données sont structurées d'une manière proche de celle qu'on rencontrerait avec les objets, mais là sous forme de tableau. Et c'est sur cette structure que handleRequest() se base pour effectuer la liaison des données de la requête avec "l'entité mère".
Dans l'idéal, plutôt que de récupérer les valeurs de champs une à une, sérialise l'entier du formulaire. Tu trouveras des méthodes sur cette page notamment. Une autre version pour soumettre un formulaire par AJAX est disponible ici.
EDIT : Alors on reprend tout car en fait j'ai rien compris.
Le serializeArray() si je comprends bien c'est pour renvoyer sous forme de tableau les valeurs d'un form sous Ajax.
Sauf que la valeur que je veux récupérer en JS n'est pas dans un formulaire mais dans un simple input.
function choiceList() {
var table = document.getElementById("liste");
for (var k = 0; k < listeObjects.length; k++) {
var id = listeObjects[k].id;
var nom = listeObjects[k].nom;
var cp = listeObjects[k].cp;
var ville = listeObjects[k].ville;
var distance = listeObjects[k].distance;
var nbDispo = listeObjects[k].nb;
var row = table.insertRow(k);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
cell1.innerHTML = '<input type=radio name=choiceLoueur[] id=choiceLoueur value=' + id + '>';
cell2.innerHTML = '<label for=' + id + '>' + nom + '<br>' + cp + ' ' + ville + ' - ' + nbDispo + ' dispo' + '<br></label>';
}
}
J'en doute, serializeArray() ne va pas générer la bonne structure, c'est vraiment serialize() qui serait le plus adapté. Mais tout ça c'est uniquement si tu as un formulaire pour ton client.
A mon tour de ne plus te suivre. Tu nous parles de formulaire, mais « la valeur que je veux récupérer en JS n'est pas dans un formulaire mais dans un simple input ». Tu as une liste de clients, mais tu veux en saisir un nouveau.
La partie haute et basse est gerée par le builder. La partie centrale est gérée par le JS. Il faut que je récupère l'id du bouton radio et que je le fasse passer au handleRequest() pour persister la donnée en base.
C'est plus clair ?
- Edité par ElodieMartin13 3 octobre 2019 à 17:00:21
OK, alors la possibilité la plus simple que je verrais serait d'adapter ton JavaScript qui insère ces boutons radio pour avoir le name correct — si tu as besoin d'aide à ce propos, il nous faudra celui de heureDebutLoc par exemple — et tu soumets en AJAX le formulaire.
Ce n'est pas une bonne pratique de faire ainsi. Comment récupères-tu l'ID du loueur à mettre dans ton formulaire ? Ne pourrais-tu pas le récupérer de la même manière pour l'ajouter à l'entité une fois que le formulaire est soumis et validé, sans qu'il ne re-transite par le client ? Parce que justement, ça fait une donnée de plus à vérifier si c'est la bonne. Or, si cette donnée est en session, mieux vaut l'enregistrer "au dernier moment". Si l'utilisateur peut la choisir, pourquoi ne pas permettre de le faire sur la même page ?
C'est probablement normal, il doit y avoir des éléments qui ont besoin de certaines informations lorsque la page est générée. Il nous faudrait l'entier du code qui fait s'afficher la page du formulaire pour mieux expliquer. Et si ton entité utilisateur est liée d'une manière ou d'une autre aux balises, peut-être que c'est une des explications.
Comment récupères-tu l'ID du loueur à mettre dans ton formulaire ?
La récupération de l'id Loueur est faite à la fin de la fonction choiceList(), premier code de mon message précédent.
Ne pourrais-tu pas le récupérer de la même manière pour l'ajouter à l'entité une fois que le formulaire est soumis et validé, sans qu'il ne re-transite par le client ?
Ce que j'ai voulu faire, c'est récupérer l'id du Loueur puis je l'ai transmis grâce au getElementById au champ du formulaire Twig que j'ai mis en caché.
Si l'utilisateur peut la choisir, pourquoi ne pas permettre de le faire sur la même page ?
L'utilisateur choisit le loueur en cochant le bouton radio et tout se fait sur la meme page.
Il nous faudrait l'entier du code qui fait s'afficher la page du formulaire pour mieux expliquer.
Une des requêtes vient du fait que le EntityType "caché" (en CSS — pour moi un champ caché c'est un type="hidden") doit être rempli de la liste complète des loueurs.
Attention : pour la valeur d'un <input />, c'est l'attribut value de la balise auto-fermante qui est utilisé, pas un texte placé entre les balises ouvrante et fermante comme tu l'illustres. Après, peut-être que c'est une manière de ton navigateur pour afficher ça, mais c'est trompeur.
Je ne comprends pas pourquoi il faut un champ caché pour l'ID du loueur. Si tu as des boutons radio avec les bons attributs name (ce qui semble être le cas), pas besoin d'aller mettre la valeur dans un autre champ. C'est certes un peu moins pratique pour aller chercher la valeur choisie, mais il n'y a pas besoin de recréer un champ supplémentaire alors que, quel que soit son type, s'il existe au moins un champ avec le même name, il est considéré comme existant déjà, et la dernière valeur remplacera la première — sauf en cas de champ où plusieurs valeurs sont possibles.
J'ai cru comprendre que la liste des loueurs s'affichait dynamiquement. J'imagine que tu souhaites qu'elle soit vide tant que tu n'as pas choisi les dates et heures de location ?
Dans ce cas, je te propose de changer quelques paramètres de ton EntityType pour les loueurs : on va lui mettre 'expanded' => true pour avoir toute une liste des loueurs sous forme de case à cocher (il faudra déplacer ce "champ caché" là où tu as mis tes boutons radio). En JavaScript, quand mets l'écouteur d'événements sur le click du bouton SEARCH (oui, avant l'événement et non uniquement dedans), tu vas supprimer toutes ces cases à cocher qui seront par défaut affichées. Le reste va se comporter de la même manière que maintenant, à ceci près que tu pourras récupérer le choix directement depuis les boutons radio.
Pour l'instant, à chaque erreur, le formulaire se réaffichera avec la liste complète des loueurs, mais le choix sera conservé. A voir quel comportement tu souhaites, suivant comment on va devoir passer par un FormEventListener pour conserver la liste restreinte.
La liste de l'affichage dynamique est vide à l'affichage du formulaire. Par contre l'id loueur il y a 3 loueurs alors que la liste en contient plus de 200 et il y a un doublon. Dois-je faire tout ce que tu expliques dans ton dernier paragraphe du coup ?
Si j'ai rajouté le champs twig id Loueur c'est parce que je me suis aperçue que même en donnant le même name et le même id que Twig, la requête ne prenait pas la valeur en compte (test fait sur le champs nb de balise).
Attention : pour la valeur d'un <input />, c'est l'attribut value de la balise auto-fermante qui est utilisé, pas un texte placé entre les balises ouvrante et fermante comme tu l'illustres. Après, peut-être que c'est une manière de ton navigateur pour afficher ça, mais c'est trompeur.
J'utilise chrome en navigateur. Du coup ca signifie qu'il n'est pas récupéré ? Je pensais que si vu que la valeur change chaque fois que je clic mais tu dois avec raison puisque la requête considère la valeur null ! Du coup qu'est ce qui ne va pas dans mon code ?
- Edité par ElodieMartin13 7 octobre 2019 à 12:53:55
En fait, tu as besoin du champ loueur avec EntityType, sans quoi Symfony ne pourra effectivement pas lier la demande de location avec le loueur correctement. Seulement, avec ce que tu as, je serais plus pour l'utiliser un peu différemment que ce que tu fais actuellement, et oui, je te propose l'avant-dernier paragraphe du message précédent, premier de la dernière section.
Pour ce qui est de l'affichage de la valeur et du navigateur, cela explique très probablement que celle-ci n'est pas récupérée. Attention cependant : je ne crois pas qu'il y ait de navigateur qui mette à jour ce qu'on voit quand on change la valeur d'un champ, on ne peut donc pas se baser là-dessus.
En fait, tu as besoin du champ loueur avec EntityType, sans quoi Symfony ne pourra effectivement pas lier la demande de location avec le loueur correctement. Seulement, avec ce que tu as, je serais plus pour l'utiliser un peu différemment que ce que tu fais actuellement,
Faire différement c'est à dire ?
Pour ce qui est de l'affichage de la valeur et du navigateur, cela explique très probablement que celle-ci n'est pas récupérée.
[…] je te propose l'avant-dernier paragraphe du message précédent, premier de la dernière section.
Je note cependant à l'instant que tu as les attributs qui contiennent loueurs au pluriel. Si tu as bien une relation *(Location)ToMany(Loueur), il nous faudra encore autre chose. Si non, c'est là qu'on peut voir que les pluriels inutiles ne sont pas de très bonnes idées.
ElodieMartin13 a écrit:
Une idée d'ou vient le problème dans mon code ?
Probablement de ce que tu ajoutes des balises <option> à une balise <input>, en fait. Ce qui explique aussi que la valeur se retrouve comme un nœud dans la balise <input>.
Alors pour le pluriel je plaide coupable, j'avais mis une relation manyToMany alors que c'était un OneToMany, du coup il reste peut être des erreurs.
En fait on ne peut louer une balise qu'à un seul loueur.
Suite aux changement que tu m'as dit, voici le résultat. (J'ai mis le champ censé être en caché en visible pour les tests) Il y a bien une liste, mais c'est toujours la même.
Voici mon entityType si j'ai bien compris ce que tu m'as dis :
Ça ne te gêne pas de dire que ton champ Location#loueur contient des locations ? C'est pourtant ce que tu dis avec la seconde ligne… Le paramètre 'class' est pour dire quelle entité sera utilisée par le champ, pas par le formulaire dans lequel se trouve ledit champ.
Le champ caché que tu as mis en visible, dans mon idée, il devrait remplacer la liste que tu as à côté de la carte. Plus besoin de le cacher ni de le remplir avec du JavaScript, vu que la valeur est déjà choisie par l'utilisateur par le biais des boutons radio.
Ça ne te gêne pas de dire que ton champ Location#loueur contient des locations ? C'est pourtant ce que tu dis avec la seconde ligne… Le paramètre 'class' est pour dire quelle entité sera utilisée par le champ, pas par le formulaire dans lequel se trouve ledit champ.
Ben je crois que l'on est sur la même longueur d'onde. J'ai voulu dire "l'attribut loueur" que l'on trouve dans l'entité "Location".
Et vu que j'ai mis un OneToOne, une location a un seul loueur.
Tu sais quoi ? Tu m'as encore perdue du coup !
Le champ que j'ai mis en caché ne comporte que l'id du Loueur.
La liste que j'ai sur le côté comporte les boutons radios, donc si je l'enlève pour ne laisser que le champ id Loueur, mon utilisateur ne pourra plus faire de choix
le code de l'entité Location que tu mentionnes ci-dessus (où tu dis avec les mappings targetEntity="App\Entity\Loueur" que la propriété Location#loueur est un objet Loueur)
et le code de LocationType (code que j'ai cité deux messages plus haut, et où tu dis avec le paramètre 'class' => App\Entity\Location::class que la même propriété va contenir un objet Location)
il y a quelque chose qui ne joue pas.
Mais il y a autre chose qui doit m'échapper. Les deux fois tu fournis un affichage avec la liste des balises et la carte, et tu dis que ça s'affiche après la sélection d'un loueur. Il n'y a donc pas que le choix des dates et heures de début et de fin de location qui influe sur la liste de balises, il y a aussi un choix de loueur, et ici par loueur on ententd propriétaire de balise ?
Je crois qu'il me faudrait que tu réexpliques en français non technique ce que l'utilisateur doit pouvoir faire/ce qu'il doit se passer.
Comme si tu parlais à quelqu'un qui ne connaît rien à PHP ni en HTML.
Merci d'être si patient. J'ai compris que j'avais mal compris à quoi servait le paramètre class. Je croyais qu'il fallait que je lui dise à quelle entité il appartenait alors que je devais lui dire à quelle entité il renvoyait.
Du coup maintenant l'enregistrement de la location et de l'utilisateur se fait bien en base. Il manque une dernière chose, c'est lorsque je choisis le loueur, il faut que je liste les balises disponibles et fonctionnelles du loueur et que le système en attribue le nombre demandé par l'utilisateur.
Ça, c'est un peu plus complexe à mon avis. Je vois deux possibilités :
au choix d'un loueur, tu lances une nouvelle requête AJAX qui te retourne les informations des balises, et tu génères la carte à ce moment-là ;
quelque part dans les attributs du bouton radio ou du <label>, on met les informations sur les balises sous forme de JSON, mais ça implique de les avoir déjà lors du rendu des boutons radio, avec tout ça je ne sais plus si c'est le cas.
Edit
Pour ce qui est de l'attribution, ça devrait se passer comment ? On prend ce qu'il y a de libre tant qu'il y en a, et c'est tout, ou il y a un processus plus subtil ?
Choix 1 : La carte doit s'afficher au moment ou la liste apparait afin que l'utilisateur puisse visualiser l'emplacement des différents loueurs et faire un choix. Une fois que le choix a été fait la carte n'a plus d'utilité.
L'attribution des balises doit passer inapercu pour l'utilisateur.
Choix 2 : Dans la requête on a récupéré l'id des balises puisqu'on les compte mais ensuite on regroupe par loueur, du coup je ne sais pas si les id sont conservés.
Pour l'attribution il n'y a pas de règle spécifique, on prend une balise libre et fonctionnelle dans la liste. Et on en attribut autant que l'utilisateur en a loué. Puis on l'enregistre en base de données.
- Edité par ElodieMartin13 8 octobre 2019 à 14:05:50
OK, donc ce ne sont pas les balises qui s'affichent, mais les loueurs, j'avais mal compris.
Du coup, cette histoire de répartition peut se faire dans le contrôleur, après validation du formulaire et avant persistance de la location. Tu récupères les balises du loueur, tu boucles dessus autant de fois que souhaité et tu as de quoi attribuer. Pour la requête, elle sera très similaire à ce que tu as déjà fait pour avoir les loueurs libres et leur nombre, simplement il n'y aura plus de regroupement par loueur et tu as l'ID de ce dernier comme paramètre supplémentaire.
Question cependant : le nombre de balises, si le loueur n'en a pas assez, tu fais comment ? Actuellement tu filtres quand même pour n'afficher que les loueurs qui ont assez de balises libres, ou non ? Si oui, tu filtres à quel moment/par quel moyen ?
Je gère la vérification de la quantité dans mon js, et seuls les loueurs ayant assez de quantités disponibles apparaissent dans la liste avec les boutons radios.