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é ?
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 :
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 :
Et dans mon fichier de rendu, j'ai quelque chose comme ça :
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
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.
Si je remet tout le contenu de la class Articles dans la class Database, ça fonctionne. La connexion se fait bien en tout cas
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 :
Ensuite dans ta classe "Article" tu dois avoir :
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
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.
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.
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à)
Avec toujours ça dans mon rendu :
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
J'espere avoir bien compris ou tu voulais en venir.
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.
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) ?
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.
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 :
Pour le moment, je comprends juste pas cette partie là, si quelqu'un peut m'éclairer, merci :)
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
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.
Donc si on reviens dans notre index.php, c'est comme si on avait fait.
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.
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.
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
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.
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 ?
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
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 :)
« 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
C'est de l'injection de dépendance : http://www.grafikart.fr/formations/programmation-objet-php/injection
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.
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 :
Comme dans la formation. Ce bout de code ce trouve dans la class Table à même titre que la fonction query tel que :
En commentaire l'appel des fonctions de la classe Database qui se trouve ci dessous :
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 :
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.. :/
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.
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.
Ma classe Database :
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
Non non, dans ton constructeur de table
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
Bah oui bah c'est ce que jdis, si je précise Database :
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.
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
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 :)