[RESOLU] problème de SELECT

Eléphant du PHP | 345 Messages

27 juin 2021, 19:17

J'ai mis cela ainsi, mais dans mes tests, ça n'affiche qu'un seul avatar (le dernier au niveau du id)
<?php
require_once 'config.php';
$id = !empty($_SESSION['id']) ? $_SESSION['id'] : NULL;
$sql = "SELECT pos_x, pos_y FROM membres WHERE id=:id";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);
$pdostat->execute();
$resultat = $pdostat->fetch();    
if (!empty($resultat )) { 
$pos_x = $resultat['pos_x'];
$pos_y = $resultat['pos_y'];
}
$sql = "SELECT avatar FROM membres WHERE pos_x=pos_x AND pos_y=pos_y";
$pdostat = $bdd->prepare($sql);
$pdostat->execute();
while ($resultat = $pdostat->fetch())
{ 
//if (!empty($resultat )) { 
$avatar = $resultat['avatar'];
}
echo '<img src="'.$avatar.'">';  
?>

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

28 juin 2021, 16:49

Un programme informatique en général est assez bête et ne fait que ce que tu lui demandes. Dans ce dernier code, tu lui demandes dans une boucle, de lire tous les avatars retournés pas ta requête. Il va donc bien les lire puis sortir de la boucle sans rien faire de plus.

Puis tu lui indiques qu'une fois qu'il a terminé de tout lire et qu'il a quitté la boucle, d'afficher l'image correspondante. PHP affiche donc la dernière valeur connue de $avatar et ne le fait qu'une seule fois puisqu'il a fini sa boucle ;)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 345 Messages

28 juin 2021, 18:27

Expliqué ainsi, oui je comprends mieux mais je ne vois pas ce qu'il faut rajouter pour que le script affiche tous les avatars :oops:
Peut-etre mettre le echo DANS la boucle?

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

28 juin 2021, 18:30

Si tu veux afficher tous les avatars, alors il faut mettre la ligne de code qui fait l'affichage dans ta boucle pour l'appeler autant de fois qu'il y a d'avatars.
Quand tout le reste a échoué, lisez le mode d'emploi...

Eléphant du PHP | 345 Messages

28 juin 2021, 18:36

Merci messieurs, ma logique de codage a encore été calamiteuse :roll:
<?php
require_once 'config.php';
$id = !empty($_SESSION['id']) ? $_SESSION['id'] : NULL;
$sql = "SELECT pos_x, pos_y FROM membres WHERE id=:id";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);
$pdostat->execute();
$resultat = $pdostat->fetch();    
if (!empty($resultat )) { 
$pos_x = $resultat['pos_x'];
$pos_y = $resultat['pos_y'];
}
$sql = "SELECT avatar FROM membres WHERE pos_x=pos_x AND pos_y=pos_y ";
$pdostat = $bdd->prepare($sql);
$pdostat->execute();
while ($resultat = $pdostat->fetch())
{
$avatar = $resultat['avatar'];
echo '<img src="'.$avatar.'">';  
}
?>

Mammouth du PHP | 2703 Messages

28 juin 2021, 19:20

$sql = "SELECT avatar FROM membres WHERE pos_x=pos_x AND pos_y=pos_y ";
ça fait ce qui est attendu ? à savoir, afficher les membres qui ont la même position que le membre connecté ?

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

28 juin 2021, 19:25

C'est de l'algorithmie et ça s'apprend aussi, indépendamment du langage que tu utilises pour coder.

Désormais, tu demandes bien à php de boucler sur tous les éléments retournés par ta requête et pour chacun d'eux, de lire l'élément et l'affecter à la variable $avatar, puis d'afficher le contenu de cette variable, concaténé à une chaine de caractère :)

Tu peux aussi prendre l'habitude d'indenter ton code, c'est à dire de décaler les lignes d'une tabulation vers la droite à chaque fois que tu ouvres des accolades (et de retirer une tabulation quand tu les refermes). Cela rend le code plus lisible et te permet potentiellement d'identifier plus rapidement que ton instruction n'est pas placée où il faut ;)
<?php
require_once 'config.php';
$id = !empty($_SESSION['id']) ? $_SESSION['id'] : NULL;
$sql = "SELECT pos_x, pos_y FROM membres WHERE id=:id";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);
$pdostat->execute();
$resultat = $pdostat->fetch();    
if (!empty($resultat )) { 
    $pos_x = $resultat['pos_x'];
    $pos_y = $resultat['pos_y'];
}
$sql = "SELECT avatar FROM membres WHERE pos_x=pos_x AND pos_y=pos_y ";
$pdostat = $bdd->prepare($sql);
$pdostat->execute();
while ($resultat = $pdostat->fetch())
{
    $avatar = $resultat['avatar'];
    echo '<img src="'.$avatar.'">';  
}
?>
Et maintenant que tu as identifié les éléments qui te posaient problème, tu pourras à l'occasion essayer d'optimiser ton code en ne faisant qu'une seule requête comme tu l'envisageais au départ ;)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 345 Messages

