Partage
  • Partager sur Facebook
  • Partager sur Twitter

Pourquoi une requête SQL retourne true (booléen) ?

Fatal/Uncaught Error: Call to a member function fetch() on boolean

Sujet résolu
    22 juillet 2018 à 15:57:10

    Bonjour,

    J'ai l'impression d'être victime d'un bug, si j'en crois ce post : https://stackoverflow.com/questions/6208156/why-does-mysql-query-return-true-with-a-select-statement

    Pouvez-vous m'aider ?

    function BDD_co(){
    	require'admin/passwords.php';
    	try{$BDD = new PDO('mysql:host=sabouacont777.mysql.db;dbname=sabouacont777;charset=utf8',$BDD_login,$BDD_password);
    		$BDD -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);}
    	catch(PDOException $e){echo'Erreur : '.$e->getMessage();}
    	return $BDD;
    }
    function BDD_req($BDD,$req){return $BDD->query("$req") OR die('<p>Erreur : '.$e->getMessage().'</p>');}
    $req="SELECT p.date date, p.time heure, p.titre_".$PAGE['lng']." titre, p.corps_".$PAGE['lng']." corps FROM publications p INNER JOIN categories c ON p.id_categorie=c.id WHERE p.slug_$URL[0]='$URL[2]' AND c.slug_$URL[0]='$URL[0]/$URL[1]'";
    //Avec une URL bien formée, donne qqch du type :
    $req="SELECT p.date date, p.time heure, p.titre_fr titre, p.corps_fr corps FROM publications p INNER JOIN categories c ON p.id_categorie=c.id WHERE p.slug_fr='1-evola-le-zen' AND c.slug_fr='fr/traductions'";
    //(la requête fonctionne dans phpMyAdmin)
    $BDD=BDD_co();
    if(true): // if(!empty($BDD_publication=BDD_req($BDD,$req))):
    $BDD_publication=BDD_req($BDD,$req);
    $BDD_aa=$BDD_publication->fetch();

    Fatal error: Uncaught Error: Call to a member function fetch() on boolean in /home/***/www/index.php:266 Stack trace: #0 {main} thrown in /home/***/www/index.php on line 266

    -
    Edité par sylvainsab 22 juillet 2018 à 16:02:00

    • Partager sur Facebook
    • Partager sur Twitter
      22 juillet 2018 à 16:39:49

      C'est toi le bug : c'est que ta requête plante.

      Je ne comprends même pas ton code : $e n'existe même pas dans ta fonction BDD_req. Et je ne comprends pas non plus comment, en ayant demandé à PDO de lever une exception en cas d'erreur de requête, tu n'aies rien avant.

      • il faut éviter les or die, de toute façon en mode PDO::ERRMODE_EXCEPTION, par défaut, PHP stoppera déjà l'exécution du script (entre autres)
      • empty sur un PDOStatement, ça ne fonctionnera pas
      • j'espère que n'appelles qu'une fois BDD_co sinon tu vas multiplier inutilement les connexions

      > Tu as oublié de mettre une virgule avant corps, dans : "p.corps_fr corps".

      Ca en fait implicitement un alias (AS sous-entendu).

      -
      Edité par julp 22 juillet 2018 à 16:49:04

      • Partager sur Facebook
      • Partager sur Twitter
        22 juillet 2018 à 16:41:03

        Bonjour,

        Ta requête ne retourne pas de booléen si elle fonctionne, mais elle a un problème de syntaxe donc elle te retourne FALSE, d'où le booléen.

        Tu as oublié de mettre une virgule avant corps, dans : "p.corps_fr corps".

        julp a écrit:

        > Tu as oublié de mettre une virgule avant corps, dans : "p.corps_fr corps".

        > Ca en fait implicitement un alias (AS sous-entendu).

        En effet, je suis aussi un bug ! :p

        -
        Edité par Mr.Miel 22 juillet 2018 à 16:56:52

        • Partager sur Facebook
        • Partager sur Twitter
          22 juillet 2018 à 16:48:51

          La requête retourne true, pas false (j'ai vérifié l'autre jour). Elle est correcte et fonctionne telle quelle dans phpMyAdmin (cf la variable $req commentée dans mon premier message). J'ai cet avertissement cependant :

          La sélection courante ne contient pas de colonne unique. Les grilles d'édition, les cases à cocher ainsi que les liens Éditer, Copier et Supprimer ne sont pas disponibles.

          Avez-vous regardé le premier lien que j'ai envoyé, de stack overflow ?

          Edit : ah cool, julp passe par là :p

          • Oui, moi non plus ça ne me plaît pas vraiment ces "or die", j'essayais "or echo" mais ça faisait bugger le script. Qu'est-ce que je peux mettre pour remplacer le die() du coup ? Je l'enlève sans remplacement ?
          • Pour $e je copiais le bout de code du tuto "officiel" : https://openclassrooms.com/fr/courses/918836-concevez-votre-site-web-avec-php-et-mysql/914293-lire-des-donnees#/id/r-2175084
          • Oui en effet je n'appelle BDD_co() qu'une seule fois. À vrai dire j'avais enlevé la fonction du script mais je l'ai remise car j'ai vu qu'un temps trop long de connexion à la BDD pourrait être cause de l'erreur que je rencontre (dans le lien stack overflow je crois).

          -
          Edité par sylvainsab 22 juillet 2018 à 16:57:38

          • Partager sur Facebook
          • Partager sur Twitter
            22 juillet 2018 à 16:52:44

            var_dump($BDD_publication); déjà pour confirmer/infirmer ?

            Si c'est vrai, c'est bien la première fois que je vois TRUE renvoyé.

            > Je l'enlève sans remplacement ?

            Oui.

            > Pour $e je copiais le bout de code du tuto "officiel"

            Sauf que c'est pour la connexion (pas plus utile d'ailleurs). Tu vois bien pour que ça ait un sens, qu'il aurait fallu un try/catch.

            -
            Edité par julp 22 juillet 2018 à 17:01:25

            • Partager sur Facebook
            • Partager sur Twitter
              22 juillet 2018 à 16:59:04

              Affirmatif ! C'est ce que j'avais vérifié l'autre jour :

              bool(true)



              • Partager sur Facebook
              • Partager sur Twitter
                22 juillet 2018 à 17:00:39

                Salut,

                Le true est à cause de ton or die qui est bien inutile ici.

                • Partager sur Facebook
                • Partager sur Twitter
                le bienfait n'est jamais perdu
                  22 juillet 2018 à 17:05:22

                  Non, puisque la deuxième partie du or n'est pas évaluée si la première est vraie et si le die (= fin immédiate du script) était évalué tu n'irais pas jusqu'au return (et encore moins au var_dump situé après l'appel).

                  Je retourne me coucher. Une raison de plus de ne pas utiliser or die.

                  -
                  Edité par julp 22 juillet 2018 à 17:16:48

                  • Partager sur Facebook
                  • Partager sur Twitter
                    22 juillet 2018 à 17:10:17

                    Pour en être sûr j'ai testé et avec un "or die" j'avais true.

                    https://3v4l.org/co6rC

                    -
                    Edité par WillyKouassi 22 juillet 2018 à 17:12:54

                    • Partager sur Facebook
                    • Partager sur Twitter
                    le bienfait n'est jamais perdu
                      22 juillet 2018 à 17:12:45

                      Je confirme, le type de la variable change en retirant le or die :

                      object(PDOStatement)#2



                      • Partager sur Facebook
                      • Partager sur Twitter
                        22 juillet 2018 à 17:15:26

                        Avec une bonne gestion d'erreurs avec PDO::ATTR_ERRMODE , on a même pas besoin de or die, je ne sais pas si c'est un tuto sur ce site mais on voit trop de codes avec PDO qui nous plaquent des or die à chaque requête. Même le try/catch ton code fonctionnera sans.

                        -
                        Edité par WillyKouassi 22 juillet 2018 à 17:17:32

                        • Partager sur Facebook
                        • Partager sur Twitter
                        le bienfait n'est jamais perdu
                          22 juillet 2018 à 17:33:53

                          Ça m'arrange. Je suis pas fan non plus de or die et de ses gros sabots. J'aurais du me rendre compte tout seul qu'avec try/catch il n'y en a pas besoin !

                          Et oui, il me semble que c'est un ancien tuto officiel, ou alors une mauvaise habitude des dev PHP...

                          • Partager sur Facebook
                          • Partager sur Twitter
                            22 juillet 2018 à 17:47:06

                            Tu peux aussi te passer du try/catch surtout si c'est pour faire que $e->getMessage(), par défaut le moteur de PHP donne plus d'infos quand une erreur survient (la trace d'exécution) et c'est très utile quand tu veux déboguer.

                            • Partager sur Facebook
                            • Partager sur Twitter
                            le bienfait n'est jamais perdu
                              22 juillet 2018 à 17:57:20

                              Et du coup tu remplacerais par quoi tout ce try/catch pour que PHP gère les erreurs MySQL ?
                              • Partager sur Facebook
                              • Partager sur Twitter
                                23 juillet 2018 à 20:59:43

                                Je mettrais seulement mon new PDO + setAttribute dans ton cas.. Il n'a jamais été dit que sans try/catch la gestion des erreurs ne se fait pas.

                                • Partager sur Facebook
                                • Partager sur Twitter
                                le bienfait n'est jamais perdu
                                  23 juillet 2018 à 21:16:55

                                  Idem, la seule raison de mettre un try/catch "autour" du new PDO ce serait de ne pas leaker les identifiants de connexion si jamais display_errors était à on en production, ce qui serait un non-sens total mais malheureusement ça s'est déjà vu chez plusieurs "hébergeurs".

                                  En temps normal, ça n'apporte strictement rien de catcher l'exception pour faire un die de $e->getMessage. Pourquoi ? Pour la simple et bonne raison que ce die en fait moins que ce que PHP ferait déjà par défaut : une exception non-gérée (ni try/catch ni set_exception_handler) étant transformée en erreur fatale, ce qui lui vaut d'être, comme toute erreur :

                                  • affichée si et seulement si le display_errors est à on
                                  • logguée dans tous les cas
                                  • (+ fin du script dans la foulée)

                                  Avec un die($e->getMessage()); d'une part tu fournis éventuellement des informations au client qui n'en à que faire ou, au contraire, pourrait l'aider à attaquer ton site ; d'autre part, elle ne s'en retrouve pas logguée et, en production, ne pas avoir trace d'une anomalie, c'est totalement aberrent.

                                  -
                                  Edité par julp 23 juillet 2018 à 21:28:56

                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  Pourquoi une requête SQL retourne true (booléen) ?

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                  • Editeur
                                  • Markdown