Bonjour à tous,
Dans le cadre de la formation sur la POO je suis arrivé au stade où la page d'accueil du blog peut afficher la liste de tous les articles avec leur catégorie respective ainsi que la liste de toutes les catégories. Enfin cela devrait.
Si j'utilise uniquement la fonction pour la liste des articles j'obtiens bien cette liste. De même si je n'utilse que la fonction pour afficher les catégories pas de problème.
Toutefois dès que j'utilise c'est deux fonctions simultanément simultanément j'obtiens une erreur fatal lors de l'appel à la deuxième, quelqu'elle soit.

    <!-- pages/home.php -->
    <div class="row">

    <div class="col-sm-8">
        <?php foreach(\App\Table\Article::getLast() as $post): ?>
            <h2><a href="<?= $post->url ?>"><?= $post->title ?></a></h2>
            <p><?= $post->excerpt ?></p>
            <p><em><?= $post->categorie; ?></em></p>
        <?php endforeach ?>
    </div>

    <div class="col-sm-4">
        <ul>
            <?php foreach(\App\Table\Categorie::getAll() as $category): ?>
                <li><a href="<?= $category->url; ?>"><?= $category->titre; ?></a></li>
            <?php endforeach ?>
        </ul>
    </div>
</div>

Donc lors de l'appel de la méthode getAll() de Categorie j'obtiens

Fatal error: Call to a member function query() on null in C:\xampp\htdocs\Lab\BlogPOO\app\Database.php on line 45

Notice: Undefined variable: pdo in C:\xampp\htdocs\Lab\BlogPOO\app\Database.php on line 41

Je comprends que la méthode query() définie dans Database ne reçoit aucun statement et que c'est pour cela que la variable pdo reste indéfinie.

Ce que je ne comprends pas par contre c'est pourquoi ce statement n'est pas envoyé. Je n'arrive à voir où se situe le problème.

Merci d'avances pour vos conseils

12 réponses


Carouge10
Réponse acceptée

Dans la fonction getPDO il faut retourner $this->pdo;

Explication du code actuelle: si $this->pdo !== NULL alors je retourne $pdo. Ok mais $pdo n'existe pas puisqu'on n'est pas passer dans la condition

bibi427
Auteur
Réponse acceptée

effectivement Coarouge10 s'était bien ça getPDO retournait $pdo au lieu de $this->pdo

connected
Réponse acceptée

D'accord, maintenant

ta méthode getPDO() doit retourner $this->pdo :

Remplace :

return $pdo;

par

return $this->pdo;

Bonjour,

L'erreur se situe surement dans le fichier Database.php vers les 45 et/ou 41.
Peut-on avoir le code du fichier en question ?

Vous peuvez donner un extrait du code du database.php

bibi427
Auteur
<?php

  namespace App;

  use \PDO;
  class Database{
      private $db_name;
      private $db_user;
      private $db_pass;
      private $db_host;
      private $pdo;

      public function __construct($db_name, $db_user = 'root', $db_pass = 'root', $db_host = 'localhost'){
          $this->db_name = $db_name;
          $this->db_user = $db_user;
          $this->db_pass = $db_pass;
          $this->db_host = $db_host;
      }

      private function getPDO(){

          if($this->pdo === null){
              try{
                  $pdo = new PDO('mysql:dbname=bmid_blog;host=localhost', 'root', 'root');
              }catch (PDOException $e){
                  echo 'Connection failed: ' . $e->getMessage();
              }
              $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
              $this->pdo = $pdo;
          }
          return $pdo;
      }

      public function query($statement, $class_name){
          $req = $this->getPDO()->query($statement);
          $data = $req->fetchAll(PDO::FETCH_CLASS, $class_name);
          return $data;
      }

      public function prepare($statement, $attributes, $class_name, $one = false){
          $req = $this->getPDO()->prepare($statement);
          $req->execute($attributes);
          $req->setFetchMode(PDO::FETCH_CLASS, $class_name);

          if($one){
              $data = $req->fetch();
          }else{
              $data = $req->fetchAll();
          }
          return $data;
      }

  }

Bonjour,

est-ce que tu peux aussi nous donner la classe de la table Article et/ou Categorie ?

bibi427
Auteur
    <?php
// app/Table/Articles.php

namespace App\Table;

use App\App;

class Article{

    public static function getLast(){
        return App::getDb()->query("
            SELECT articles.id, articles.title, articles.content, categories.titre as categorie
            FROM articles
            LEFT JOIN categories
            ON category_id = categories.id
            ", __CLASS__);
    }

    //fonction (méthode magique) qui permet d'appeler une fonction comme une propriété
    public function __get($key){
        $method = 'get' .ucfirst($key);
        $this->$key = $this->$method(); // permet de n'appeller la méthode qu'une seule fois
        return $this->$key;
    }

    public function getUrl(){
        return 'index.php?p=article&id=' . $this->id;
    }

    public function getExcerpt(){
        $html = '<p>'. substr($this->content, 0, 100) .'...</p>';
        $html .= '<p><a href="'. $this->getUrl() .'">Voir la suite</a></p>';
        return $html;
    }

}
bibi427
Auteur
<?php
//app/Table/Categorie.php
namespace App\Table;

use App\App;

class Categorie{

    private static $table = 'categories';
    //private static $table = 'articles';

    public static function getAll(){
        return App::getDb()->query("
            SELECT *
            FROM " . self::$table . "
            ", __CLASS__);
    }

    public static function getUrl(){
        //return 'index.php?p=categorie&id=' . $this->id;
        return 'index.php?p=categorie&id=1';
    }

    public function __get($key){
        $method = 'get' .ucfirst($key);
        $this->$key = $this->$method(); // permet de n'appeller la méthode qu'une seule fois
        return $this->$key;
    }
}

Que renvoie App::getDb(), une instance de Database ? ou bien PDO ? Je suppose que ça renvoie Database, si c'est le cas tu peux faire :

App::getDb()->getPDO()->query(...);
bibi427
Auteur

App::getBd est bien une instance de Database
Pour App::getDb()->getPDO->query()
Il n'aime pas trop car getPDO() est une méthode privée de Database.

bibi427
Auteur

En la passant en public je tombe sur les même erreur qu'ititialement