[RESOLU] Erreur avec mysql

Eléphant du PHP | 133 Messages

21 déc. 2013, 15:47

bonjour à tous ,

j'ai mis le nez enfin dans mysql , j'essai de comprendre une erreur aleatoire qui arrive sur un script que j'ai trouvé
c'est un script style "top20" pour radio

cela permet de voter pour un titre + ou -
mais par moment et cela est vrai aleatoire (5% de plantage je pense)
je me retrouve au moment du clic avec ça en erreur

Code : Tout sélectionner

Warning: mysql_fetch_row(): supplied argument is not a valid MySQL result resource in /homez.154/xxxxxx/vote/verifip.php on line 5 Warning: mysql_fetch_row(): supplied argument is not a valid MySQL result resource in /homez.154xxxxx/verifip.php on line 9 Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in /homez.154xxxxxxx/plus.php on line 65

debutant en mysql , j'essai de comprendre ce probleme mais la ...... :( perdu
au moment de voter + ou - le script va verifier dans la base s'il exite pas une ip lié a un titre pour eviter de flooder forcement
si je desactive le controle j'ai pas le soucis

voila le debut du cote plus.php
include ('verifip.php'); 
	if($bddinfo==getenv("REMOTE_ADDR")." ".date("j/m/Y")." ".date("H") && $bddtitre==$titre) 
	echo '<meta http-equiv="refresh" content="3;URL=index.php"><center><span style="font-weight:bold;"><i>'. $dejavote .'</i></span></center><br /><br />';
	else {
		
$queryouvert= mysql_query("SELECT `top_param`.`active` FROM top_param") or die('Erreur de connexion à MySQL '.mysql_error());
$donnee = mysql_fetch_assoc($queryouvert); 
if ( $donnee['active'] == 1 )
et voici le code du fichier verifier.php
<?php
$info = getenv("REMOTE_ADDR")." ".date("j/m/Y")." ".date("H");
$requette1 = mysql_query("SELECT titre FROM top_ip WHERE info LIKE '$info' AND titre LIKE '$titre'");
$resultat1 = mysql_fetch_row($requette1);
$bddtitre = $resultat1[0];
$requette2 = mysql_query("SELECT info FROM top_ip WHERE info LIKE '$info' AND titre LIKE '$titre'");
$resultat2 = mysql_fetch_row($requette2);
$bddinfo = $resultat2[0];
?>
je part de zero en mysql :) cela doit pas etre bien grave car le plantage est vraiment minimum mais bon

est ce probleme coté code ou coté ovh ?

cdt Pascal

ViPHP
xTG
ViPHP | 7331 Messages

21 déc. 2013, 17:01

Quand tu injectes une variable dans une requête il faut la protéger.
Passes tes variables dans mysql_real_escape_string() pour cela. ;)

De plus en environnement de debug tu peux regarder après chaque requête le retour de mysql_error() de cette façon :
$requette1 = mysql_query("SELECT titre FROM top_ip WHERE info LIKE '$info' AND titre LIKE '$titre'") or die(mysql_error());
Ce afin de voir les erreurs au plus tôt et avoir des informations sur ce qui coince.

Eléphant du PHP | 133 Messages

21 déc. 2013, 19:33

slt xTG

bon j'ai mis ça :
<?php
$info = getenv("REMOTE_ADDR")." ".date("j/m/Y")." ".date("H");
$requette1 = mysql_query("SELECT titre FROM top_ip WHERE info LIKE '$info' AND titre LIKE '$titre'") or die(mysql_error());
$resultat1 = mysql_fetch_row($requette1);
$bddtitre = $resultat1[0];
$requette2 = mysql_query("SELECT info FROM top_ip WHERE info LIKE '$info' AND titre LIKE '$titre'") or die(mysql_error());
$resultat2 = mysql_fetch_row($requette2);
$bddinfo = $resultat2[0];
?>
reste a avoir le soucis maintenant :( voir se que retourne l'erreur

par contre "Passes tes variables dans mysql_real_escape_string() pour cela. ;)"

j'ai pas trouvé la traduction dans mon dico de chinois :) :)


edit :
coup de chance le bug etait la :)

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 't wait'' at line 1

