1003 votes

mysql_fetch_array()/mysql_fetch_assoc()/mysql_fetch_row()/mysql_num_rows etc... s'attend à ce que le paramètre 1 soit une ressource.

J'essaie de sélectionner des données dans une table MySQL, mais je reçois l'un des messages d'erreur suivants :

mysql_fetch_array() attend du paramètre 1 qu'il soit une ressource, booléen donné

Voici mon code :

$username = $_POST['username'];
$password = $_POST['password'];

$result = mysql_query('SELECT * FROM Users WHERE UserName LIKE $username');

while($row = mysql_fetch_array($result)) {
    echo $row['FirstName'];
}

15 votes

Vous pouvez obtenir des messages d'erreur plus utiles en utilisant: : QUERY ou die(mysql_error()) ;

124 votes

Et aussi la note obligatoire : Votre code est susceptible de Injection SQL . Vous devez valider et/ou échapper à la saisie de l'utilisateur. Jetez un coup d'œil à mysql_real_escape_string . Ne faites jamais confiance aux données des utilisateurs.

7 votes

En fait, le code de l'OP provoquera une erreur de syntaxe sur le serveur MySQL, mais au moins il est no vulnérable à l'injection SQL car les guillemets simples n'ont pas d'interpolation de variable.

679voto

scompt.com Points 11304

Une requête peut échouer pour diverses raisons, auquel cas les extensions mysql_* et mysqli renverront toutes deux false à partir de leurs fonctions/méthodes d'interrogation respectives. Vous devez tester cette condition d'erreur et la traiter en conséquence.

L'extension mysql_* :

NOTE Le site Les fonctions mysql_ sont dépréciées et ont été supprimés dans la version 7 de php.

Vérifiez $result avant de le transmettre à mysql_fetch_array . Vous verrez que c'est false parce que la requête a échoué. Voir le mysql_query pour connaître les valeurs de retour possibles et les suggestions sur la façon de les traiter.

$username = mysql_real_escape_string($_POST['username']);
$password = $_POST['password'];
$result = mysql_query("SELECT * FROM Users WHERE UserName LIKE '$username'");

if($result === FALSE) { 
    die(mysql_error()); // TODO: better error handling
}

while($row = mysql_fetch_array($result))
{
    echo $row['FirstName'];
}

extension mysqli
style procédural :

$username = mysqli_real_escape_string($mysqli, $_POST['username']);
$result = mysqli_query($mysqli, "SELECT * FROM Users WHERE UserName LIKE '$username'");

