Bonjour à tous,
je suis entrain mtn de creer mon prorpe MVC
J'ai commencé à créer ma classe UserModel qui herite de la classe Model
dans la classe Model je veux créer une fonction qui permet d'inserer les donnes dans la BDD InsertData() et cette fonction doit être appelé ds la class UserModel
le problem je veux preciser les donnes et les champs a inserer depuis la classe UserModel et passer ces donnes a la fonction InsertData ()
comment je peux le faire???
Model.php:
<?php
class model
{
private $database;
public function getPdo(){
if ($this->database===null) {
$pdo=new pdo('mysql:host=localhost;dbname=pronostic','root','');
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}
return $this->database=$pdo;
}
public function InsertData($table,$dato){
$datas = array(
'usero' => $dato['username'],
'usero' => $dato['password']
);
$req="INSERT INTO $table(user,pass) VALUES(:usero,:usero)";
$sql=$this->getPdo()->prepare($req);
$sql->execute($datas);
}
}
UserModel.php:
<?php
class UserModel extends model
{
function isnertUser($dataa){
$model = new model();
$resulto=$model->insert('users',$dataa);
}
}
UserController:
<?php
class UserControllerextends controller
{
private $ModelUser;
function __construct(){
$this->LoadModel('UserModel');
$this->ModelUser=new UserModel();
}
function index(){
$this->LoadView('show');
}
function add(){
$tab = array(
'username' => "Jean",
'password' => "qwertz1234",
);
$result=$this->ModelUser->isnertUser($tab);
echo "Bien ajoouter";
}
}
je te suggere d'ajouter un attribut de type array dans la classe Model avec la liste des champs dela table que tu veux inserer comme sa a chaque fois que tu extends la classe Modele tu pourras lui donner les champs que tu veux.
Salut, tu peux faire ceci
Attention ta fonction getPDO à un petit souci,
class Model
{
public function getPdo(){
if ($this->database===null) {
$this->database=new PDO('mysql:host=localhost;dbname=pronostic','root','');
$this->database->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}
return $this->database;
}
public function insertData($table, array $data)
{
$fields = implode(',' , array_keys($data));
$values = "";
foreach ($data as $k => $v) {
if (!empty($values)) {
$values = ',';
}
$values .= "$k=:$k";
}
$query = $this->getPdo()->prepare("INSERT INTO `$table` ($fields) VALUES ($values)");
$query->execute( $data );
return $this->getPdo()->lastInsertId();
}
}
En faite, lorsqu'on appelle ta fonction getPDO deux fois de suite normalement cela plante !!
$this->getPdo();
$this->getPdo();
Pourquoi et comment ?
Ta fonction suit cette logique
Premiere appelle :
$this->database ne vaut plus null donc on entre pas dans la condition if ($this->database === null), ce qui implique que ta variable $pdo ne sera pas definie, comme $pdo n'est pas defini et que tu fais $this->pdo = $pdo, alors tout plante. :)
Voila voila
Salut,
effectivement pour getPDO il faut changer un peu :
if ($this->database === null) {
$pdo=new pdo('mysql:host=localhost;dbname=pronostic','root','');
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$this->database = $pdo;
}
return $this->database;
Dans le constructeur de la class "UserController" il y a une incohérence :
normalement
$this->LoadModel('UserModel');
fais en sorte que
$this->ModelUser
soit une instance de la classe "UserModel"
Pourtant juste après, tu écrase cette instance que tu viens de créer par un "new" :
// "range" une instance de la class "UserModel" dans la variable "private $ModelUser"
$this->LoadModel('UserModel');
// Écrase l'instance fraichement créé par une nouvelle instance
$this->ModelUser = new UserModel();
De plus, tu utilise 2 fois usero ici, ce n'est pas bon :
$datas = array(
'usero' => $dato['username'],
'usero' => $dato['password']
);
Il faut changer ça :
$datas = array(
'usero_name' => $dato['username'],
'usero_pass' => $dato['password']
);
$req="INSERT INTO $table(user, pass) VALUES(:usero_name, :usero_pass)";
Détails : je ne sais pas si tu as les mêmes erreurs dans ton code chez toi, que les erreurs qui sont dans le code de ce message :
Oh dis donc, j'ai relu ta question et je me rend compte que je répond complètement à côté... Excuse moi, je réessaie.
Je vois un soucis d'organisation, tu as voulu créer une méhode générique "InsertData()" dans ta classe "Model", comme ça toutes les classes qui héritent de la classe "Model" auront cette fonction "InsertData()" de disponible.
C'est pas mal, mais au final cette méthode n'est pas générique puisque ce bout de code est trop spécifique :
$datas = array(
'usero' => $dato['username'],
'usero' => $dato['password']
);
Pour rendre ce bout de code générique j'imagine qu'on pourrait utiliser un foreach, avec $key, $value... Ça me parait galère...
Je pense qu'il vaut mieux créer une méthode bien spécifique à l'ajout d'un utilisateur, donc pas dans la classe générique "Model", mais dans la classe "UserModel".
(Supprime ta fonction insertData() de la classe "Model", et modifie la fonction "insertUser" de la classe "UserModel")
// dans la classe "UserModel"
function insertUser(array $datas)
{
$sql = 'INSERT INTO nom_table_users (username, password) values (:username, :password)';
$req = $this->getPdo()->prepare($sql);
$attributes = array (
"username" => $datas['username'],
"password" => $datas['password']
);
$res = $req->execute($attributes);
return $res->rowCount();
}
et dans UsersController :
public function add()
{
$tab = array (
'username' => "Jean",
'password' => "qwertz1234"
);
if ($this->ModelUser->insertUser($tab) > 0) {
echo 'OK<br>';
}
else {
echo 'Erreur<br>';
}
}
Dans ta classe "Model" qui est générique, tu laissera la fonction getPdo(), et tu pourra ajouter des méthodes très générique comme par exemple :
public function find($table, $id)
{
$req = $this->getPdo()->query('SELECT * FROM' . $table . ' WHERE id = ' . $id);
return $req->fetch();
}
public function delete($table, $id)
{
$req = $this->getPdo()->prepare('DELETE * FROM ' . $table . ' WHERE id = ?');
$res = $req->execute([$id]);
return $res->rowCount();
}
...
SLK
j'ai fait la meme chose
pourquoi il faut changer cette fonction ?? en fait j'ai fait ce qu'il a fait jonathan :D
if ($this->database===null) {
$pdo=new pdo('mysql:host=localhost;dbname=pronostic','root','');
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}
return $this->database=$pdo;
et j'ai pas bien compris cette partie :
// "range" une instance de la class "UserModel" dans la variable "private $ModelUser"
$this->LoadModel('UserModel');
// Écrase l'instance fraichement créé par une nouvelle instance
$this->ModelUser = new UserModel();
pourriez-vous m'expliquer car je suis debutant dans le monde POO :P
Oui bien sur.
1)
Balbert te l'a déjà expliqué, mais je vais essayer d'y aller plus doucement.
cette ligne de code
return $this->database = $pdo;
est un "racourcis" pour faire 2 choses à la fois :
$this->database = $pdo;
// puis
return $this->databse;
Maintenant qu'on sait ça, lançons le code pour la toute 1ère fois :
// $this->database vaut bien "null", on ne l'a encore jamais initialisé
if ($this->database === null) {
// donc on rentre dans ce IF, et on execute les 2 lignes suivantes
$pdo = new pdo('mysql:host=localhost;dbname=pronostic','root','');
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}
// comme on est rentré dans le IF, $pdo vaut quelquechose, il n'est PAS "null"
// du coup la ligne suivante s'exécute sans problèmes
return $this->database = $pdo;
// maintenant $this->database EST définie, elle ne vaut PLUS "null"
rappelons la fonction une 2ème fois :
// comme $this->database ne vaut PLUS "null", cette fois on n'entre PAS dans le IF
if ($this->database === null) {
// comme on n'entre pas dans le IF, ces 2 lignes ne sont pas exécutées
$pdo = new pdo('mysql:host=localhost;dbname=pronostic','root','');
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}
// comme on n'est pas rentré dans le IF, la variable $pdo N'EXISTE PAS, pourtant on va essayer de s'en servir :
return $this->database = $pdo; // ERREUR, $this->database essaie de prendre la valeur d'une variable qui n'existe pas.
2)
dans cette ligne :
$this->LoadModel('UserModel');
"$this" représente le controller "UserController"
Ce controller à un attribut privé :
private $ModelUser;
Ce controller à aussi une méthode "loadModel()" (dont il a hérite de la classe "Controller")
La méthode "loadModel()" se charge d'instancier une classe, et de "ranger" cette instance dans la variable privé "$ModelUser".
J'ai dit "une classe" ? Oui mais quelle classe ?
Celle que tu lui donne en paramètre. Ici on lui demande d'instancier la classe "UserModel" :
$this->LoadModel('UserModel');
On a donc une instance de la classe "UserModel" dans notre variable privé $ModelUser. Parfait !
Mais juste après, on l'écrase en y mettant une nouvelle instance :
$this->ModelUser = new UserModel();
En vérité ces 2 lignes :
$this->LoadModel('UserModel');
$this->ModelUser = new UserModel();
font la même chose, donc il faut en garder une, et supprimer l'autre.
C'est la 1ère qu'il FAUT garder. Parcequ'elle respecte le principe d'encapsulation, alors que la seconde, non.
Si tu ne connais pas le principe d'encapsulation, il faut savoir que c'est probablement LE grand principe que doit respecter du code orienté objet.
En gros, ce principe te dit qu'il ne faut jamais attribuer des valeurs à tes attributs directement (c'est à dire en utilisant un "=") :
$mon_attribut = "une_valeur"; // PAS BIEN !! On a modifié un attribut directement, principe d'encapsulation non respecté.
Si tu veut initialiser ou modifier des attributs, tu DOIT passer par une méthode :
class MaClass
{
private $mon_attribut;
// cette fonction ne sert qu'à modifier notre attribut, on appelle ce genre de fonction un "setter"
public function setMonAttribut($nouvelle_valeur)
{
$this->mon_attribut = $nouvelle_valeur;
}
}
$objet = new MaClasse();
$objet->setMonAttribut($nouvelle_valeur); // BIEN ! On a utilisé une méthode pour modifier la valeur de notre attribut. Principe d'encapsulation respecté.
Je te laisse te documenter sur :
Au passage, pour "nommer" un attribut d'une classe, la convention nous dit de commencer par une minuscule, et d'utiliser des underscores entre chaque mots, exemples :
OK
PAS OK
Si ce genre de chose t'intéresses tu peux regarder du côté des conventions officielle "PSR"
il semble que la PSR-0 soit dépréciée, il faut regarder les PSR-1, PSR-2, PSR-3, PSR-4
http://www.php-fig.org/psr/psr-1/
Merci bcp SLK pour cette reponse qui'est tres clair ,
mais le problem quand je supprime une ligne par exemple :
cette ligne :
$this->LoadModel('UserModel');
je recois ce message
Fatal error: Class 'UserModel' not found in C:\xampp\htdocs....
et quand je supprime l'autre
$this->ModelUser = new UserModel();
je recois ce message
Fatal error: Call to a member function getUser() on null....
je peux pas appeler les fonnctions de UserModel
mais quand je laisse les deux lignes tout marche bien
$this->LoadModel('UserModel');
$this->ModelUser = new UserModel();
mais merci bcp quand meme pr ta reponse ;)
Ah, ok on va essayer de trouver d'où vient le problème.
Je maintiens qu'il faut conserver
$this->LoadModel('UserModel');
et supprimer
$this->ModelUser = new UserModel();
Maintenant, essayons de trouver ce qui ne va pas.
J'ai 3 questions (en gras).
On a cette erreur :
Fatal error: Class 'UserModel' not found in C:\xampp\htdocs....
Donne moi le chemin complet de l'erreur.
Et aussi, comment est-ce que tu "charge" tes classes ?
Class 'UserModel' not found
Il dit qu'il ne trouve pas la classe "UserModel"
est-ce qu'au même titre que tu as une classe "UserController" qui hérite de la classe "Controller",
tu as bien une classe "UserModel" qui hérite de la classe "Model" ?
oui le meme titre et aussi j'ai la classe UserModel qui hérite de la classe "Model"
je charge les models (children Model) depuis la classe Controller avec cette fonction :
function LoadModel($filename){
require(ROOT.'/models/'.$filename.'.php');
}
et je charge la classe Model depuis l'index voila mon index j'uitilse aucun autoloader :
<?php
define('WEBROOT', str_replace('index.php', '', $_SERVER['SCRIPT_NAME']));
define('ROOT', str_replace('index.php', '', $_SERVER['SCRIPT_FILENAME']));
require (ROOT . 'core/model.php');
require (ROOT . 'core/controller.php');
$URL="http://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
define('SITE_URL', str_replace('index.php', '', $URL));
if (isset($_GET['p']))
{
$param = explode('/', $_GET['p']);
$MyController = isset($param[0]) ? $param[0] : 'index';
#$action = isset($param[1]) ? $param[1] : 'index';
if (!isset($param[1]) || $param[1]=="") {$action='index';}else{$action=$param[1];}
if (file_exists("controllers/" . $MyController . "Controller.php"))
{
require "controllers/" . $MyController . "Controller.php";
$controller = $MyController . "Controller";
$controller = new $controller();
if (method_exists($controller, $action))
{
$controller->$action();
}
}
else
{
// echo "errror 404";
require "views/404.php";
}
}
else
{
$MyController = "index";
$action = "index";
require "controllers/" . $MyController . "Controller.php";
$controller = $MyController . "Controller";
$controller = new $controller();
if (method_exists($controller, $action))
{
$controller->$action();
}
}
Ah c'est bon je vois.
Ta fonction loadModel() ne fais que le require du fichier qui contient la classe, maintenant il faut aussi instancier cette classe :
function LoadModel($filename)
{
require(ROOT.'/models/'.$filename.'.php'); // charge la classe "UserModel"
$this->ModelUser = new UserModel(); // instancie la classe "UserModel" dans l'attribut privé "$ModelUser" du controller "UserController"
}
Fatal error: Call to a member function getUser() on null....
Cette erreur venait du fait que tu devais faire quelque part
$this->ModelUser->getUser();
alors qu'on avait jamais instancié l'attribut $ModelUser, il vallait "null" et on essayait de lui appliquer une fonction (du coup, Fatal Error).
Il me semble que le reste est correct.