Utilisateurs connectés : mysql_num_rows(): supplied argument...

Résolu
Bonjour,

Lorsque je mets sur mon site ce script qui permet de compter les utilisateurs connectés :

<?php
$link = mysql_connect('CONNEXION');
mysql_select_db("BDD", $link);

$result = mysql_query('SELECT COUNT (*) AS nbre_entrees FROM connectes WHERE ip=\'' . $_SERVER['REMOTE_ADDR'] . '\' ', $link);
$donnees = mysql_num_rows($result);

if ($donnees['nbre_entrees'] == 0) // L'IP ne se trouve pas dans la table, on va l'ajouter.
{
mysql_query('INSERT INTO connectes VALUES(\'' . $_SERVER['REMOTE_ADDR'] . '\', ' . time() . ')');
}
else // L'IP se trouve déjà dans la table, on met juste à jour le timestamp.
{
mysql_query('UPDATE connectes SET timestamp=' . time() . ' WHERE ip=\'' . $_SERVER['REMOTE_ADDR'] . '\'');
}

// -------
// ÉTAPE 2 : on supprime toutes les entrées dont le timestamp est plus vieux que 5 minutes.

// On stocke dans une variable le timestamp qu'il était il y a 5 minutes :
$timestamp_5min = time() - (60 * 5); // 60 * 5 = nombre de secondes écoulées en 5 minutes
mysql_query('DELETE FROM connectes WHERE timestamp < ' . $timestamp_5min);

// -------
// ÉTAPE 3 : on compte le nombre d'IP stockées dans la table. C'est le nombre de visiteurs connectés.
$retour = mysql_query('SELECT COUNT(*) AS nbre_entrees FROM connectes');
$donnees = mysql_fetch_array($retour);


// Ouf ! On n'a plus qu'à afficher le nombre de connectés !
if($donnees['nbre_entrees'] > 1 )
{
echo '<p>Il y a actuellement ' . $donnees['nbre_entrees'] . ' visiteurs connectés sur le site !</p>';
}

else
{
echo '<p>Il y a actuellement ' . $donnees['nbre_entrees'] . ' visiteur connecté sur le site !</p>';
}
?> 


Le message d'erreur suivant s'affiche :

PHP Error Message

Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in /home/a3506773/public_html/m/accueil.php on line 49

Free Web Hosting

Il y a actuellement 0 visiteur connecté sur le site !


Que faire ?

Merci d'avance



Une fois un problème résolu, mettez un +1 sur la réponse qui vous à aidez et mettez Problème Résolu ! ;-)

18 réponses

Résumé de la discussion

Le script PHP destiné à compter les visiteurs connectés déclenche une erreur mysql_num_rows() et met en lumière une manipulation incorrecte de COUNT(*) et du résultat de requête sur la table connectes. Des solutions essentielles recommandent d’utiliser COUNT(*) sans espaces et de récupérer la valeur via mysql_fetch_array(), puis d’utiliser cette valeur plutôt que mysql_num_rows sur le résultat et d’afficher le compteur extrait. En cas d’échec, il est conseillé d’ajouter die(mysql_error()) pour diagnostiquer les messages MySQL et de vérifier que l’instruction INSERT ou UPDATE est bien formée et exécutée selon la présence de l’adresse IP. D'autres échanges indiquent que des erreurs d’orthographe dans les noms de colonnes ou des définitions de champs peuvent aussi empêcher l’insertion et fausser le comptage.

