Débutant : Classe membre bien écrite ?

Avatar de l’utilisateur
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

05 Jan 2017, 16:54

Non, si tu veux faire de la POO, donc séparation des concepts, il ne faut pas que la récupération des informations du membre soit dans ta classe Member.
Il faudrait que tu fasse une classe MemberLoader ou MemberHydrator qui ferais la requête et qui créerais l'objet Memberphp

Voici un exemple, avec 2 méthodes de récupération d'un membre, selon son id ou son username :
<?php

class MemberHydrator
{
/**
* Database connection instance
*
* @var PDO
*/
protected $conn;

/**
* MemberHydrator constructor.
*
* @param PDO $conn
*/
public function __construct(PDO $conn)
{
$this->conn = $conn;
}

/**
* Create a Member instance from database with it id
*
* @param string $id
*
* @return Member
*/
public function getFromId(string $id): Member
{
$datas = $this->conn->query(
'SELECT * FROM users WHERE id = :id',
['id' => $id]
)->fetch();

return static::hydrate($datas);
}

/**
* Create a Member instance from database with it username
*
* @param string $username
*
* @return Member
*/
public function getFromUsername(string $username): Member
{
$datas = $this->conn->query(
'SELECT * FROM users WHERE username = :username',
['username' => $username]
)->fetch();

return static::hydrate($datas);
}

/**
* Create a Member instance, and hydrate it from database query result
*
* @param array $datas
*
* @return Member
*/
static protected function hydrate(array $datas): Member
{
$member = new Member($datas['id'], $datas['username']);

$member->setEmail($datas['email']);
$member->setSurname($datas['surname']);
$member->setName($datas['name']);
$member->setSex($datas['sex']);
$member->setBirthdate(new Datetime($datas['birthdate']));
$member->setUserstart($datas['userstart']);
$member->setUserdate(new Datetime($datas['userdate']));

return $member;
}
}


Attention, c'est un exemple simpliste pour te donner une idée du découpage, mais à ne pas prendre telle quel, puisque je n'ai pas géré l'absence de retour de la requête, le catch des erreurs de création du membre
C'est juste pour te donner une idée du découpage.

Après, au lieu d'avoir une classe Member et une classe MemberHydrator, tu pourrais jouer avec les namespace et avoir Entity\Member et Hydrator\Member
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Eléphant du PHP | 379 Messages

09 Jan 2017, 18:30

zeus a écrit :Non, si tu veux faire de la POO, donc séparation des concepts, il ne faut pas que la récupération des informations du membre soit dans ta classe Member.

Je suis d'accord avec ça ;)

zeus a écrit :Attention, c'est un exemple simpliste pour te donner une idée du découpage, mais à ne pas prendre telle quel, puisque je n'ai pas géré l'absence de retour de la requête, le catch des erreurs de création du membre

J'ai déjà une classe qui s'occupe de gérer les authentifications, donc les créations et connexions des membres.

Mais dès qu'un membre s'inscrit ou se connecte, je récupère (sous forme d'objets) toutes les infos du membre et je les met dans une variable $_SESSION['auth'], et je fais :
$member = new Member($_SESSION['id'],$_SESSION['username']);
pour affecter les valeurs des attributs de la classe Membre, et d'éviter de pouvoir faire un echo $_SESSION->username; pour afficher le pseudo.

Je préfère utiliser une classe Member qui défini le membre avec ses paramètres ;) et faire $member->username;
J'ai bien compris le découpage de classe, je créerai une classe qui s'occupera des requêtes SQL (donc hydrater aussi les attributs de la classe Member) et qui héritera de la classe Member

zeus a écrit :Après, au lieu d'avoir une classe Member et une classe MemberHydrator, tu pourrais jouer avec les namespace et avoir Entity\Member et Hydrator\Member

Je suis en apprentissage la dessus ;)

Avatar de l’utilisateur
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

09 Jan 2017, 20:47

nico44530 a écrit :Mais dès qu'un membre s'inscrit ou se connecte, je récupère (sous forme d'objets) toutes les infos du membre et je les met dans une variable $_SESSION['auth'], et je fais :
$member = new Member($_SESSION['id'],$_SESSION['username']);
pour affecter les valeurs des attributs de la classe Membre, et d'éviter de pouvoir faire un echo $_SESSION->username; pour afficher le pseudo.

C'est un tableau que tu mets dans ta session, visiblement.

nico44530 a écrit :Je préfère utiliser une classe Member qui défini le membre avec ses paramètres ;) et faire $member->username;
J'ai bien compris le découpage de classe, je créerai une classe qui s'occupera des requêtes SQL (donc hydrater aussi les attributs de la classe Member) et qui héritera de la classe Member

L'héritage ne devrait être utilisé que pour préciser le comportement (par exemple si tu voulais séparer les administrateurs des visiteurs), mais pas pour rajouter du comportement tiers.
C'est pour ça que je te parlais d'un hydrateur.
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Eléphant du PHP | 379 Messages

11 Jan 2017, 23:01

Donc dans mon cas, je dois bien hydrater les attributs avec ton exemple, je vais essayer, et comment gérer l'absence de retour de la requête, le catch des erreurs de création du membre, comme tu le dis ? ;)

Ton précédent code n'est pas sécurisé ou il manque des choses ?

Merci, je pense que j'ai suffisamment d'infos pour continuer seul ensuite :) Si tu peux juste me faire un petit récap sur la poo avec un espace membre ? =)
Pour que j'apprenne seul, il faut que je pratique ;)

Avatar de l’utilisateur
Modérateur PHPfrance
Modérateur PHPfrance | 8415 Messages

12 Jan 2017, 11:11

juste pour info, si tu utilise PDO (et p'tet mysqli) tu peux demander à fetch direct l'objet qui va bien plutôt que de te taper les set à la main
PDOStatement::fetch avec le flag PDO::FETCH_CLASS

ça te permet de gagner en ligne de code, en temps, en lisibilité et en source d'erreur.

pour la gestion d'erreur utilise les execeptions et en bout de chaîne soit un objet json (code / message) si tu as une api REST soit un echo avec un beau message.

@+
Il en faut peu pour être heureux ......