// mysqli_query returns false if something went wrong with the query
if($result === FALSE) { 
    yourErrorHandler(mysqli_error($mysqli));
}
else {
    // as of php 5.4 mysqli_result implements Traversable, so you can use it with foreach
    foreach( $result as $row ) {
        ...

oo-style :

$username = $mysqli->escape_string($_POST['username']);
$result = $mysqli->query("SELECT * FROM Users WHERE UserName LIKE '$username'");

if($result === FALSE) { 
    yourErrorHandler($mysqli->error); // or $mysqli->error_list
}
else {
    // as of php 5.4 mysqli_result implements Traversable, so you can use it with foreach
    foreach( $result as $row ) {
      ...

en utilisant une déclaration préparée :

$stmt = $mysqli->prepare('SELECT * FROM Users WHERE UserName LIKE ?');
if ( !$stmt ) {
    yourErrorHandler($mysqli->error); // or $mysqli->error_list
}
else if ( !$stmt->bind_param('s', $_POST['username']) ) {
    yourErrorHandler($stmt->error); // or $stmt->error_list
}
else if ( !$stmt->execute() ) {
    yourErrorHandler($stmt->error); // or $stmt->error_list
}
else {
    $result = $stmt->get_result();
    // as of php 5.4 mysqli_result implements Traversable, so you can use it with foreach
    foreach( $result as $row ) {
      ...

Ces exemples illustrent seulement ce que devrait être fait (gestion des erreurs), pas comment le faire. Le code de production ne devrait pas utiliser or die lors de la sortie du HTML, sinon il générera (au minimum) du HTML invalide. De plus, les messages d'erreur de la base de données ne doivent pas être affichés aux utilisateurs non administrateurs, car cela pourrait nuire à l'intégrité de la base de données. divulgue trop d'informations .

9 votes

C'est vrai, mais utiliser un die() si la requête échoue est un peu trop.

30 votes

J'allais concevoir un mécanisme complet de gestion des erreurs pour le PO, mais j'ai décidé que cela dépassait le cadre de ma réponse.

0 votes

@scompt.com Oui, c'est également couvert dans plusieurs autres réponses. Je suppose que je voulais simplement faire remarquer que, puisque c'est la accepté sur une question à haute visibilité, en plus des (excellents) conseils sur la manière de capturer correctement les erreurs à l'avenir, elle devrait (IMHO) répondre réellement à la question spécifique (c'est-à-dire expliquer pourquoi il y a une erreur dans ce cas).

165voto

John Conde Points 102874

Ce message d'erreur s'affiche lorsque votre requête comporte une erreur qui l'a fait échouer. Il se manifeste lors de l'utilisation de :

  • mysql_fetch_array / mysqli_fetch_array()
  • mysql_fetch_assoc() / mysqli_fetch_assoc()
  • mysql_num_rows() / mysqli_num_rows()

Nota : Cette erreur ne no apparaissent si aucune ligne n'est affectée par votre requête. Seule une requête dont la syntaxe est invalide générera cette erreur.

Étapes de dépannage

  • Assurez-vous que votre serveur de développement est configuré pour afficher toutes les erreurs. Vous pouvez le faire en plaçant ceci en haut de vos fichiers ou dans votre fichier de configuration : error_reporting(-1); . Si vous avez des erreurs de syntaxe, il vous les signalera.

  • Utilisez mysql_error() . mysql_error() rapportera toutes les erreurs que MySQL a rencontrées lors de l'exécution de votre requête.

    Exemple d'utilisation :

    mysql_connect($host, $username, $password) or die("cannot connect"); 
    mysql_select_db($db_name) or die("cannot select DB");
    
    $sql = "SELECT * FROM table_name";
    $result = mysql_query($sql);
    
    if (false === $result) {
        echo mysql_error();
    }
  • Exécutez votre requête depuis la ligne de commande MySQL ou un outil tel que phpMyAdmin . Si vous avez une erreur de syntaxe dans votre requête, vous saurez de quoi il s'agit.

  • Assurez-vous que vos devis sont corrects. L'absence de guillemets autour de la requête ou d'une valeur peut entraîner l'échec de la requête.

  • Assurez-vous de l'échappement de vos valeurs. Les guillemets dans votre requête peuvent provoquer l'échec de celle-ci (et vous exposer à des injections SQL). Utilisez mysql_real_escape_string() pour échapper à votre entrée.

  • Assurez-vous que vous ne mélangez pas mysqli_* y mysql_* fonctions. Elles ne sont pas la même chose et ne peuvent pas être utilisées ensemble. (Si vous devez choisir l'une ou l'autre, restez-en à la fonction mysqli_* . Voir ci-dessous pour savoir pourquoi).

Autres conseils

mysql_* ne doivent pas être utilisées pour un nouveau code. Elles ne sont plus maintenues et la communauté a entamé le processus d'amélioration de la qualité. processus de dépréciation . Vous devriez plutôt vous renseigner sur déclarations préparées et utiliser soit AOP o MySQLi . Si vous n'arrivez pas à vous décider, cet article vous aidera à choisir. Si vous voulez apprendre, voici bon tutoriel PDO .

1 votes

Compte tenu de cette question aujourd'hui stackoverflow.com/q/43804651/1415724 et d'autres similaires ces derniers temps ; je pense qu'il peut être utile de mettre à jour votre réponse pour contenir quelque chose comme _"Cette erreur peut également être causée par le fait de ne pas exécuter la requête avec mysql_query() / mysqli_query($connection) etc."_ ; des réflexions ? Puisqu'aucune autre réponse dans ce Q&R ne mentionne cela.

113voto

nik Points 2289

L'erreur survenue ici est due à l'utilisation de guillemets simples ( ' ). Vous pouvez formuler votre requête de la manière suivante :

mysql_query("
SELECT * FROM Users 
WHERE UserName 
LIKE '".mysql_real_escape_string ($username)."'
");

Il utilise mysql_real_escape_string pour la prévention de l'injection SQL. Nous devrions utiliser l'extension MySQLi ou PDO_MYSQL pour les versions mises à jour de PHP (PHP 5.5.0 et ultérieur), mais pour les versions plus anciennes mysql_real_escape_string fera l'affaire.

5 votes

Pourquoi ajouter du bruit avec la concaténation de chaînes de caractères au lieu de simplement mettre la variable dans la chaîne de requête ?

1 votes

@Matteo Riva Oui, mais j'ai pensé que c'était une façon un peu plus propre de séparer les variables des chaînes de caractères :)

59voto

Kau-Boy Points 5512

Comme scompt.com a expliqué la requête peut échouer. Utilisez ce code pour obtenir l'erreur de la requête ou le résultat correct :

$username = $_POST['username'];
$password = $_POST['password'];

$result = mysql_query("
SELECT * FROM Users 
WHERE UserName LIKE '".mysql_real_escape_string($username)."'
");

if($result)
{
    while($row = mysql_fetch_array($result))
    {
        echo $row['FirstName'];
    }
} else {
    echo 'Invalid query: ' . mysql_error() . "\n";
    echo 'Whole query: ' . $query; 
}

Véase el la documentation pour mysql_query() pour de plus amples informations.

L'erreur réelle était les guillemets simples afin que la variable $username n'a pas été analysé. Mais vous devriez vraiment utiliser mysql_real_escape_string($username) pour éviter les injections SQL.

51voto

Matteo Riva Points 14340

Mettez des guillemets $username . Les valeurs de type chaîne, par opposition aux valeurs numériques, doivent être placées entre guillemets.

$result = mysql_query("SELECT * FROM Users WHERE UserName LIKE '$username'");

De même, il est inutile d'utiliser le LIKE si vous n'utilisez pas de jokers : si vous avez besoin d'une correspondance exacte, utilisez = au lieu de LIKE .

2 votes

Et si $username est : " ' ; DROP TABLES ;" ? C'est l'avantage d'utiliser les instructions préparées et les valeurs liées, que je pense que le demandeur souhaite conserver.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X