voici le retour :(

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

21 déc. 2013, 20:30

Salut,

Il faut afficher la requête SQL pour plus d'info ;)

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

ViPHP
xTG
ViPHP | 7331 Messages

21 déc. 2013, 21:10

Et un petit lien vers la doc pour t'aider dans la traduction. ;)
http://www.php.net/manual/fr/function.m ... string.php

Eléphant du PHP | 133 Messages

21 déc. 2013, 22:22

je viens de voir que ça bloque sur 2 titres qui viennent de passer :

Depeche Mode Just can't get enough
Talk Talk It's My Life

j'ai un ' il fait parti des caractères spéciaux , surement ça qui bloque
le code controle que le titre et pas l'artiste
pcq dans mon tableau "top20" j'ai un artiste avec des " dans le noms et pas rencontré de soucis

je viens de charger volontairement un titre avec un ' :
Blue Feather Let's funk tonight

erreur à nouveau
Modifié en dernier par sax76 le 21 déc. 2013, 22:27, modifié 1 fois.

ViPHP
xTG
ViPHP | 7331 Messages

21 déc. 2013, 22:26

Et la fonction que je t'ai linké sert justement à protéger les caractères spéciaux. :)

Eléphant du PHP | 133 Messages

21 déc. 2013, 22:38

<?php
$info = getenv("REMOTE_ADDR")." ".date("j/m/Y")." ".date("H");
$requette1 = mysql_query("SELECT titre FROM top_ip WHERE info LIKE '$info' AND titre LIKE '$titre'");
mysql_real_escape_string($titre);
$resultat1 = mysql_fetch_row($requette1);
$bddtitre = $resultat1[0];
$requette2 = mysql_query("SELECT info FROM top_ip WHERE info LIKE '$info' AND titre LIKE '$titre'");
mysql_real_escape_string($titre);
$resultat2 = mysql_fetch_row($requette2);
$bddinfo = $resultat2[0];
?>
j'ai mis ça mais je peux flooder le vote , ca marche pour les titre avec ou sans ' mais quand je dois verifier si il y a deja un vote il trouve pas et compte un nouveau


j'ai utilisé cet exemple
<?php
// Connexion
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')
OR die(mysql_error());

// Requête
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password));
?>
$info c'est l'ip , seul le $titre bloque j'ai donc mis la fonction que sur cette $var

U2 New Year's Day
erreur :(


le titre va bien ce mettre dans la base de donnée :

Image

c'est donc uniquement dans le fichier verif.php que ca bloque avec le ' car il est bien mis dans la base

Mammouth du PHP | 2278 Messages

22 déc. 2013, 10:59

Aspropos, il faudrait, surtout si tu commences, rédiger avec mysqli ou pdo au lieu de mysql qui est déclaré obsolète, dépassé en franco-chinois, et sera abandonné à terme par php. Les syntaxes sont un peu différentes, mais c'est toujours plus facile quand on n'a pas des réflexes d'ancien combattant de la guerre de P1-P5 qui viennent tout brouiller.
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

Eléphant du PHP | 133 Messages

22 déc. 2013, 11:47

:D

ben disons que le script est codé comme ça , j'ai deja trouvé et depanné 2/3 erreurs et j'ai du l'adapté a mon site
mais la partie qui bloque est resté d'origine (heureusement)

enfin la je suis bloqué et le code bloque sur les ' et le mysql_real_escape_string() marche pas ou alors je l'utilise pas comme il faut pour lire la base
mysql arrive a le charger sans soucis l'ajouter a la base mais arrive pas a le lire depuis la base pour le renvoyer dans php c'est bizarre ce truc !!

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

22 déc. 2013, 18:22

Salut ,

Les mysql_real_escape_string après construction de la requête ne servent a rien il faut l'utiliser dans la concaténation.
La ce sera utile.

Ensuite je suis, aussi, d'avis d'utiliser mysqli plutôt que mysql.
Les plus grandes différences c'est le i et le fait que tu va devoir passer la ressource de connections aux fonctions sinon c'est la même chose (pour toi).

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

Eléphant du PHP | 133 Messages

22 déc. 2013, 21:12

Salut ,

Les mysql_real_escape_string après construction de la requête ne servent a rien il faut l'utiliser dans la concaténation.
La ce sera utile.
mysql_real_escape_string() s'utilise dans le INSERT ?
$resultat=mysql_query("INSERT INTO top_vote_titre (fleche, artiste, titre, cover, plus, moins, total) VALUES ('images/haut.png', '$artiste','$titre','$cover', '1', '0', '1')");
c'est la que je créé la donnée et j'ai mon $titre , je dois faire ça ?
[php]$resultat=mysql_real_escape_string("INSERT INTO top_vote_titre (fleche, artiste, titre, cover, plus, moins, total) VALUES ('images/haut.png', '$artiste','$titre','$cover', '1', '0', '1')");
[/php]

Ensuite je suis, aussi, d'avis d'utiliser mysqli plutôt que mysql.
Les plus grandes différences c'est le i et le fait que tu va devoir passer la ressource de connections aux fonctions sinon c'est la même chose (pour toi).

@+
si passer en mysqli (je savais meme pas que ça existait :)) resoudré mon soucis de ' , j'y passe :)