Bobot (l’IA à votre service)
  1. Contributeur
    Salut,

    tu dois avoir un problème avec cette requête :

    $result = mysql_query('SELECT COUNT (*) AS nbre_entrees FROM connectes WHERE ip=\'' . $_SERVER['REMOTE_ADDR'] . '\' ', $link);

    tu peux rajouter : OR die(mysql_error()); pour avoir l'éventuelle erreur mysql, mais je pense que tu devrais construire ta requête avant de l'exécuter, tu pourrais l'afficher, et comprendre rapidement d'où peut venir l'erreur.
    0
    1. Oui, cela vient du
       AS nbre_entrees 
      j'ai l'impression.
      0
      1. Contributeur
        le mieux c'est d'en être sûr.

        fais ça :

        echo $req = 'SELECT COUNT (*) AS nbre_entrees FROM connectes WHERE ip=\'' . $_SERVER['REMOTE_ADDR'] . '\' ';
        $result = mysql_query($req, $link); 


        tu peux même mettre un die(); après ton echo pour éviter de subir une redirection ou autre.

        Ta requête va être affichée, peut être que l'erreur va te sauter aux yeux à ce moment là.
        Sinon, exécute cette requette dans phpmyadmin, ou regarde ce qu'il te dit dans le die(mysql_error())
        0
        1. Voilà ce qui s'affiche :

          SELECT COUNT (*) AS nbre_entrees FROM connectes WHERE ip='IP EST ICI'
          
          PHP Error Message
          
          Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in /home/a3506773/public_html/m/accueil.php on line 51


          Sachant que la ligne 51 est :
          $link = mysql_connect('xxxxxxxxxxxx');
          mysql_select_db("a3506773_bdd", $link);
          
          echo $req = 'SELECT COUNT (*) AS nbre_entrees FROM connectes WHERE ip=\'' . $_SERVER['REMOTE_ADDR'] . '\' ';
          $result = mysql_query($req, $link); 
          
          $donnees = mysql_num_rows($result);


          Une fois un problème résolu, mettez un +1 sur la réponse qui vous à aidez et mettez Problème Résolu ! ;-)
          0
          1. Contributeur
            et tu as exécuté ta requête dans phpmyadmin ou fait ça :
            $result = mysql_query($req, $link) or die(mysql_error());

            pour avoir une idée de l'erreur ?

            D'autre part, faire un mysql_num_rows sur un count(*) n'a pas de sens, le résultat d'un num_rows là dessus sera toujours 1 étant donné que le but du count(*) est de donner le nombre de ligne.
            0
          2. Donc je fais seulement SELECT * ?

            Et où et comment je dois exécuter ma requête dans Phpmyadmin ?
            0
          3. Contributeur
            dans phpmyadmin, une fois rentré dans n'importe quelle table, tu as un onblet SQL, tu mets ta requête là et tu observes le résultat.

            tu peux garder ton count, mais après il faut faire un mysql_result($result, 0);
            0
        2. Bonjour

          Es-tu sûr que ta base de données a été créée ? Arrives-tu à te connecter avec phpmyadmin ?
          0
          1. Oui, ma base de donnée a bien été crée et j'arrive à me connecter à phpmyadmin.

            Voici le résultat de ma requête :

             MySQL said: Documentation
            #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 '*) AS nbre_entrees FROM connectes WHERE ip='ADRESSE IP ICI'
            LIMIT 0, 30' at line 1  


            Donc normalement, dans mon code, si la ligne n'existe pas, alors une ligne avec toutes les informations doit être créer.

            if ($donnees['nbre_entrees'] == 0) // L'IP ne se trouve pas dans la table, on va l'ajouter.
            {
            mysql_query('INSERT INTO connectes VALUES(\'' . $_SERVER['REMOTE_ADDR'] . '\', ' . time() . ')');
            }
            else // L'IP se trouve déjà dans la table, on met juste à jour le timestamp.
            {
            mysql_query('UPDATE connectes SET timestamp=' . time() . ' WHERE ip=\'' . $_SERVER['REMOTE_ADDR'] . '\'');
            }

            0
            1. Tu as une espace en trop entre COUNT et (*)
              Les fonction mysql NE DOIVENT PAS être séparées da la parenthèse ouvrante par une espace.
              0
              1. Remarque : je t'avais demandé si ta base avait été créée parce que je m'étais connecté à ton compte avec les identifiants que tu avais eu l'imprudence de mettre en clair. Je m'étais bien connecté, mais ça m'avait affiché qu'il n'y avait aucune base de données. Il faut croire qu'il y avait autre chose.
                J'ai demandé à la modération de masquer tes identifiants, mais fais attention une autre fois.
                0
              2. Ah oui, effectivement j'ai oublié de les enlever. D'habitude je fais gaffe ;) Merci :)
                0
            2. Effectivement, le message d'erreur disparait. Problème, vu que l'IP ne se trouve pas dans la table, une entrée devrait ce créer pour que mon IP s'y trouve.
              Or, l'insertion ne s'effectue pas. Quelqu'un sait pourquoi ?
              if ($donnees['nbre_entrees'] == 0) // Ce qui est le cas
              {
              mysql_query('INSERT INTO connectes VALUES(\'' . $_SERVER['REMOTE_ADDR'] . '\', ' . time() . ')');
              }
              else // L'IP se trouve déjà dans la table, on met juste à jour le timestamp.
              {
              mysql_query('UPDATE connectes SET timestamp=' . time() . ' WHERE ip=\'' . $_SERVER['REMOTE_ADDR'] . '\'');
              } 

              0
              1. Ta requête est SELECT COUNT(*)
                Cette requête a toujours UNE ligne de réponse. La réponse est peut-être 0,1, 10 ou 10000 mais il y a une ligne et une seule

                Ce qu'il faut tester, ce n'est pas le nombre de lignes de la réponse (qui sera toujours 1) mais le contenu de cette réponse.

                $donnees=mysql_fetch_array($result);
                if ($donnees['nbre_entrees'] == 0)...
                0
                1. J'ai modifié deux/trois trucs, mon code est donc celui-ci :

                  echo $req = 'SELECT * FROM connectes WHERE ip=\'' . $_SERVER['REMOTE_ADDR'] . '\' ';
                  $result = mysql_query($req, $link); 
                  
                  $donnees=mysql_num_rows($result);
                  echo $donnees;
                  
                  if ($donnees == 0) // L'IP ne se trouve pas dans la table, on va l'ajouter.
                  {
                  mysql_query('INSERT INTO connectes VALUES(\'' . $_SERVER['REMOTE_ADDR'] . '\', ' . time() . ')');
                  }
                  else // L'IP se trouve déjà dans la table, on met juste à jour le timestamp.
                  {
                  mysql_query('UPDATE connectes SET timestamp=' . time() . ' WHERE ip=\'' . $_SERVER['REMOTE_ADDR'] . '\'');
                  }


                  Le echo $donnnees donne 0, or l'insertion ne se fait pas...
                  0
                  1. Ce n'est pas une bonne idée d'avoir remplacé le SELECT COUNT(*) par SELECT * et le mysql_fetch_array par un mysql_num_rows.
                    En effet, tu obliges mysql à aller chercher toutes les données de ta table, ce qui est laborieux, alors que tu as juste besoin du nombre de lignes, ce qui est instantané.

                    Mais, bon, ça marche quand même.

                    Par contre, ton insert ne marche pas. Ta table a 6 champs, mais tu ne donnes que 2 valeurs dans ton INSERT. Comment il fait pour deviner quelle valeur va dans quel champ ?

                    'INSERT INTO connectes (id_user,timestamp)  VALUES(\'' . $_SERVER['REMOTE_ADDR'] . '\', ' . time() . ')'
                    


                    Il faudrait d'ailleurs compléter les autres champs, surtout que tu leur a donné des attributs NOT NULL
                    0
                    1. Autre remarque :

                      l'insertion ne se fait pas
                      La prochaine fois qu'une requête ne marche pas, ajoute toi-même or die (mysql_error()) pour avoir le message d'erreur de mysql
                      0
                  2. Alors j'ai modifié comme cela :

                    if ($donnees == 0) // L'IP ne se trouve pas dans la table, on va l'ajouter.
                    {
                    echo " il faut creer !";
                    mysql_query('INSERT INTO connectes (id_user, username_user, nbre_entrees, ip, timestamp) VALUES("'.$_SESSION['id'].'", "'.$_SESSION['username'].'", "1", "\'' . $_SERVER['REMOTE_ADDR'] . '\'", "' . time() . '")');
                    }
                    else // L'IP se trouve déjà dans la table, on met juste à jour le timestamp.
                    {
                    echo " existe deja";
                    mysql_query('UPDATE connectes SET timestamp=' . time() . ' WHERE ip=\'' . $_SERVER['REMOTE_ADDR'] . '\'');
                    }


                    problème, mon $donnees affiché 1 hors ma table connectes est vide...

                    De plus, j'ai modifié et remis comme avant (avec un SELECT COUNT(*) et un mysql_fetch_array hors l'erreur réapparait : Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource)

                    Une fois un problème résolu, mettez un +1 sur la réponse qui vous à aidez et mettez Problème Résolu ! ;-)
                    0
                    1. Ton $donnees affiche 1 alors qu'il affichait 0 avant ? C'est que tu as 'bricolé' le code qui précède. Car avec le code que tu montres, on ne peut rien dire, $donnees est déjà déterminé.
                      Tu as sans doute mis SELECT COUNT(*) puis compté les lignes avec mysql_num_rows
                      0
                      1. Voici mon code a l'état actuel :
                        $link = mysql_connect('xxxxxxxxxxxxxxxxxxxxxx');
                        mysql_select_db("xxxxxxxxxxxx", $link);
                        
                        echo $req = 'SELECT COUNT(*) AS nbre_entrees FROM connectes WHERE username='.$_SESSION['username'].' AND ip=\'' . $_SERVER['REMOTE_ADDR'] . '\' ';
                        $result = mysql_query($req, $link); 
                        
                        $donnees=mysql_fetch_array($result);
                        echo $donnees;
                        
                        if ($donnees == 0) // L'IP ne se trouve pas dans la table, on va l'ajouter.
                        {
                        echo " il faut creer !";
                        mysql_query('INSERT INTO connectes (id_user, username_user, nbre_entrees, ip, timestamp) VALUES("'.$_SESSION['id'].'", "'.$_SESSION['username'].'", "1", "\'' . $_SERVER['REMOTE_ADDR'] . '\'", "' . time() . '")');
                        }
                        else // L'IP se trouve déjà dans la table, on met juste à jour le timestamp.
                        {
                        echo " existe deja";
                        mysql_query('UPDATE connectes SET timestamp=' . time() . ' WHERE ip=\'' . $_SERVER['REMOTE_ADDR'] . '\'');
                        } 


                        Et voici ce qu'affiche ma page :

                        SELECT COUNT(*) AS nbre_entrees FROM connectes WHERE username=admin AND ip='AFFICHE ICI IP'
                        PHP Error Message
                        
                        Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /home/a3506773/public_html/m/accueil.php on line 53
                        
                        Free Web Hosting
                        il faut creer !
                        
                        Il y a actuellement 0 visiteur connecté sur le site !
                        0
                        1. $donnees=mysql_fetch_array($result);
                          echo $donnees;
                          if ($donnees == 0)

                          Le nombre d'entrées est dans $donnees['nbre_entrees'], pas simplement dans $donnees ! Il faudrait vraiment que tu revoies le B A BA de mysql !

                          Quant à ton message d'erreur, on ne sait pas à quelle ligne il se rapporte (53, ça ne me dit rien) et, au risque de me répéter, tu n'as pas besoin qu'on te redise à chaque fois d'ajouter or die (mysql_error()) à l'exécution de chaque requête pour avoir un message d'erreur parlant.
                          0
                          1. Je ne suis pas vraiment très bon en PHP.

                            La ligne 53 correspond à
                            $donnees=mysql_fetch_array($result); 

                            0
                            1. Maintenant, j'ai modifié le code. Le message d'erreur a disparu. problème, l'insertion ne fonctionne pas..

                              Voici mon code :
                              echo $donnees['nbre_entrees'];
                              
                              if ($donnees['nbre_entrees'] == 0) // L'IP ne se trouve pas dans la table, on va l'ajouter.
                              {
                              echo " il faut creer !";
                              mysql_query('INSERT INTO connectes (id_user, username, nbre_entrees, ip, timestamp) VALUES("'.$_SESSION['id'].'", "'.$_SESSION['username'].'", "1", "\'' . $_SERVER['REMOTE_ADDR'] . '\'", "' . time() . '")') or die (mysql_error());
                              echo "  / c'est creer";
                              }


                              Et voici ce qui s'affiche sur ma page : 0 il faut creer ! / c'est creer
                              0
                              1. il n' y a pas un mysql_init() dans les parages?? histoire d'initialiser correctement mysql
                                0
                              2. Non...
                                0
                              3. Normal. J'ai beau regarder dans la liste, je ne vois pas de fonction mysql_init()
                                0
                            2. Finalement, après avoir bidouillé le code plusieurs fois, j'ai réussi à avoir ce que je voulais. Je le met donc en ligne pour en faire profiter tout le monde :

                              <?php
                              $link = mysql_connect('SERVEUR', 'NOM', 'MOT DE PASSE');
                              mysql_select_db("BASE DE DONNEE", $link);
                              
                              $req = 'SELECT * FROM connectes WHERE username="'.$_SESSION['username'].'" ' or die (mysql_error());
                              $result = mysql_query($req, $link) or die (mysql_error()); 
                              
                              $donnees = mysql_num_rows($result);
                              echo $donnees;
                              echo " // ";
                              if ($donnees == 0) // L'IP ne se trouve pas dans la table, on va l'ajouter.
                              {
                              echo "il faut creer !";
                              $sql = 'INSERT INTO connectes VALUES ("", "'.$_SESSION['id'].'", "'.$_SESSION['username'].'", "1", "'. $_SERVER['REMOTE_ADDR'] . '", "' . time() . '")';
                              	$requete = mysql_query($sql) or die(mysql_error());
                              }
                              if ($donnees == 1) // L'IP ne se trouve pas dans la table, on va l'ajouter.
                              {
                              echo "existe deja";
                              $sql = "UPDATE connectes SET timestamp='".time()."' WHERE username='".$_SESSION['username']."' ";
                              $requete = mysql_query($sql) or die(mysql_error());
                              }
                              
                              // -------
                              // ÉTAPE 2 : on supprime toutes les entrées dont le timestamp est plus vieux que 5 minutes.
                              
                              // On stocke dans une variable le timestamp qu'il était il y a 5 minutes :
                              $timestamp_5min = time() - (60 * 5); // 60 * 5 = nombre de secondes écoulées en 5 minutes
                              mysql_query('DELETE FROM connectes WHERE timestamp < ' . $timestamp_5min);
                              
                              $sql = "DELETE FROM connectes WHERE timestamp<".$timestamp_5min." ";
                              $select = "SELECT * FROM connectes WHERE timestamp<".$timestamp_5min." "; 
                              $query = mysql_query($select) or die(mysql_error());
                              
                              
                              // -------
                              // ÉTAPE 3 : on compte le nombre d'IP stockées dans la table. C'est le nombre de visiteurs connectés.
                              $retour = mysql_query('SELECT COUNT(*) AS nbre_entrees FROM connectes');
                              $donnees = mysql_fetch_array($retour);
                              
                              
                              // Ouf ! On n'a plus qu'à afficher le nombre de connectés !
                              if($donnees['nbre_entrees'] > 1 )
                              {
                              echo '<p>' . $donnees['nbre_entrees'] . ' utilisateurs connectés</p>';
                              }
                              
                              else
                              {
                              echo '<p>' . $donnees['nbre_entrees'] . ' utilisateurs connectés</p>';
                              }
                              ?> 

                              0