Bonjour,

Je pense m'emmeller les pinceaux, je galère un peu en faite, je suis même pas sur de ce que je suis en train de faire.

J'ai suivit la formation de POO, mais y a trop de code à assimiler d'un coup et du coup j'ai du mal à m'en sortir une fois que je suis tout seul. (Et n'ayant pas les sources, ça n'aide pas :P )

Bref en gros, je suis en train de faire un blog. A ce blog, pour le moment j'ai fait la connexion à la BDD, l'autoloader et je suis en train de faire la class Articles qui me permettra d'y mettre toutes mes fonctions en rapport avec les articles.

L'autoloader, c'est le même que dans la formation, il ne change pas.

Pour ma class Database, la voici :

<?php

class Database {

    private $db_name;
    private $db_user;
    private $db_password;
    private $db_host;
    private $pdo;
    private static $instance = null;

    public function __construct($db_name = DB_NAME, $db_user = DB_USER, $db_password = DB_PASSWORD, $db_host = DB_HOST) {

      $this->db_name = $db_name;
      $this->db_user = $db_user;
      $this->db_password = $db_password;
      $this->db_host = $db_host;

      $this->pdo = new PDO('mysql:host='.$this->db_host.';dbname='.$this->db_name.';charset=utf8', $this->db_user, $this->db_password);
      $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    }

    public static function getInstance()
    {  
      if(is_null(self::$instance))
      {
        self::$instance = new Database();
      }
      return self::$instance;
    }
  }

  ?>

Et là où je galère, c'est que je suis même pas sur que le singleton devrait être ici, je m'y perds totalement. Parce que je suis pas sûr de ce que je fais par rapport à la classe Articles qui ressemble à ça :

<?php

class Articles {

    public function query($query)
    {
      return $this->pdo->query($query);
    }

    public function countThis($arg)
    {
      return count($this->pdo->query('SELECT * FROM articles WHERE statut = "'.$arg.'"')->fetchAll());
    }

  }

  ?>

Et dans mon fichier de rendu, j'ai quelque chose comme ça :

$db = Database::getInstance();
$query = $db->query('SELECT * FROM articles WHERE statut <> "Corbeille"');
$draft = $db->countThis('Brouillon');

Mais évidemment, il me sort une erreur avec la fonction query (ce qu'il ne faisait pas quand j'avais tout dans la même classe)

Je sais pas si c'est très clair, moi même je m'y perds comme j'ai dit ^^'
Mais j'espère sincèrement que quelqu'un pourra m'aider. J'ai toujours programmer en procédural, ça fait maintenant plusieurs années, et j'ai jamais eu de problèmes en PHP, mais depuis que je travail avec la POO, j'ai l'impression de devoir tout réapprendre, que toutes ces années n'ont servies à rien :/

Bref merci, n'hésitez pas si vous avez des questions, je vous répondrai

31 réponses


Damarus
Réponse acceptée

Non pas uniquement la connexion à la BDD, tu peux te créer un singleton pour charger un fichier de config.
Effectivement on pourrait faire ce que tu dis mais l'idée est de rendre les class les plus indépendantes possible. Peut-importe l'application dans laquelle elle est executée, peut importe la class qui l'appelle. Nous devons créer une class générique qui fonctionnera toujours.

L'idée du singleton est d'être certain que la classe de sera instanciée qu'une seule fois, peut importe le nombre de fois où on l'appelle peut importe d'où on l'appelle.

Je pense qu'il est facile de penser "un peu de rigueur dans le code est c'est bon, on le sais qu'elle est chargée dans l'index", oui mais je trouve que la class devient moins souple à utiliser s'il faut faire attention à ce genre de détail. La class doit être instancié qu'une seule c'est à la class de gérer ça de manière à être totalement indépendante.

On peut imaginer aussi des class qui ne doivent être instancier qu'une seule fois sinon l'application plante, j'ai pas d'exemple là comme ça mais pourquoi pas.

Damarus
Réponse acceptée

Alors l'idée de Grafikart est de créer une class par Table contenu dans la BDD. Une class PostsTable, une class CategoriesTable et une class UsersTable. Il souhaite également automatiser l'appel de ces class.
Par exemple : "Donne moi la table Post", le système de chargera de renvoyer la class PostsTable.
C'est ce qu'il fait dans son fichier index.php avec le code

$posts = $app->getTable('Posts'));

