Bonjour,

Je suis en train de suivre le tuto POO de grafikart, et je rencontre un problème au niveau de la vidéo 18 (en précisant que j'ai déjà commencé le refactoring fait dans la vidéo 19 en espérant que je comprendrais le problème).

En gros je me retrouve avec l'erreur suivante :

Catchable fatal error: Argument 1 passed to Core\Table\Table::__construct() must be an instance of Core\Database\Database, none given in /volume1/web/catrescue/admin/core/table/table.class.php on line 10

Voici ma class App.php

<?php

    use Core\Config;
    use Core\Database\mysqlDatabase;

    class App {
        public $title = "CatRescue Admin";
        private static $_instance;
        private static $db_instance;

        public static function getInstance() {
            if(is_null(self::$_instance)) {
                self::$_instance = new App();
            }
            return self::$_instance;
        }
        public static function load() {
            session_start();
            require ROOT . 'app/autoloader.class.php';
            App\Autoloader::register();
            require ROOT . 'core/autoloader.class.php';
            Core\Autoloader::register();
        }

        public function getTable($name) {
            $class_name = 'App\\Table\\' . ucfirst($name) . 'Table';
            $db = $this->getDb();
            return new $class_name($db);
        }
        public static function getDb() {
            $config = Config::getInstance(ROOT . 'config/config.php');
            if(self::$db_instance === null) {
                self::$db_instance = new mysqlDatabase($config->get('db_name'), $config->get('db_user'), $config->get('db_pass'), $config->get('db_host'));
            }
            return self::$db_instance;
        }
    }

Et ici le code de ma class Core\Table\Table.php

<?php
    namespace Core\Table;
    use Core\Database\Database;

    class Table {

        protected $table;
        protected $db;

        public function __construct(Database $db) {
            echo '<pre>';
            var_dump($db);
            echo '</pre>';
            $this -> db = $db;
            if(is_null($this->table)) {
                $parts = explode('\\', get_class($this));
                $class_name = end($parts);
                $this -> table = lcfirst(str_replace('Table', '', $class_name));
            }
        }

        // public function getAll() {
        //     return $this->db->query("SELECT * FROM {$this->table}");
        // }
    }

Le var_dump de $db dans le construct de table me retourne ceci :

object(Core\Database\mysqlDatabase)#3 (5) {
  ["db_name":"Core\Database\mysqlDatabase":private]=>string(9) "catrescue"
  ["db_user":"Core\Database\mysqlDatabase":private]=>string(4) "root"
  ["db_pass":"Core\Database\mysqlDatabase":private]=>string(0) ""
  ["db_host":"Core\Database\mysqlDatabase":private]=>string(9) "localhost"
  ["pdo":"Core\Database\mysqlDatabase":private]=>NULL
}

Le tout étant appelé comme ci-dessous :

<?php
    define('ROOT', __DIR__ . '/');
    require ROOT . '/app/app.class.php';
    App::load();
    $app = App::getInstance();
    $posts = $app -> getTable('Cats');
    var_dump($posts->getAll());
    // le getAll() étant dans ma class App\Table\postsTable qui a en extends ma class Core\Table\Table

Et donc ce que je ne comprends pas c'est qu'il demande une instance de Core\Database\Database et qu'on lui envoie l'instance de Core\Database\mysqlDatabase qui a en extends la class Database et dans la vidéo ça fonctione.

Merci d'avance pour vos réponses.

6 réponses


Elv
Auteur
Réponse acceptée

Merci de ta réponse !
Finalement j'ai résolu le problème en poursuivant la vidéo Refactoring, car par la suite on passe en paramètre CLASS le fichier entity correspondant à la table appelée plutôt que la class table en cours.
Ce qui au final est plus pratique car l'utilisation des entity clarifie pas mal le tout :)

Normal tu dis que c'est une instance de Database hors que tu lui injecte mysqlDatabase donc remplace par mysqlDatabase dans le constructde ta classe Table

Elv
Auteur

Merci de ta réponse, j'avais déjà essayé ceci et voilà ce qu'il me retourne :

object(Core\Database\mysqlDatabase)#3 (5) {
  ["db_name":"Core\Database\mysqlDatabase":private]=>
  string(9) "catrescue"
  ["db_user":"Core\Database\mysqlDatabase":private]=>
  string(4) "root"
  ["db_pass":"Core\Database\mysqlDatabase":private]=>
  string(0) ""
  ["db_host":"Core\Database\mysqlDatabase":private]=>
  string(9) "localhost"
  ["pdo":"Core\Database\mysqlDatabase":private]=>
  NULL
}
Catchable fatal error: Argument 1 passed to Core\Table\Table::__construct() must be an instance of Core\Database\mysqlDatabase, none given in /volume1/web/catrescue/admin/core/table/table.class.php on line 10

en mettant :

    namespace Core\Table;
    use Core\Database\mysqlDatabase;

    class Table {

        protected $table;
        protected $db;

        public function __construct(mysqlDatabase $db) {
            echo '<pre>';
            var_dump($db);
            echo '</pre>';
            $this -> db = $db;
            if(is_null($this->table)) {
                $parts = explode('\\', get_class($this));
                $class_name = end($parts);
                $this -> table = lcfirst(str_replace('Table', '', $class_name));
            }
        }
    }

Dans ta fonction getTable tu fais $this->getDb hors que getDb est en static essaye en mettant self::getDb() dans getTable()

Elv
Auteur

Oui j'ai modifié ça tout à l'heure, mais ce n'était pas ça, en revanche j'ai trouvé l'origine du problème.

Dans ma class mysqlDatabase j'avais une fonction query qui prend en paramètre optionnel un $className pour pouvoir changer le fetchMode en FETCH_CLASS si le paramètre est précisé, dans l'autre cas ça le met en FETCH_OBJ :

        public function query($statement, $className = null, $one = false){
            $req = $this -> getPDO() -> query($statement);
            if($className === null) {
                $req -> setFetchMode(PDO::FETCH_OBJ);
            } else {
                $req -> setFetchMode(PDO::FETCH_CLASS, $className);
            }

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

Et la méthode que j'appelais pour aller chercher mon contenu utilisait la méthode query de ma class mysqlDatabse avec l'option $className précisée et donc passait le fetchMode en FETCH_CLASS. _Dès que je ne précise plus le paramètre ça fonctionne, mais je comprends pas pourquoi, ça voudrait dire du coup que ça ne fonctionnerait plus dès que le fetchMode est en FETCHCLASS ? Mais pourqoi ? J'aimerais quand même pouvoir l'utiliser en FETCH_CLASS ça ne m'arrange pas. ^^

Salut Elv !

J'étais entrain de regarder la vidéo et j'ai eu le même soucis que toi. En fait, le problème vient du fait que PDO appelle le constructeur sans paramètres. Du coup, il lui est impossible de créer la classe que tu lui demandes !

Tu peux donc spécifier ceci pour ton constructeur:

function __construct(mysqlDatabase $db = null) {

Cependant, un autre problème survient: Les objets créés par PDO ne pourront pas passer d'appels à la DB, puisque leur variable $db sera null.