8721 sujets

Développement web côté serveur, CMS

Bonjour,

C'est le désespoir total ! Je sais, le problème a été déjà traité maintes et maintes fois. J'ai trouvé une multitude de posts sur divers forums, mais jamais celle solutionnant mon problème. Et c'est pas faute d'avoir essayé !

J'ai créé une page 'artiste' assez basique dans laquelle s'affiche le nom, la bio et la discographie de l'artiste en question.

- Je récupère donc le nom d'artiste passé en variable d'url sous la forme '?name=prenom-nom'
- Je rajoute les espaces et les majuscules, tel que c'est formaté dans la BDD
- Je fais une recherche dans 3 colonnes de la BDD
- Enfin j'affiche le résultat.

Voici le code :



$name = $_GET['name'];
$nameSpace = ucwords(str_replace('-', ' ', $name));
echo $nameSpace; 

$reponseArtist = $bdd->query("SELECT * FROM nouvellePage WHERE artiste1 = '".$nameSpace."' OR artiste2 = '".$nameSpace."' OR artiste3 = '".$nameSpace."' ORDER BY date DESC LIMIT 1");

while ($dataArtist = $reponseArtist->fetch()){
	if ($dataArtist['artiste1'] ==$nameSpace){
		$bio = $dataArtist['bio1en'];
		$photo = 1;
	}
	elseif($dataArtist['artiste2'] == $nameSpace){
		$bio = $dataArtist['bio2en'];
		$photo = 2;
	}
	else{
		$bio = $dataArtist['bio3en'];
		$photo = 3;
	}
	$artistLatestRef = $dataArtist['reference'];
}


Ca marche très bien pour tous les artistes sauf si un apostrophe est présent dans le nom ou le prenom. J'ai essayé de remplacer l'apostrophe par deux apostrophes comme indiqué dans certains forum, sans succès.

Ce que je ne comprends pas, c'est que le résultat de
echo $nameSpace; 
avant d'envoyer la requete est au bon format, c'est à dire, identique à la valeur dans la BDD.

par exemple, en passant en url :

/?name=daddy%27s-groove

echo $nameSpace; 
renvoie bien Daddy\'s Groove, tel qu'il est inscrit dans la BDD. Et pourtant, la requête SQL ne renvoie rien. Pas même un message d'erreur.

Autre bizarrerie, si je vais directement dans phpMyAdmin et que je fais une recherche sur le nom, en entrant exactement Daddy\'s Groove, tel qu'il est inscrit dans la BDD, la recherche ne mène à rien, mais il transforme la requete comme celà :

SELECT * 
FROM  `nouvellePage` 
WHERE  `artiste` LIKE  '%Daddy\\''s Groove%'


C'est à dire en rajoutant \' à ceux déjà existant. Donc je me demande si ce n'est pas une option à désactiver quelque part, peut-être dans php.ini ?

Quelqu'un aurait-il une explication ?

Merci !!
Bonjour,

Il faut d'abord que tu vérifie que les guillemets magiques sont bien désactivés : http://www.php.net/manual/fr/security.magicquotes.disabling.php

Ensuite, tu doit absolument échapper tes données, pour des raison de sécurité, avant de les intégrer à ta requête.
Pour cela utilise la méthode escape de ton objet $bdd si elle existe. Ou alors tu as la fonction mysql_real_escape_string

$bdd->query("SELECT * FROM nouvellePage WHERE artiste1 = '".$bdd->escape($nameSpace)."' OR artiste2 = '".$bdd->escape($nameSpace)."' OR artiste3 = '".$bdd->escape($nameSpace)."' ORDER BY date DESC LIMIT 1");

Modifié par benj (29 May 2013 - 18:59)
Hello,

Merci pour vos réponses. Je reviens dessus un peu plus bas.

Car j'ai finalement réussi à résoudre le problème avec l'aide d'un ami qui a un sens du déboggage bien plus méthodique que le mien. Donc pour ceux que ça intéresse :

Il y avait en fait deux problèmes, mais pas là où je pensais.

