[RESOLU] Récupérer une seule donnée d'une requête SQL

Eléphanteau du PHP | 17 Messages

21 août 2014, 15:07

Bonjour,

Je suis entrain de créer un site internet mais à un moment je dois traiter les informations des utilisateurs pour qu'ils puissent se connecter. (pour créer leurs comptes il n'y a pas de problème mais c'est juste pour se connecter). Le problème d'après moi viendrait des lignes suivante :
$resultat = $bdd->query('SELECT pseudo, pass, email, adresse, ville, postal, pays FROM membres WHERE pseudo=\''.$pseudo.'\' ');
			while ($donnes = $resultat->fetch())
Car là ça fait que je récupérer les réponse de la requête SQL et que pour chaque passage ça regarde si le pseudo entré == pseudo qui est dans la bdd et de même avec le mdp. Mais le problème c'est que le while est exécuté pour tout les pseudos de la bdd donc le if renverra false donc on passera au else qui stoppera la requête SQL car on sera renvoyé sur une nouvelle page alors que tout les pseudos de la bdd n'ont pas été vérifié. J'aimerais savoir comment récupéré un seul résultat d'une requête SQL (et si possible que ça ne soit pas un array :cry: )
<?php
try
{
	$bdd = new PDO('mysql:host=localhost;dbname=IATF', 'root', '', array (PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
}
 catch (Exception $e)
{
       die('Erreur : ' . $e->getMessage());
}
session_start();

	// On récupére les informations envoyé.
			$pseudo = htmlspecialchars($_POST['pseudo']);
			$pass = htmlspecialchars($_POST['pass']);
		// On fait une requête SQL pour vérifier les données du pseudo entré.
			$resultat = $bdd->query('SELECT pseudo, pass, email, adresse, ville, postal, pays FROM membres WHERE pseudo=\''.$pseudo.'\' ');
			while ($donnes = $resultat->fetch())
	{
		// On demande si le pseudo et le mot de passe existe dans la bdd.
			if ($pseudo == $donnes['pseudo'] AND $pass == $donnes['pass']) 
		{
		// connection réussie !
			// On donne les données nécessaire pour la section profil.
				$_SESSION['pseudo'] = $pseudo;
				$_SESSION['email'] = $donnes['email'];
				$_SESSION['adresse'] = $donnes['adresse'];
				$_SESSION['ville'] = $donnes['ville'];
				$_SESSION['postal'] = $donnes['postal'];
				$_SESSION['pays'] = $donnes['pays'];
			// On redirige vers l'accueil.
				header('Location: index.php');
		}
			else
		{
		// pseudo ou mot de passe incorect !
			// On redirige vers une page où il sera indiqué que le mdp || le pseudo n'est pas correct.
				header('Location: incorrect.php');
		}
	}
$resultat->closeCursor();
?>
Cordialement,
aenarion
Je ne suis qu'une personne qui cherche à vous aider mais je suis comme vous, je suis "débutant" (quelqu'un cherchant de l'expérience en essayant de résoudre les problèmes des autres)

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

21 août 2014, 21:24

salut,

as tu testé la requête sql ?
l'as tu comprise ?

cette requête retourne toutes les lignes qui ont un pseudo identique à $pseudo.
Donc, sauf si tu as plusieurs pseudo identique, cette requête ne retourne qu'une seule.

Quand au fonctionnement du code :
- la méthode fetch retourne une ligne de résultat et lorsque le jeux est épuisé (ou qu'il n'y a pas de résultat) retourne false.

Du coup lorsque tu fais while ($donnes = $resultat->fetch()) tu utilise un abus de langage (le transtypage) pour que la condition du while soit vrai vrai tant qu'il y a des résultats.

au final, dans ton cas, le whil est inutile.
C'est vrai parce que le pseudo doit être unique et donc tu aura toujours zéro ou une réponse.
Si ce n'est pas le cas tu aura une authentification aléatoire (en fonction de la première ligne du résultat).
ensuite sur ton test la partie $pseudo == $donnes['pseudo'] est forcément inutile vu que tu le connais d'avance.

$pseudo = htmlspecialchars($_POST['pseudo']);
$pass = htmlspecialchars($_POST['pass']);

La fonction htmlspecialchars ne protège en rien des injection sql.
pour cela utilise la méthode quote de pdo ou une requête préparée (la première est la bonne solution a mon goût).
$resultat = $bdd->query('SELECT pseudo, pass, email, adresse, ville, postal, pays FROM membres WHERE pseudo=\''.$bdd->quote($_POST['pseudo']).'\' ');

pour la vérification : if ($_POST['pass'] == $donnes['pass'])

@+
Il en faut peu pour être heureux ......

Eléphanteau du PHP | 17 Messages

23 août 2014, 15:27

Re, et désolé de répondre si tard...
J'a ifait des modifications suite à ton post. Mais le problème c'est que si j'enlève le while comme tu m'as dit de faire ça me marque:
parse error: syntax error, unexpecter 'if' (T_IF) in C:..... on line 13
c'est pour ça que j'avais mis le while
Voilà le nouveaux code (avec tes modifs) mais ça ne marche... j'aurais juste besoin de piste de réflexions, d'aide.
<?php
try
{
	$bdd = new PDO('mysql:host=localhost;dbname=IATF', 'root', '', array (PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
}
 catch (Exception $e)
{
       die('Erreur : ' . $e->getMessage());
}
session_start();
			$resultat = $bdd->query('SELECT pseudo, pass, email, adresse, ville, postal, pays FROM membres WHERE pseudo=\''.$bdd->quote($_POST['pseudo']).'\' ');
			$donnees = $resultat->fetch()
					if ($_POST['pass'] == $donnees['pass'])
						{
							$_SESSION['login'] = true;
							$_SESSION['pseudo'] = $donnees['pseudo'];
							$_SESSION['email'] = $donnees['email'];
							$_SESSION['adresse'] = $donnees['adresse'];
							$_SESSION['ville'] = $donnees['ville'];
							$_SESSION['postal'] = $donnees['postal'];
							$_SESSION['pays'] = $donnees['pays'];
							header('Location: index.php');
						}
					else
						{
							header('Location: incorrect.php');
						}
			$reponse->closeCursor();
			?>
</body>
</html>
Je ne suis qu'une personne qui cherche à vous aider mais je suis comme vous, je suis "débutant" (quelqu'un cherchant de l'expérience en essayant de résoudre les problèmes des autres)

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

25 août 2014, 16:07

Salut,

il te manque un ; à la fin de la ligne du fetch ^_^

@+
Il en faut peu pour être heureux ......

Eléphanteau du PHP | 17 Messages

25 août 2014, 16:53

bonjour,

Je me suis sentit très con en voyant que j'avais juste oublié un ; ^^
Mais j'ai encore une autre erreur:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'azgfzge''' at line 1' in C:\wamp\www\IATF\traitementconnection.php on line 12

J'ai fait des recherches sur internet mais j'ai pas trouvé la solution.
Et si quelqu'un aurai des sites tuto pour la SQL ça serai sympas car en php/js j'y arrive mais en SQL je suis à la ramasse.

Cordialement,
aenarion
Je ne suis qu'une personne qui cherche à vous aider mais je suis comme vous, je suis "débutant" (quelqu'un cherchant de l'expérience en essayant de résoudre les problèmes des autres)

Eléphant du PHP | 113 Messages

25 août 2014, 21:01

c'est pour quelle requête qu'il y a eu ce rapport ? sa aiderait :P

Eléphanteau du PHP | 17 Messages

25 août 2014, 21:17

Pour cette requête:
$resultat = $bdd->query('SELECT pseudo, pass, email, adresse, ville, postal, pays FROM membres WHERE pseudo=\''.$bdd->quote($_POST['pseudo']).'\' ');
Je ne suis qu'une personne qui cherche à vous aider mais je suis comme vous, je suis "débutant" (quelqu'un cherchant de l'expérience en essayant de résoudre les problèmes des autres)

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

26 août 2014, 09:44

Je me suis sentit très con en voyant que j'avais juste oublié un ; ^^
:mrgreen:

ça arrive même au meilleur ;)

deux choses :
- Le message indique que tu ne capture pas l'exception PDOException.
en clair il faut que tu utilise un try / catch (voir finally) pour gérer correctement l'exception.
- Le message indique une erreur SQL.
L'erreur vient du fait que la méthode quote "protège" la chaîne contre les différentes "attaques" possible, mais aussi qu'elle retourne la donnée "prête à l'emplois" dans la requête sql.

en clair
si tu as $var = "toto" après l'utilisation de quote tu as $var = "'toto'"
Ceci parce que par défaut quote traite une chaîne de caractère. il est possible de lui indiquer un autre type bien entendu (plus d'infos dans la doc)

Exemple du code avec un gestion d'erreur et la correction de la requête SQL :
<?php
try {
    $sql = 'SELECT pseudo, pass, email, adresse, ville, postal, pays FROM membres WHERE pseudo=';
    $sql .= $bdd->quote($_POST['pseudo']);
    $resultat = $bdd->query($sql);
    $donnees = $resultat->fetch();
    // pas de cryptage // hash du mot de passe ?
    if (!is_null($donnees) && is_array($donnees) && $_POST['pass'] == $donnees['pass']) {
        $_SESSION['auth'] = $donnees;
        // parce que l'on a pas besoin du mot de passe en session
        unset($_SESSION['auth']['pass']);
        header('Location: index.php');
    } else {
        // il faudrait quand même gérer un message pour indiquer ce qui ne va pas ?
        header('Location: incorrect.php');
    }
    $resultat->closeCursor();
} catch (PDOException $e) {
    echo '<p class="avertissement erreur"> Erreur SQL login :';
    if(DEBUG){
        echo '<br/>Message d\'erreur : <br />';
        echo $e->getMessage();
        echo '<br />Trace<br />',$e->getTraceAsString();
    }
    echo '</p>';
} 

@+
Il en faut peu pour être heureux ......

Eléphanteau du PHP | 17 Messages

26 août 2014, 10:28

Bonjour,

Merci de votre aide, tout fonctionne maintenant.
Juste pour que je puisse m'améliorer en SQL, connaîtrais vous des tutos sur la SQL ?

Cordialement,
aenarion
Je ne suis qu'une personne qui cherche à vous aider mais je suis comme vous, je suis "débutant" (quelqu'un cherchant de l'expérience en essayant de résoudre les problèmes des autres)