je viens de lire rapidement un tuto de http://fr.openclassrooms.com/informatiq ... i-sans-poo (rapidement)
il suffit de rajouter un i a la fin de mysql , j'ai comparé 2/3 commande mysql et mysqli c'est les memes (ou alors j'ai loupé un truc :D)

mais si je passe en mysqli je dois reprendre la config complete de la base , y compris la connexion du debut ou pas ?

ViPHP
xTG
ViPHP | 7331 Messages

23 déc. 2013, 08:21

Non le problème des quotes c'est mysql_real_escape_string ou mysqli_real_escape_string qui va te le régler.
Mais seulement si tu utilises correctement la fonction.
$var = mysql_real_escape_string($var);
// je peux maintenant utiliser $var dans une requête SQL
Et elle est à utiliser pour toute requête (insert, update, select, ect).

Le driver mysql n'est plus supporté (plus de mises à jour de sécurité donc), il est fortement conseillé de passer à mysqli ou bien à PDO.

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

23 déc. 2013, 12:11

le problème est dû :
- au fait que tu n'utilise pas la concaténation
- que tu n'as pas compris l'utilisation des variables ;)
ceci
<php
$requette1 = mysql_query("SELECT titre FROM top_ip WHERE info LIKE '$info' AND titre LIKE '$titre'");
mysql_real_escape_string($titre);
est inutile parce que tu ne récupère pas le retour de mysql_real_escape_string et surtout que tu le fait après exécution de la requête.

l’exécution d'un script est séquentielle. c'est à dire qu'elle s'effectue ligne après ligne (seule sont omit les commentaires les lignes dansu n if / else qui ne correpsondent pas à la condition bien sur).
Mais le point important c'est que l'on ne revient pas en arrière.
Donc ici le mysql_query est executé donc l'échappement du titre est inutile.

pour la concaténation cela permet d'avoir un code plus lisible, d'éviter des source d'erreur (le parseur de chaine ne sais pas toujours ce qu'il doit utiliser comme variable, sauf si tu utilise les {}) et par principe il y a de grandes chances que cela soit plus rapide (pas d'analyse de la chaîne à faire).
Tu ne peux pas utiliser dans fonction sans concaténation.
Dernière chose, même si l'utilisation du passage par référence est généralisé cela ne veux pas dire que c'est toujours le cas, ce qui fait qu'ici la valeur de $titre ne change pas.

la requête correcte est
<php
$sql = 'SELECT titre FROM top_ip WHERE info = \'.mysql_real_escape_string($info).'\' AND titre =\''.mysql_real_escape_string($titre).'\'';
$requette1 = mysql_query($sql);
Les like sont inutiles vu que tu n'utilise pas de joker (%) le égale est suffisant et surtout (dans ce cas) plus performant.

pour répondre à ta question sur mysqli, effectivement cela peux résoudre ton problème car la plus part du temps présenté avec les requêtes préparées (utilisées à tors et à travers) qui s'occupent de réaliser l'échappement des données pour toi (avec les bind*).
Ceci dit il est préférables de savoir le faire toi même histoire de comprendre ce que tu faite.
j'ai utilisé une variable pour la requête SQL simplement parce que cela permet de la réutiliser pour debuguer (avec xdebug par exemple) et / l'afficher dans un quelconque message d'erreur voir un loguer).

J'ajouterais au fait que le driver mysql n'est plus supporté, qu'il est prévu pour être supprimé dans une future version (ce n'est pas pour demain mais autant préparer sont code à l'avenir c'est pas trop complexe et te permettra de ne pas devoir le faire au dernier moment ;)

du coup ton code deviendrait
<?php
mysql_connect('host', 'user', 'password');
mysql_selectdb('le nome la base');
$info = getenv("REMOTE_ADDR") . " " . date("j/m/Y") . " " . date("H");
$sql = 'SELECT count(*) as nb FROM top_ip WHERE info = \'' . mysql_real_escape_string($info) . '\' AND titre = \'' . mysql_real_escape_string($titre) . '\'';
$req = mysql_query($sql);
if ($req === false) {
    echo 'Erreur SQL : ' . mysql_error() . '<br />Avec la requête : ' . htmlentities($sql);
} else {
    $data = mysql_fetch_assoc($req);
    if ($data['nb'] != 0) {
        echo 'existe deja dans la table';
    } else {
        echo 'existe pas dans la table';
    }
    mysql_free_result($req);
}
mysql_close();

// version mysqli
$connexion = mysqli_connect('host', 'user', 'password', 'nom de la base', 3306);

$info = getenv("REMOTE_ADDR") . " " . date("j/m/Y") . " " . date("H");
$sql = 'SELECT count(*) as nb FROM top_ip WHERE info = \'' . mysql_real_escape_string($info) . '\' AND titre = \'' . mysql_real_escape_string($titre) . '\'';
$req = mysqli_query($connexion, $sql);
if ($req === false) {
    echo 'Erreur SQL : ' . mysqli_error($connexion) . '<br />Avec la requête : ' . htmlentities($sql);
} else {
    $data = mysqli_fetch_assoc($req);
    if ($data['nb'] != 0) {
        echo 'existe deja dans la table';
    } else {
        echo 'existe pas dans la table';
    }
    mysqli_free_result($req);
}

mysqli_close($connexion);

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

Eléphant du PHP | 133 Messages

28 déc. 2013, 02:21

merci j'ai resolu mon soucis j'ai plus d'erreur

par contre pour le mysqli .... plus tard lol