C'est là que le cerveau commence à briller ^^.

Que fait la méthode getTable dans la class App. Déjà elle prend comme paramètre le nom de la table que l'on souhaite récupèrer.

public function getTable($name) {
    $class_name = '\\App\\Table\\' . ucfirst($name) . 'Table'; // Il récupère le nom complet de la class à charger, namespace compris.
    //Donc ici par exemple, $class_name = \App\Table\PostsTable
    return new $class_name(); // Là on instanci la class demandé, et on retourne l'instance. 
}

Donc si on reviens dans notre index.php, c'est comme si on avait fait.

$posts = new \App\Table\PostsTable();

Sauf que tout est gérer automatiquement, le namespace et les conventions de nommage (ici ucfirst());
Par contre on a instancier PostsTable, ok mais qu'est-ce qu'il c'est passé. Regardons ça dans notre fichier PostsTable.

class PostsTable extends Table 
{
}

Et c'est tout, on vois par contre que PostsTable extend de la class Table. Donc le constructeur de Table va être exécuté. Continuons regardons ça, c'est le code que tu as mis.

public function __construt(Database $db) {
    $this->db = $db //Ici on récupère une instance de la class Database qu'on stocke dans $this->db, cette variable étant déclarée protected elle sera disponible pour les class enfants, comme PostsTable, UsersTable ou CategoriesTable

    if (is_null($this->table)) { //Si $this->table ne contient rien
        $parts = explode('\\', get_class($this)); // Ici $this contient la class enfant car le constructeur est appellé par l'enfant donc $this est un objet de \App\Table\PostsTable. Il explode ce nom par des \
        $class_name = end($parts); // Récupère le dernièr élément de $parts. Donc ici $class_name = 'PostsTable';
        $this->table = strtolower(str_replace('Table', '', $class_name)); // Ici on replace la chaine de carectere Table par du vide, donc au final $this->table = Posts !!
}

Et oui tout pour qu'on final $this->table contienne 'Posts', donc le nom de table dans la base données ! Oui le but est de deviner le nom de la table dans la base de donnée à partir du nom de la class chargée.

Et du coup vu que $table est définie comme protected dans la class PostsTable on aura accès à $this->table qui contient de la table !

Et par conséquent dans chaque class qui étend de Table on connais le nom de table à utiliser, si c'est pas beau ça !

Enjoy

Damarus
Réponse acceptée

Non ce n'est pas le namespace là, Database c'est le type qu'on attend. On oblige a ce que $bd soit une instace de Database.
Avec le namespace ça donnerai \App\Database.

On pourrai très bien mettre

class MaSuperClass {
  public function __construct(Array $a) {
  }
 }

$tableau = [1,2,3,4];
$chaine = 'Du texte';

$instance = new MaSuperClass(); //Ça va planter car il n'y a pas de paramètre fourni
$instance2 = new MaSuperClass($chaine); //Ça va planter car le paramètre n'est pas un tableau
$instance3 = new MaSuperClass($tableau); //Ça marche car tout va bien

Effectivement tu peux faire sans namespace mais avec le temps tu y viendra même si tu es le seul sur le code c'est utile quand tu charges des librairies. Tout est bien compartitionnés et aucun risque de conflit. Mais bon c'est certain pour le moment oubli y a plus important pour un début en POO :)

Je te peux t'assurer que le jour où tu aura le déclic de la POO tu ne regrettera pas de d'être arracher les neuronnes :)

Damarus
Réponse acceptée
Damarus
Réponse acceptée

Plus précisement l'injection de dépendance c'est le fait de forcer à avoir un objet d'une classe particulière.
Mais le fait de forcer un type de variable comme Array ou autre c'est le "typage explicite" et ça fontionne aussi en procédural sur de simple fonctions.

http://php.net/manual/fr/language.oop5.typehinting.php

Damarus
Réponse acceptée

Un plaisir de partager, je suis passé par cette dure transition aussi. Je sais précisément ce que c'est et à quel point c'est dur ^^.

Ah bin oui avec ton Edit je comprend mieux xD.
Ça viens justement du fait que tu passe une instance PDO. Dans ta class Table tu fais.

public function query($statement, $attributes = null, $one = false) {
      if($attributes) {
        $this->db->prepare($statement,  // Et bien non vue que tu passes un objet PDO tu appelles directement le prepare de PDO et non de Database.
                           $attributes,
                           get_class($this).'Entity',
                           $one
                          );
      }
      ....
}      

