Salut à tous,
J'aurais aimé avoir votre avis sur les bonnes pratiques en programmation orienté objet.
Actuellement j'ai des classes que l'on dira métiers qui manipule et affiche les données, pour chacun de ces classe métiers, j'ai un équivalent en classe Sql qui sera charger de faire les requetes et renvoyer des tableau bruts de résultats. Quand j'ai besoin d'inserer des données, je passe mon objet entier à une méthode de ma classe Sql.
Récement en mettant à jours mon serveur php, je me suis retrouvé avec des warning Only variables should be passed by reference in
car je faisais cela dans mes classe Sql :
public function insert($objet){
$query = "INSERT INTO maTable (Id,monChamp) VALUES (:id,:monChamp)";
$prep = $this->pdo->prepare($query);
$prep->bindParam(':id', $objet->getId(), PDO::PARAM_INT);
$prep->bindParam(':monChamp', $objet->getMonChamp(), PDO::PARAM_STR);
try {
$prep->execute();
return $this->pdo->lastInsertId();
} catch (PDOException $e) {
conn::setErreur($e);
return false;
}
}
Le Warning vient du fait qu'il ne serais pas recommandé de manipuler un objet à l'intérieur de la méthode BindParam de pdo. Et c'est bien dommage car je trouvais cela bien pratique. car ca eviter de déclarer de nouvelles variable le temps de l'insertion des données, mais également la facilité à l'écriture grace à un bon ide.
Donc si il n'est pas recommander de faire ca, sous quelle forme est t'il conseillé de faire passer les données aux méthodes Sql ?
public function insert($objet){
$id = $objet->getId();
$monChamp = $objet->getMonChamp();
$query = "INSERT INTO maTable (Id,monChamp) VALUES (:id,:monChamp)";
$prep = $this->pdo->prepare($query);
$prep->bindParam(':id', $id, PDO::PARAM_INT);
$prep->bindParam(':monChamp', $MonChamp, PDO::PARAM_STR);
try {
$prep->execute();
return $this->pdo->lastInsertId();
} catch (PDOException $e) {
conn::setErreur($e);
return false;
}
}
ou encore, sachant pour pour les grosse requete ca va par être très lisible je trouve
public function insert($id,$objet){
$query = "INSERT INTO maTable (Id,monChamp) VALUES (:id,:monChamp)";
$prep = $this->pdo->prepare($query);
$prep->bindParam(':id', $id, PDO::PARAM_INT);
$prep->bindParam(':monChamp', $MonChamp, PDO::PARAM_STR);
try {
$prep->execute();
return $this->pdo->lastInsertId();
} catch (PDOException $e) {
conn::setErreur($e);
return false;
}
}
Merci de votre aide :)
Salut,
Ce vieux PHP, qui nous sort des erreurs quand il n'y a pas lieu d'être ; si une fonction veut la référence d'une variable mais qu'on ne veut pas récupérer la valeur si il la modifie, qu'il nous laisse faire. :) Ta première solution me semble la mieux.
Salut et merci pour ton retour.
Ce qui est renvoyé semble plus être un warning qu'une erreur, car le script ne s'arrête pas. Pour toi la première solution est la bonne ?
Au delà des warning renvoyer, que pensez de la séparation entre les classes métiers et base de donnée, est t'il logique que la classe sql manipule des objets métier ?
Bonjour.
Tu n'as pas l'impression que tu fais des erreurs dans le code d'exemple que tu nous montre ?
Tu définies :id
et :monChamp
, mais pas la suite tu utilises :idstage
et :ideleve
, ce qui est totalement différent.
salut, eeffectivement il ya des erreurs qui ne sont là que par ce que j'ai adapté un bout de vrai code pour simplifier la problematique, don as tu une remarque en faisant abstraction de cette coquille ?
Lorsque tu dis que tu as mis à jours ton serveur PHP, je suppose que tu veux dire que tu as mis à jours la version de PHP avec une plus récente qu'auparavent.
C'est ça ?
oui c'est bien ca, je suis passé vers un php 5.6 en mod dev qui renvoit tous les warnings.
Bonjour Yoann, dans l'esprit le fait d'appeler un une fonction directement en paramètre d'une autre semble élégant.
Je te recommande chaudement de ne pas écrire ton propre ORM mais de passer par un existant. De préférence :
Merci de ta réponse, même si cela semble élégant php n'en ai pas pour autant content de cet usage. Alors doit ton zappé ces erreurs ou non, tel est la question.
Merci pour tes conseil concerant l'usage des ORM, d'ailleurs je compte passer à Synfony ou Laravel qui utilise si je ne dis pas de betise Doctine.
En allant encore plus loin dans la sépération des couches, que pense tu de la fonction qui permet de créer directement un objet d'une classe ne tant que retour de requête
PDO::FETCH_CLASS: retourne une nouvelle instance de la classe demandée, liant les colonnes du jeu de résultats aux noms des propriétés de la classe. Si fetch_style inclut PDO::FETCH_CLASS (c'est-à-dire PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE), alors le nom de la classe est déterminé à partir d'une valeur de la première colonne.
Je l'ai utiliser sur certain projet, et c'est quand même vachement ultra pratique !! Mais si on part du principe que la partie Donnée du projet doit être disocier de la partie métier, cet usage ne devrait pas être conseillé.
hello, je suis peut-être hors jeu mais il suffirait d'exécuter ta requête comme ça :
$vals = array(
'id' => $objet->getId(),
'monChamp' => $objet->getMonChamp()
);
$query = "INSERT INTO maTable (Id,monChamp) VALUES (:id,:monChamp)";
$prep = $this->pdo->prepare($query);
try {
$prep->execute($val);
return $this->pdo->lastInsertId();
} catch (PDOException $e) {
conn::setErreur($e);
return false;
}
je trouve ça, tout aussi élégant ;)
Salut Saibe,
Merci pour ta proposition :)
Dans ce cas, pourquoi ne pas directement passer carrement comme ca ?
public function insert($val){
$query = "INSERT INTO maTable (Id,monChamp) VALUES (:id,:monChamp)";
$prep = $this->pdo->prepare($query);
try {
$prep->execute($val);
return $this->pdo->lastInsertId();
} catch (PDOException $e) {
conn::setErreur($e);
return false;
}
}
Sinon je n'ai pas compris ton dernier message
;) oui biensûr ; tu remarqueras que je n'ai pas englobé le tout dans une fction, chacun construit son $val où il veut...
pour mon dernier mess, laisse tomber, je me suis un peu laché et surtout planté ;) quand j'ai lu bindParam j'ai pensé "liaisons" et je croyais que ça ne fonctionnait pas à cause de ça, qu'il fallait définir un context...
Biensur que l'ont fait ce qu'on veux, mais l'idée et de rester dans le plus logique :)
Si tu veux être générique, autant faire
$object->insert('nomTable', ['monChamp1' => 'maValeur', 'monChamp2' => 'maValeur2']);
Dans quel contexte tu utilise ?
$objet->setId(2)
$objet->setNom('plop')
$objet->insert('nomTable', ['monChamp1' => 'maValeur', 'monChamp2' => 'maValeur2'])
?
slt, ou ça, pour reprendre ta 1ere syntaxe
public function insert($objet){
$query = "INSERT INTO maTable (Id,monChamp) VALUES (:id,:monChamp)";
$prep = $this->pdo->prepare($query);
/* et à la place de :
$prep->bindParam(':id', $objet->getId(), PDO::PARAM_INT);
$prep->bindParam(':monChamp', $objet->getMonChamp(), PDO::PARAM_STR);
*/
// juste ça, mais c vrai que tu crées une variable
$vals = array(
'id' => $objet->getId(),
'monChamp' => $objet->getMonChamp()
);
try {
// et donc ça
$prep->execute($vals);
/* ou ça, pour pas créer :)
$prep->execute(array(
'id' => $objet->getId(),
'monChamp' => $objet->getMonChamp()
));
*/
return $this->pdo->lastInsertId();
} catch (PDOException $e) {
conn::setErreur($e);
return false;
}
}
après un bon patern POO c le MVC, du moins c celui que j'utilise...