29 juin 2021, 00:33

@ Or, oui, j'obtiens bien ce que je souhaitais.
@ Ryle, ok pour mieux indenter le code.

Je reviendrais surement sur la suite à donner à ce script car il y a encore un truc assez costaud que je souhaite mettre en place.

Eléphant du PHP | 345 Messages

30 juin 2021, 10:25

Je me suis gourré dans mes tests. le script ne va pas car il affiche TOUS les avatars, quelque soient leur position.... :oops:
J'ai modifié la seconde requête de cette façon mais ça ne va toujours pas.
<?php
require_once 'config.php';
$id = !empty($_SESSION['id']) ? $_SESSION['id'] : NULL;
$sql = "SELECT pos_x, pos_y FROM membres WHERE id=:id";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);
$pdostat->execute();
$resultat = $pdostat->fetch();    
if (!empty($resultat )) 
     { 
     $pos_x = $resultat['pos_x'];
     $pos_y = $resultat['pos_y'];
     }
$sql = "SELECT * FROM membres WHERE (pos_x=pos_x AND pos_y=pos_y) =:id";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);
$pdostat->execute();
while ($resultat = $pdostat->fetch())
     {
     $avatar = $resultat['avatar'];
     $pseudo = $resultat['pseudo'];
     echo '<a href="affiche_perso.php"><img src="'.$avatar.'"></a>'; 
     echo $pseudo;
     }
?>


Eléphant du PHP | 345 Messages

30 juin 2021, 11:03

Ouf, ça semble à présent correct !
<?php
require_once 'config.php';
$id = !empty($_SESSION['id']) ? $_SESSION['id'] : NULL;
$sql = "SELECT pos_x, pos_y FROM membres WHERE id=:id";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);
$pdostat->execute();
$resultat = $pdostat->fetch();    
if (!empty($resultat ))
      { 
     $pos_x = $resultat['pos_x'];
     $pos_y = $resultat['pos_y'];
     }
$sql = "SELECT * FROM membres WHERE pos_x=$pos_x AND pos_y=$pos_y";
$pdostat = $bdd->prepare($sql);
$pdostat->bindvalue(':id',$id ,PDO::PARAM_INT);
$pdostat->execute();
while ($resultat = $pdostat->fetch())
     {
     $avatar = $resultat['avatar'];
     $pseudo = $resultat['pseudo'];
     echo '<a href="affiche_perso.php"><img src="'.$avatar.'"></a>'; 
     echo $pseudo;
     }
?>


Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

30 juin 2021, 11:47

Il y a quelques problèmes avec ce code à mon sens.

Le premier, c'est que si $resultat est vide, les variables $pos_x et $pos_y ne seront pas déclarées, et la seconde requête ne pourra pas fonctionner. Il faudrait à mon sens mettre tout le code qui suit dans le if() puisque si pas de résultat, il n'y aura de toute façon pas d'avatar à afficher. Ou s'il y a forcément un résultat parce que l'utilisateur "id" est forcément quelque part, le if() ne sert à rien ;)

Le deuxième problème concerne la construction de la deuxième requête. Comme évoqué précédemment par @rthur, il ne faut pas mettre de variables php dans la construction d'une requête préparée. Ça n'est ni propre, ni sécurisé. Pour passer des valeurs à une requête préparée, on utilise un flag dans la requête, et on passe la valeur associée à ce flag avec un bind ou lors de l'exécution. C'est ce que tu fais correctement pour la première requête.
En revanche pour la seconde, tes variables sont en dur dans ta requête et si tu fais bien un bindvalue, tu donnes une valeur pour le flag :id qui n'existe pas dans cette requête :)
$sql = "SELECT * FROM membres WHERE pos_x=:x AND pos_y=:y"; // pas de variable $pos_x/y, mais des flag :x et :y
...
$pdostat->bindvalue(':x',$pos_x ,PDO::PARAM_STR); // pour chaque flag, on associe la valeur que l'on veut utiliser
$pdostat->bindvalue(':y',$pos_y ,PDO::PARAM_STR);
Et enfin, je pense que tu vas avoir des problèmes avec ton lien qui ouvre toujours la même page quel que soit l'avatar spécifié, il te faudra sans doute récupérer un identifiant pour savoir sur quel avatar l'utilisateur a cliqué, mais j'imagine que c'est en cours ;)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Eléphant du PHP | 345 Messages

16 juil. 2021, 14:40

La seconde requete a été modifiée ainsi:
$sql = "SELECT * FROM membres WHERE (pos_x=$pos_x AND pos_y=$pos_y) AND id!=:id";
et je bind ensuite sur id