Ton $this->db, n'est pas une instance de Database vu que tu lui passe un objet PDO, donc il lance directement la méthode prépare de PDO et non de Database. Et là ça concorde avec l'erreur que tu obtiens, tu lui donnes 4 paramètres alors qu'il en attend 2.

Donne un objet Database dans ton $this->db et ça devrait aller.

Damarus
Réponse acceptée

Non non, dans ton constructeur de table

public function __construct($db) {
      $this->db = $db;
      if (is_null($this->table))
        $this->table = strtolower(get_class($this));
    }

Tu disais que tu envoi directement un objet PDO, tout le souci est là. Il faut que ce soit un objet Database.
Actuellement c'est le prepare de PDO qui est lancé et qui te fais une erreur or tu dois lancer celui de Database. $this->$db doit être une instance de Database. C'est pour ça que dans sa vidéo il oblige le paramètre du constructeur avec

public function __construct(Database $db) {
    }

Bonsoir,

Il y a déjà un problème avec la connexion à la BDD, je pense que $db est null.
Quelle est l'erreur qui est affiché ?

Salut,

dans un premier temps pour moi ta classe Database est bonne.

En revanche j'ai l'impression qu'ensuite tu te mélanges les variables $this.
Avant d'aller plus loin j'aimerai être sur que tu as bien compris ce que représente cette variable au sein d'une classe.

Genki
Auteur

Si je remet tout le contenu de la class Articles dans la class Database, ça fonctionne. La connexion se fait bien en tout cas

Genki
Auteur

This fait référence à une variable créer précédemment dans la classe (comme private $db_user)
J'avais aussi tenté un extends Database, j'ai testé pleins de trucs, mais rien n'a fonctionné :/

Pour moi la class database est erronée car il n'y a aucun lien entre $this->pdo et $instance et pas de return dans le constructeur.

Bonjour,

alors désolé je n'ai jamais regardé les vidéos je viens juste de passer dessus rapidement. De ce que j'ai vu, il te manque une classe "App" qui contiendras le lien spécifique à ta BDD :

<?php

namespace App;

class App
{
    const DB_NAME = 'machin';

    const DB_USER = 'bidule';

    const DB_PASS = 'chouette';

    const DB_HOST = 'truc';

    /**
     * @var \App\Database $database
     */
    private static $database;

    public static function getDb()
    {
        if (null === self::$database) {
            self::$database = new \App\Database(self::DB_NAME, self::DB_USER, self::DB_PASS, self::DB_HOST);
        }

        return self::$database;
    }
}

Ensuite dans ta classe "Article" tu dois avoir :

<?php

namespace App\Table;

class Article
{
    public static function countThis($statut)
    {
        $statement = \App\App::getDb()->prepare('SELECT COUNT(id) FROM articles WHERE statut = :statut');

        $statement->execute(['statut' => $statut]);

        return $statement->fetchColumn();
    }

    // Tes autres méthodes ici...
}

Bon j'ai pas du tout tester le code je fais un peu tout de mémoire donc désolé si ça passe pas directement. Pour ce qui est du passage du procédural à l'objet ne t'inquiète pas, c'est une gymnastique à prendre et tu verras que ça te facilitera vraiment la vie au fur et à mesure que tu en feras :).

En fait à chaque fois que tu auras besoin de récupérer le lien vers la base de données tu auras simplement à appeler

\App\App::getDb()

qui te retournera l'objet PDO instancié et prêt à fonctionné.

Tu ne peux pas utiliser les méthodes présentes dans ta classe Article sur un objet de type Database. Voici comment tu devrais utiliser la classe Database et Article.

<?php 

class Database 
{ 
    // Ton code est bon ici (quoi que, généralement, on essaye de mettre les constructeurs privés
    //lorsqu'on utilise le patron « Singleton ».

    // Puisque $this->pdo est privé, alors on créé un accesseur.
    public function getPDO() 
    {
        return $this->pdo;
    }
}

class Article 
{
    // Cependant, tu devrais avoir besoin ta connexion à la base de données qui, 
    // je te le rappel est déclaré dans la classe Database.
    private $database = Database::getInstance();

    public function query($query)
    {
        // $this->database est de type Database, par conséquent, tu as accès à toutes ses méthodes publics.
        return $this->database->getPDO()->query($query);
    }