Je m'acharnais à vouloir trouver la bonne requête SQL ou plutôt la bonne façon de passer la valeur dans la variable à chercher via LIKE. En fait ma requête était bonne : la chaîne de caractères contenant l'apostrophe était bien échappée (en l'occurrence, grâce ou à cause des magic quotes).

L'erreur venait d'une part de la valeur dans la base de donnée, qui elle aussi était échappée (ex: O\'Brian). Je l'ai retiré.

J'avais déjà testé ça sans succès, car une autre erreur se cachait plus bas, dans la condition IF : en enlevant le slash dans la BDD, je comparais dans PHP une valeur échappée à une valeur non échappée. Donc ça me renvoyer un FALSE. Logique.

Donc pour résumer :

Côté PHP :
"SELECT *
 FROM ma_table
 WHERE colonne
 LIKE '".$maVariable."'
 ORDER BY..."


avec
$maVariable = 'O\'Brian';


Côté BDD :
Valeur = O'Brian

Et ça fonctionne.

@benj :
Pour ce qui concerne les magic quotes, j'ai effectivement lu ça et là qu'il valait mieux désactiver la fonction. Pourquoi ?

Quelle différence entre
addslashes($nameSpace)
et
$bdd->escape($nameSpace)
?

@Lothindil :
Même question pour mysqli_real_escape_string ?

Merci !
Pourquoi pas passer par des requêtes préparées ? La fonction prepare() de PDO permet de te faire les echappements et tout le travail derrière comme il faut.
C'est qu'un avis perso, je passe toujours par ça quand j'utilise une variable dans une requête.
Apoooo,

C'est mieux de passer par la classe PDO ?

J'en profite pour poser une question plus ou moins liée :
peut-on garder des majuscules dans les variable d'URL ?

J'ai tout passé en minuscule avant d'envoyer dans les urls. Mais ça me pose des problèmes, notamment sur les noms composés d'initiales du style ATB. Car un ucwords() va me passer seulement la première lettre en majuscule. Et un strtoupper() ne va pas fonctionner sur un nom normal ou seule la premiere lettre doit être en majuscule. Dilemme...
Kittisak a écrit :
@Lothindil :
Même question pour mysqli_real_escape_string ?

Merci !

Ma remarque portait juste entre mysql_real_escape_string et mysqli_real_escape_string.

Et pourquoi, simplement parce que la série de fonction mysql_ est dépréciée depuis quelques temps déjà et obsolète depuis la version 5.5 de PHP. Ce qui signifie qu'elle devrait sans doute disparaître totalement dans le PHP 6. (cf introduction à l'extension mysql sous php)

Et je conseille d'utiliser mysqli_ pour remplacer mysql_ parce que le passage se fait beaucoup plus aisément sur un code déjà en place que le PDO. (après PDO ou mysqli_ est un débat sur lequel je m'avance pas, j'utilise le mysqli parce qu'il me paraît plus simple à appréhender, c'est tout^^)
Kittisak a écrit :

@benj :
Pour ce qui concerne les magic quotes, j'ai effectivement lu ça et là qu'il valait mieux désactiver la fonction. Pourquoi ?

Quelle différence entre
addslashes($nameSpace)
et
$bdd->escape($nameSpace)
?

Les magic quotes posent plus de problèmes qu'ils ne sont sensé en résoudre. voir la doc : http://www.php.net/manual/fr/security.magicquotes.whynot.php

La fonction mysqli_real_escape_string est spécialement conçu pour échapper les chaines mysql. Ce qui n'est pas le cas de addslashes.

Lothindil a écrit :
ou plutôt mysqli_real_escape_string (et abandonner définitivement les balises mysql_ )
Oups, merci de m'avoir repris.
Kittisak a écrit :
Apoooo,

C'est mieux de passer par la classe PDO ?


Mieux je ne sais pas, mais je parle de PDO vis à vis du code donné :

$reponseArtist = $bdd->query("SELECT * FROM nouvellePage WHERE artiste1 = '".$nameSpace."' OR artiste2 = '".$nameSpace."' OR artiste3 = '".$nameSpace."' ORDER BY date DESC LIMIT 1");


Pour moi ton appli tourne déjà avec une connexion via PDO.
Utiliser mysqli_... va t'obliger à ouvrir une autre connexion juste pour cette fonction si tu ne comptes l'utiliser que pour échapper...
(sauf si je me trompe ? je n'ai jamais utilisé mysqli mais j'imagine que c'est le même comportement que l'ancien mysql_)
Modifié par Apoooo (30 May 2013 - 14:41)
Modérateur
Bonjour Kittisak,

Pourquoi cela te simplifierait-il la vie pour tes requêtes SQL? Par défaut, les requêtes ne sont pas sensibles aux lettres majuscules et minuscules.
Bonjour Tony,

Et merci. En t'écrivant mon explication, je viens de trouver la solution tout seul Smiley biggol

Je voulais récupérer le nom à afficher depuis l'url (qui est au format minuscule-minuscule) et pas forcément au format MAJUSCULE pour un nom d'artiste en initiales. Alors que je n'ai qu'à le récupérer depuis la BDD où il est au bon format.

Ma question était stupide Smiley confus
Voilà donc, effectivement, le problème venait ENCORE de mes conditions, vu que je comparais deux chaines de casses différentes.

La solution : strcasecmp($string1, $string2) qui renvoie 0 si les strings sont égales malgré des casses différentes Smiley smile

Merci à tous
Modifié par Kittisak (30 May 2013 - 19:23)
Apoooo a écrit :


Mieux je ne sais pas, mais je parle de PDO vis à vis du code donné :

$reponseArtist = $bdd->query("SELECT * FROM nouvellePage WHERE artiste1 = '".$nameSpace."' OR artiste2 = '".$nameSpace."' OR artiste3 = '".$nameSpace."' ORDER BY date DESC LIMIT 1");


Pour moi ton appli tourne déjà avec une connexion via PDO.
Utiliser mysqli_... va t'obliger à ouvrir une autre connexion juste pour cette fonction si tu ne comptes l'utiliser que pour échapper...
(sauf si je me trompe ? je n'ai jamais utilisé mysqli mais j'imagine que c'est le même comportement que l'ancien mysql_)

mysqli en orienté objet pourrait donner exactement le même code Smiley cligne

Mais effectivement, s'il utilise déjà une connexion via PDO, il a tout intérêt à rester dans la même extension.

En revanche, s'il était sur l'ancien mysql_; il a tout intérêt à passer sur mysqli_, le passage se fait plus en douceur.
Tony Monast a écrit :

Pourquoi cela te simplifierait-il la vie pour tes requêtes SQL? Par défaut, les requêtes ne sont pas sensibles aux lettres majuscules et minuscules.


En fait la sensibilité à la casse dépend de l'interclassement choisi. Avec ceux qui se terminent par "_ci" (case insensitive) il n'y aura pas de différence entre majuscules et minuscules, avec les autres si.
Merci jb_gfx pour cette info. Je savais pas. Effectivement je suis en UTF8_general_ci.

Et comme dit plus haut, mon problème de casse venait de la condition qui traite la réponse.
Modifié par Kittisak (31 May 2013 - 11:33)