    // Tu peux adapter le reste...
}

$article = new Article();
$query = $article->query('SELECT * FROM articles WHERE statut <> "Corbeille"')
$draft = $article->countThis('Brouillon');

?>

Tu pourrais passer la connexion en paramètre du modèle, mais c'est toi qui vois, ça peut être utile comme ça ne peut pas l'être pour plus tard.

Je te laisse penser à la suite pour la réutilisation de code. :-)

Ramz.

Genki
Auteur

Ok je pense pas avoir tout compris ^^'

Voilà un peu plus de précision, si je réunis tout dans la même class tel que :
(Notons que DB_NAME, DB_USER etc..., sont des constantes créées dans mon fichier config.php, donc pas de problème de ce côté là)

<?php

  /**
  * Class de connexion à la base de données
  */

  class Database {

    private $db_name;
    private $db_user;
    private $db_password;
    private $db_host;
    private $pdo;
    private static $instance = null;

    public function __construct($db_name = DB_NAME, $db_user = DB_USER, $db_password = DB_PASSWORD, $db_host = DB_HOST) {

      $this->db_name = $db_name;
      $this->db_user = $db_user;
      $this->db_password = $db_password;
      $this->db_host = $db_host;

      $this->pdo = new PDO('mysql:host='.$this->db_host.';dbname='.$this->db_name.';charset=utf8', $this->db_user, $this->db_password);
      $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    }

    public static function getInstance()
    {  
      if(is_null(self::$instance))
      {
        self::$instance = new Database();
      }
      return self::$instance;
    }

    public function query($query)
    {
      return $this->pdo->query($query);
    }

    public function countThis($arg)
    {
      return count($this->pdo->query('SELECT * FROM articles WHERE statut = "'.$arg.'"')->fetchAll());
    }
  }

    ?>

Avec toujours ça dans mon rendu :


  $db = Database::getInstance();
  $query = $db->query('SELECT * FROM articles WHERE statut <> "Corbeille"');
  $draft = $db->countThis('Brouillon');
  $published = $db->countThis('Publie');
  $trash = $db->countThis('Corbeille');

Tout marche, j'ai bien le résultat de la requête, le countThis fonctionne impec.
Ce que j'aimerai juste c'est séparer query et countThis dans une class Articles rien de plus :/
Mais j'ai du mal, je m'embrouille avec le singleton, avec le getInstance() etc.. :S

Effectivement @Ramzz1994 car dans la classe "Database" tu devrais avoir ces méthodes "query", "prepare" exposée en "public". Et du coup tu ne devrais surtout pas te retrouver avec la méthode "query" dans ton "model".

Ça dépend toujours de ce qu'il voulait en faire. C'est vrai que dans ce cas-ci, la méthode « query » représente un cas générique, alors ce n'est pas très pertinent. Quoi qu'il en soit, ce n'était pas vraiment le point de ma réponse, je voulais juste lui montrer l'utilisation du singleton.

Je ne savais pas ce que Grafikart avait proposé dans son tutoriel...

Si j'ai bien compris ce que tu veux faire c'est que Article hérite de Database, ainsi les objet Article auront accés aux methode de Database (commun a tous les objets model) ainsi qu'a des methode spécifique a l'article comme getCount

Pour cela tu dois utilisé extends. Cela donnera un truc du genre

class Article extends Database {
    public function countThis($arg){
        // Ta methode
    }
}

$article = Article::getIntance();
$result = $article->query('SELECT * FROM articles WHERE statut <> "Corbeille"');
  $draft = $article->countThis('Brouillon');
  $published = $article->countThis('Publie');
  $trash = $article->countThis('Corbeille');

J'espere avoir bien compris ou tu voulais en venir.

Genki
Auteur

Oui mais ce que je comprends pas dans son TP : http://www.grafikart.fr/formations/programmation-objet-php/tp-tables

Il utilise la static App:getDb() puis fait ses requêtes dessus :
App:getDb()->query('SELECT...');

Et je comprends pas ce lien entre getDb et query qui sont pourtant pas dans la même classe.

Il utilise la fonction Query qui se trouve dans la class Database (qui fait le lien grace à getPDO()) en tant que méthode de App:getDb() qui elle se trouve dans la class App.

C'est plus ou moins ce que j'essaye de reproduire. Si bien que maintenant, je comprends même pu à quoi sert le singleton. Je suis vraiment perdu et ça me fou les boules d'en baver autant alors que j'ai vraiment pas de problème en procédural :(

Le singleton te sert à n'avoir qu'une seule instance de la classe Database et donc de ne faire qu'une seule connexion PDO. C'est là toute l'idée du singleton, ne pas créer 36 instances alors qu'une suffit. Du coup on économise en perf.

Genki
Auteur

Ok donc ça j'ai visiblement pas vraiment compris. Le singleton ne sert que pour la connexion à la BDD ?
Pourquoi faire se système d'auto instantiation plutôt que faire juste une fois $db = new Database; dans l'index.php (ce qui amène alors à la connexion à être instancié une fois et tout le long du projet, vu que tout passe par index.php) ?

Genki
Auteur

Ok j'arrive un peu mieux maintenant à faire la distinction. Je regarde encore et encore les vidéos, surtout sur le refactoring où on voit pas mal de code (les sources manquent vraiment :/)

Mais du coup je comprends pas quelque chose
En gros de ce que j'ai compris, le singleton va instancier automatiquement la classe qui va se charger de se connecter à la BDD.
Connexion qui sera transmise en paramètre au moment où on choisira la table/class sur laquelle travailler.

getInstance()->getTable('nom_de_la_classe").

=On initialise la class puis on connecte à la bdd au moment où on envoi en paramètre le nom de la class sur laquelle travailler pour ainsi faire toutes les fonctions qu'on veut.

Mais je ne comprend pas ceci qui se trouve dans la class Table :

protected $table;
protected $db;

public function __construct(Database $db) {
    $this->db = $db // On récupère la connexion à PDO c'est bien ça ?
    // A partir d'ici je comprends pu rien.
    if (is_null($this->table)) {
        $parts = explode('\\', get_class($this)); // $this fait référence à quoi ?
        $class_name = end($parts);
        $this->table = strtolower(str_replace('Table', '', $class_name));
        // A quoi sert ce code au juste ?
}

Pour le moment, je comprends juste pas cette partie là, si quelqu'un peut m'éclairer, merci :)

Genki
Auteur

Ok, tout commence à être clair pour moi, ça vient bon. J'ai reproduit le code en l'adaptant à mes besoins mais y a un mini truc que je comprends toujours pas.

public function __construct(Database $db) {

Database c'est le namespace ? (j'associe ça dans ma tête comme jQuery en faite, comme pour le selecteur $('#global div') avec l'espace qui délimite le conteneur), du coup je comprends pas trop. Bon je n'utilise pas les namespaces, ça peut paraître wtf, mais ça ne fait que m'embrouiller, ça rajoute du code en plus et pour moi trop de problèmes, je suis le seul à utilisé le code et je continuerai de l'être, donc j'en ai pas besoin, mais dans l'idée, si c'est le namespace, pourquoi il est pas relié ? Database\$db
Ou je sais pas ?

Genki
Auteur

« Non ce n'est pas le namespace là, Database c'est le type qu'on attend. On oblige a ce que $bd soit une instace de Database. »

Comment on le sait ça ?? Je trouve rien sur la doc PHP, ni sur les potentiels paramètres de __construct

Pour le coup je connaissais pas ça

Genki
Auteur

Merci beaucoup Damarus pour ton partage de connaissances, ton temps que tu as consacré à me répondre, clairement avec les explications qui vont avec. Tu m'as beaucoup aidé !

Globalement, je vais mettre le sujet en résolu, car j'ai eu à peu près toutes les réponses dont j'avais besoin.
Si je peux grapiller encore juste une petite aide de ta part, ça serai fort aimable, je t'en serai très reconnaissant.

J'ai juste un problème avec query() et prepare().
En gros je veux faire ça :

    public function find($id) {
      return $this->query("SELECT * FROM {$this->table} WHERE id = ?", [$id], true);
    }

Comme dans la formation. Ce bout de code ce trouve dans la class Table à même titre que la fonction query tel que :

public function query($statement, $attributes = null, $one = false) {
      if($attributes) {
        $this->db->prepare($statement,  // donc là, normalement, ça appel la fonction prepare qui se trouve dans la class Database ?
                           $attributes,
                           get_class($this).'Entity',
                           $one
                          );
      }

      else {
        $this->db->query($statement, // et ici la fonction query toujours dans la classe Database ?
                         get_class($this).'Entity',
                         $one
                        );

      }

    }

En commentaire l'appel des fonctions de la classe Database qui se trouve ci dessous :

public function query($statement, $class_name = null, $one = false) {
      $req = $this->getPDO()->query($statement);
      if(is_null($class_name))
        $req->setFetchMode(PDO::FETCH_OBJ);
      else
        $req->setFetchMode(PDO::FETCH_CLASS, $class_name);
      if($one)
        $datas = $req->fetch();
      else
        $datas = $req->fetchAll();
      return $datas;
    }

    public function prepare($statement, $attributes, $class_name = null, $one = false) {
      $req = $this->getPDO()->prepare($statement); // C'est ça que j'ai besoin qu'il execute ! pas le prépare du précédent code !
      $req->execute($attributes);
      if(is_null($class_name))
        $req->setFetchMode(PDO::FETCH_OBJ);
      else
        $req->setFetchMode(PDO::FETCH_CLASS, $class_name);
      if($one)
        $datas = $req->fetch();
      else
        $datas = $req->fetchAll();
      return $datas;
    }

Sur le papier tout à l'air juste, j'ai regrouper au mieux les codes des vidéos (mais j'arrive jamais à voir vraiment si tout correspond bien).
Et pourtant, j'ai un message d'erreur, il execute la fonction prepare comme appartenant à PDO, et non pas la fonction qui se trouve dans la table Database :

Warning: PDO::prepare() expects at most 2 parameters, 4 given

Changer le nom n'y change rien. Donc j'ai du raté un truc :/
Merci !!

EDIT : A noter aussi que dans mon construct de table j'ai ça moi :

    public function __construct($db) {
      $this->db = $db;
      if (is_null($this->table))
        $this->table = strtolower(get_class($this));
    }

Si je met Database $db, il me dit en erreur que c'est une instance de Database qui doit être donné et que moi je donne une instance de PDO. Si ça peut aider.. :/

Genki
Auteur

Ma classe Database :

    public static function getInstance()
    {  
      if(is_null(self::$instance))
      {
        self::$instance = new Database();
      }
      return self::$instance;
    }

    private function getPDO() {
      if($this->pdo === null) {        
        $pdo = new PDO('mysql:host='.$this->db_host.';dbname='.$this->db_name.';charset=utf8', $this->db_user, $this->db_password);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->pdo = $pdo;
      }
      return $this->pdo;
    }    

    public function getTable($name) {
      $class_name = ucfirst($name);
      return new $class_name($this->getPDO());
    }     

Donc au lieu de faire :

return new $class_name($this->getPDO());

Je fais

return new $class_name($this->getInstance());

? Mais c'est bizarre parce que j'ai pas vu Graf le faire dans ses vidéos

Genki
Auteur

Bah oui bah c'est ce que jdis, si je précise Database :

    public function __construct(Database $db) {
      $this->db = $db;
      if (is_null($this->table))
        $this->table = strtolower(get_class($this));
    }

Ca retourne une erreur :

Catchable fatal error: Argument 1 passed to Tables::__construct() must be an instance of Database, instance of PDO given, called in /site/libs/class.Database.php on line 46 and defined in /site/libs/class.Tables.php on line 8

Il faut que tu lui passe une instance de Database et non de PDO.

Genki
Auteur

Si, je viens de regarder la vidéo où il créer la classe Table, et c'est là mon erreur. Lui il a getDb(), c'est son singleton en faite, là ou moi je pensais que getDb() était la connexion à PDO.

Son getDb était = à mon getPDO().
Ce qui est faux en faite, si je met

return new $class_name($this->getInstance()); // donc dans sa vidéo getDb()

Là j'ai pu l'erreur (enfin si, il me dit qu'il trouve pas le fichier ArticlesEntity, mais je l'ai pas créer encore, mais ça prouve que ça marche, que la fonction prepare est la bonne vu qu'il passe le $class_name en paramètre)

En tout cas merci tu m'as rudement bien aider :)
J'aimerai te dire que je te rendrai la pareille mais je doute que venant de moi tu en es besoin XD

Ok j'ai pas du tout comprendre alors, bon si ça marche :)

Tout le monde peut apprendre quelque chose et tout le monde peut enseigner quelque chose à quelqu'un ! Si c'est pas moi ça sera quelqu'un d'autre :)