L'orienté objet, en PHP et dans d'autres langages, est également nommé POO (programmation orientée objet).
C'est un paradigme de programmation informatique.
La POO consiste en la définition et l'interaction de briques logicielles appelées objets.
Un objet représente un concept, une idée ou toute entité du monde physique, comme une voiture, une personne ou encore une page d'un livre. Il possède une structure interne et un comportement, et il sait interagir avec ses pairs.
Il s'agit donc de représenter ces objets et leurs relations. L'interaction entre les objets via leurs relations permet de concevoir et réaliser les fonctionnalités attendues, de mieux résoudre le ou les problèmes. Dès lors, l'étape de modélisation revêt une importance majeure et nécessaire pour la POO. C'est elle qui permet de transcrire les éléments du réel sous forme virtuelle.
- code
- Introduction
- 1. Les classes et les objets
- 1.1. Déclaration d'une classe
- 1.2. Instanciation d'une classe
- 1.3. Accès aux propriétés et aux méthodes d'une classe depuis l'intérieur de la classe
- 1.4. Accès aux propriétés et aux méthodes publiques d'une classe depuis l'extérieur de la classe pour lecture ET modification
- 1.5 Les constructeurs
- 1.6 Les autres méthodes magiques
- 1.7. Les getters et les setters
- 2. L'héritage
- 3. Les espaces de noms
- 4. Auto-chargement des classes
- 5. Les exceptions
- 6. Le mapping de tables SQL en classes PHP
- 7. Les Managers
- 1. Les classes et les objets
Définition : Une classe est une structure qui permet de définir des objets. Une classe est un modèle qui décrit les caractéristiques communes d'un groupe d'objets.
Un objet est une instance d'une classe. Un objet est une entité qui possède des propriétés, des constantes et des méthodes.
La déclaration d'une classe en PHP commence par le mot clé class
, suivi du nom de la classe et de son contenu entre accolades. Voici un exemple de déclaration de classe en PHP
class MaClasse {
// Propriétés
private $proprietePrivee;
public $proprietePublique = 'Valeur par défaut';
// Constantes
const MA_CONSTANTE = 'Valeur constante';
// Méthodes
public function methodePublique() {
echo "Ceci est une méthode publique";
}
private function methodePrivee() {
echo "Ceci est une méthode privée";
}
}
Dans cet exemple, la classe s'appelle MaClasse. Elle a deux propriétés : une propriété privée $proprietePrivee
et une propriété publique $proprietePublique
initialisée à 'Valeur par défaut'.
Elle a également une constante MA_CONSTANTE
initialisée à 'Valeur constante'. Elle est accessible depuis l'extérieur de la classe en utilisant le nom de la classe suivi de l'opérateur de résolution de portée ::
et du nom de la constante.
Par exemple, pour accéder à la constante MA_CONSTANTE
depuis l'extérieur de la classe, on écrira :
echo MaClasse::MA_CONSTANTE;
Elle a également deux méthodes : une méthode publique methodePublique()
qui affiche une chaîne de caractères et une méthode privée methodePrivee()
qui affiche également une chaîne de caractères.
Les propriétés d'une classe peuvent être de différents niveaux d'accessibilité : public
, protected
ou private
. Les méthodes peuvent également être de différents niveaux d'accessibilité.
- public
Les propriétés et les méthodes publiques sont accessibles depuis l'extérieur de la classe, ainsi que dans la classe elle-même et ses sous-classes.
- protected
Les propriétés et les méthodes protégées ne sont accessibles que dans la classe elle-même et ses sous-classes.
- private
Les propriétés et les méthodes privées ne sont accessibles que dans la classe elle-même.
Nous verrons plus loin l'utilité de ces différents niveaux d'accessibilité.
PHP 8.1 introduit un nouveau modificateur d'accès public readonly
qui permet de déclarer une propriété publique en lecture seule.
Elle doit être typée et ne peut avoir de valeur par défaut. Elle ne peut être modifiée que dans le constructeur de la classe (ou une méthode de type setter)
class MaClasse {
// classe avec une propriété publique en lecture seule
public readonly string $proprietePublique;
// constructeur mettant à jour la propriété publique via un setter
public function __construct(string $valeur) {
$this->setProprietePublique($valeur);
}
// méthode de type setter pour modifier la propriété publique
public function setProprietePublique(string $valeur) {
$this->proprietePublique = $valeur;
}
}
On peut donc accéder à la propriété publique en lecture seule :
$objet = new MaClasse('Valeur');
echo $objet->proprietePublique;
Mais on ne peut pas la modifier directement :
// génère une erreur
$objet->proprietePublique = 'Nouvelle valeur';
On peut par contre la modifier via un setter :
$objet->setProprietePublique('Nouvelle valeur');
Cette nouvelle fonctionnalité permet de garantir que la propriété ne sera pas modifiée après son initialisation (sauf via un setter
) et permet également d'éviter la création de méthodes de type getter
pour les propriétés en lecture seule.
Il est important de noter que la déclaration d'une classe en PHP ne crée pas directement un objet. Une classe est simplement une structure qui décrit les propriétés et les méthodes d'un objet. Pour créer un objet à partir d'une classe, vous devez instancier la classe en utilisant le mot clé new
, comme ceci :
$objet = new MaClasse();
Dans cet exemple, nous avons instancié la classe MaClasse qui est un objet stocké en mémoire, la variable $objet est une étiquette pointant vers celui-ci.
Lorsque vous êtes à l'intérieur d'une classe, vous pouvez accéder à ses propriétés et à ses méthodes en utilisant self
et l'opérateur de résolution de portée ::
, ou le $this
si la classe est instanciée :
class MaClasse {
// Propriétés
private $proprietePrivee;
public $proprietePublique = 'Valeur par défaut';
// Constantes
const MA_CONSTANTE = 'Valeur constante';
// Méthodes
public function methodePublique() {
echo "Ceci est une méthode publique";
}
private function methodePrivee() {
echo "Ceci est une méthode privée";
}
public function methodePublique2() {
$this->proprietePrivee=5;
$this->proprietePublique="Nouvelle valeur";
$sortie = $this->methodePublique();
$sortie.=" ".self::MA_CONSTANTE;
return $sortie;
}
}
1.4. Accès aux propriétés et aux méthodes publiques d'une classe depuis l'extérieur de la classe pour lecture ET modification
Lorsque vous êtes à l'extérieur d'une classe, vous pouvez accéder à ses propriétés et à ses méthodes publiques en utilisant l'opérateur de flèche ->
, comme ceci :
echo $objet->proprietePublique;
echo $objet->methodePublique();
Attention, une propriété publique peut être modifiée depuis l'extérieur de la classe, ce qui n'est pas le cas d'une propriété privée ou protégée.
$objet->proprietePublique = 'Nouvelle valeur';
Nous pouvons même créer une propriété publique à la volée, même si elle n'existe pas dans la classe :
$objet->proprietePublique2 = 'Valeur';
Ceci est une mauvaise pratique, car cela peut créer des erreurs dans le code. Il est parfois pratique de pouvoir le faire, mais il est préférable de déclarer toutes les propriétés dans la classe et empêcher l'ajout de propriétés à la volée (nous verrons cela plus loin dans le cours).
Le constructeur est une méthode spéciale (méthode magique) qui est appelée automatiquement lorsqu'un objet est instancié. Le constructeur est généralement utilisé pour initialiser les propriétés d'un objet.
Le constructeur d'une classe est défini en créant une méthode avec le nom __construct()
:
class MaClasse {
public function __construct() {
// Code du constructeur
}
}
C'est au constructeur que l'on passe les paramètres lors de l'instanciation de la classe :
$objet = new MaClasse($param1, $param2);
Voici un exemple de constructeur :
class MaClasse {
// Propriétés
private $proprietePrivee;
public $proprietePublique = 'Valeur par défaut';
###
// Méthodes
public function __construct($param1, $param2) {
$this->proprietePrivee=$param1;
$this->proprietePublique=$param2;
}
###
}
}
Nous utiliserons plus souvent les getters et les setters pour accéder aux propriétés d'une classe.
PHP propose d'autres méthodes magiques qui permettent de gérer les objets. Vous pouvez les retrouver ici :
https://www.php.net/manual/fr/language.oop5.magic.php
Nous les verrons au fur et à mesure de nos besoins.
Les getters et les setters sont utilisés pour accéder aux propriétés d'une classe.
Un getter
est une méthode qui permet d'accéder à une propriété privée ou protégée.
Un setter
est une méthode qui permet de modifier une propriété privée ou protégée.
Les bonnes pratiques de programmation orientée objet recommandent de rendre les propriétés privées (ou protégées) et d'utiliser des getters et des setters pour accéder à ces propriétés.
Voici un exemple de getters et de setters :
class MaClasse {
// Propriétés
private $proprietePrivee;
protected $proprieteProtegee;
public $proprietePublique = 'Valeur par défaut';
###
// Méthodes
public function __construct($param1, $param2, $param3) {
// utilisation des setters pour modifier les valeurs des propriétés,
// ce qui permet de vérifier les valeurs
$this->setProprietePrivee($param1);
$this->setProprieteProtegee($param2);
// inutile d'utiliser un setter pour modifier la propriété publique
$this->proprietePublique=$param3;
}
// Getters qui récupèrent des valeurs
// Récupère la valeur de la propriété privée de type string ou null
public function getProprietePrivee():?string {
return $this->proprietePrivee;
}
// Récupère la valeur de la propriété protégée de type string ou null
public function getProprieteProtegee():?string {
return $this->proprieteProtegee;
}
// Setters qui modifient des valeurs
// Modifie la valeur de la propriété privée uniquement si elle est de type string
public function setProprietePrivee(string $valeur) {
$this->proprietePrivee=$valeur;
}
// Modifie la valeur de la propriété protégée uniquement si elle est de type string
public function setProprieteProtegee(string $valeur) {
$this->proprieteProtegee=$valeur;
}
###
}
// Création d'un objet de la classe MaClasse
$monObjet = new MaClasse('valeur1', 'valeur2', 'valeur3');
// affichage de la valeur de la propriété publique
echo $monObjet->proprietePublique;
// affichage des valeurs de la propriété privée et de la propriété protégée
echo $monObjet->getProprietePrivee();
echo $monObjet->getProprieteProtegee();
// Création d'un objet de la classe MaClasse
$monObjet = new MaClasse('valeur1', 'valeur2', 'valeur3');
// modification de la valeur de la propriété publique
$monObjet->proprietePublique = 'Nouvelle valeur';
// modification des valeurs de la propriété privée et de la propriété protégée
$monObjet->setProprietePrivee('Nouvelle valeur');
$monObjet->setProprieteProtegee('Nouvelle valeur');
L'héritage est un concept de programmation orientée objet qui permet à une classe d'hériter des propriétés et des méthodes d'une autre classe.
Une classe qui hérite d'une autre classe est appelée classe enfant ou classe dérivée. La classe dont la classe enfant hérite est appelée classe parente ou classe de base.
Pour hériter d'une classe, utilisez le mot clé extends
:
class MaClasseEnfant extends MaClasse {
// Code de la classe enfant
}
PHP ne supporte pas l'héritage multiple, c'est-à-dire qu'une classe ne peut hériter que d'une seule classe parente. Cependant, il est possible d'implémenter plusieurs interfaces (nous le verrons plus loin).
Lorsque vous héritez d'une classe, vous héritez de toutes ses propriétés et de toutes ses méthodes, mais pas de sa visibilité. Les propriétés et les méthodes privées ne peuvent pas être héritées, mais les propriétés et les méthodes protégées ou publiques peuvent l'être.
Lorsque vous héritez d'une classe, vous pouvez modifier la visibilité des méthodes et des propriétés héritées. Cependant, vous ne pouvez pas rendre une propriété privée ou une méthode protégée publique.
Les méthodes et les propriétés privées ne peuvent pas être héritées, donc elles ne peuvent pas être modifiées depuis la classe enfant.
class MaClasseEnfant extends MaClasse {
// Code de la classe enfant
// Impossible de modifier les méthodes et les propriétés privées,
// ceci génère une erreur,
// ou une nouvelle propriété publique est créée (faille de sécurité que l'on arrivera à corriger)
$this->proprietePrivee = 'Nouvelle valeur';
}
Les méthodes et les propriétés protégées peuvent être héritées et modifiées depuis la classe enfant.
class MaClasseEnfant extends MaClasse {
// Code de la classe enfant
// Les méthodes et les propriétés protégées peuvent être modifiées
$this->proprieteProtegee = 'Nouvelle valeur';
}
Les méthodes et les propriétés publiques peuvent être héritées et modifiées depuis la classe enfant.
class MaClasseEnfant extends MaClasse {
// Code de la classe enfant
// Les méthodes et les propriétés publiques peuvent être modifiées
$this->proprietePublique = 'Nouvelle valeur';
}
Il est possible de définir des constantes par classes qui restent identiques et non modifiables. La visibilité par défaut des constantes de classe est public.
À partir de PHP 7.1.0, les modificateurs de visibilité sont autorisés sur les constantes de classe.
Les constantes de classes peuvent être redéfinies par une classe enfant. À partir de PHP 8.1.0, les constantes de classes ne peuvent pas être redéfinies par une classe enfant si elle a été défini comme finale
.
class MaClasse {
const MA_CONSTANTE = 'Valeur constante'; // publique par défaut
public const MA_CONSTANTE_PUBLIQUE = 'Valeur constante publique';
protected const MA_CONSTANTE_PROTEGEE = 'Valeur constante protégée';
private const MA_CONSTANTE_PRIVEE = 'Valeur constante privée';
// ne peut pas être redéfinie par une classe enfant
final const MA_CONSTANTE_FINALE = 'Valeur constante finale';
}
// fonctionnent
echo MaClasse::MA_CONSTANTE;
echo MaClasse::MA_CONSTANTE_PUBLIQUE;
echo MaClasse::MA_CONSTANTE_FINALE;
// génèrent une erreur
echo MaClasse::MA_CONSTANTE_PROTEGEE;
echo MaClasse::MA_CONSTANTE_PRIVEE;
À partir de PHP 8.3, les constantes de classes peuvent être typées :
class MaClasse {
public const string|float MA_CONSTANTE = 'Valeur constante';
}
class MaClasseEnfant extends MaClasse {
// lors de la redéfinition, le(s) type(s) doi.t.vent être le(s) même(s)
public const string|float MA_CONSTANTE = 25.36;
}
echo MaClasse::MA_CONSTANTE;
echo MaClasseEnfant::MA_CONSTANTE;
La surcharge est un concept de programmation orientée objet qui permet à une classe enfant de redéfinir une méthode d'une classe parente. La surcharge est utilisée pour remplacer une méthode héritée par une nouvelle méthode.
La méthode redéfinie doit avoir le même nom, le même nombre de paramètres et la même visibilité. La surcharge peut également être utilisée pour ajouter des paramètres à une méthode héritée.
class MaClasseEnfant extends MaClasseParent {
// Code de la classe enfant qui surcharge la méthode de la classe parente
public function methodePublique($param1, $param2) {
// Code de la méthode redéfinie
}
}
Pour récupérer la méthode de la classe parente, utilisez le mot clé parent
:
class MaClasseEnfant extends MaClasseParent {
// Code de la classe enfant qui surcharge la méthode de la classe parente
public function methodePublique($param1, $param2) {
// Code de la méthode redéfinie
parent::methodePublique($param1, $param2);
}
}
Une classe abstraite est une classe qui ne peut pas être instanciée. Elle est utilisée pour définir des méthodes qui seront héritées par des classes enfants.
Pour définir une classe abstraite, utilisez le mot clé abstract
:
abstract class MaClasseAbstraite {
// Code de la classe abstraite
}
Une classe abstraite peut contenir des méthodes abstraites et des méthodes non abstraites.
Une méthode abstraite est une méthode qui n'a pas de corps. Elle est définie avec le mot clé abstract
et ne peut pas être définie avec les mots clés private
ou final
(final sera abordé plus loin).
abstract class MaClasseAbstraite {
// Méthode abstraite
abstract public function methodeAbstraite();
// Méthode non abstraite
public function methodeNonAbstraite() {
// Code de la méthode non abstraite
}
}
Une classe abstraite peut être héritée par une classe enfant. La classe enfant doit définir toutes les méthodes abstraites de la classe parente.
class MaClasseEnfant extends MaClasseAbstraite {
// Code de la classe enfant
public function methodeAbstraite() {
// Code de la méthode abstraite
}
}
Une méthode ou une propriété statique est une méthode ou une propriété qui peut être utilisée sans avoir besoin d'instancier la classe.
Pour définir une méthode ou une propriété statique, utilisez le mot clé static
:
class MaClasse {
// Propriété statique
public static $proprieteStatique = 'Valeur par défaut';
// Méthode statique
public static function methodeStatique() {
// Code de la méthode statique
}
}
Pour accéder à une méthode ou une propriété statique, utilisez le nom de la classe suivi de l'opérateur ::
:
// Accès à une propriété statique
echo MaClasse::$proprieteStatique;
// Accès à une méthode statique
echo MaClasse::methodeStatique();
Une classe finale est une classe qui ne peut pas être héritée. Elle est utilisée pour empêcher la création de classes enfants.
Pour définir une classe finale, utilisez le mot clé final
:
final class MaClasseFinale {
// Code de la classe finale
}
Une méthode finale est une méthode qui ne peut pas être redéfinie par une classe enfant. Elle est utilisée pour empêcher la surcharge de méthodes.
class MaClasse {
// Méthode finale
final public function methodeFinale() {
// Code de la méthode finale
}
}
Une interface est une classe abstraite qui ne contient que des méthodes abstraites. Elle est utilisée pour définir des méthodes qui seront implémentées par des classes enfants. Le mot abstract est donc inutile.
Pour définir une interface, utilisez le mot clé interface
:
interface MaInterface {
// Code de l'interface
}
Une interface contient des méthodes obligatoires
interface MaInterface {
// Méthode
public function methode();
}
Une interface peut être implémentée par une classe. La classe doit définir toutes les méthodes de l'interface.
class MaClasse implements MaInterface {
// Code de la classe
public function methode() {
// Code de la méthode
}
}
Une classe peut implémenter plusieurs interfaces. Dans ce cas, les interfaces sont séparées par une virgule.
class MaClasse implements MaInterface1, MaInterface2 {
// Code de la classe
public function methode() {
// Code de la méthode
}
}
Une interface peut hériter d'une ou plusieurs interfaces. Dans ce cas, les interfaces sont séparées par une virgule.
interface MaInterfaceEnfant extends MaInterfaceParent1, MaInterfaceParent2 {
// Code de l'interface enfant
}
Un trait est un ensemble de méthodes qui peut être utilisé par plusieurs classes. Il est utilisé pour définir des méthodes qui seront utilisées par plusieurs classes.
Pour définir un trait, utilisez le mot clé trait
:
trait MonTrait {
// Code du trait
}
Un trait peut contenir des méthodes abstraites et des méthodes non abstraites. Une méthode abstraite est une méthode qui n'a pas de corps. Elle est définie avec le mot clé abstract
et ne peut pas être définie avec les mots clés private
, protected
ou final
(final sera abordé plus loin).
trait MonTrait {
// Méthode abstraite
abstract public function methodeAbstraite();
// Méthode non abstraite
public function methodeNonAbstraite() {
// Code de la méthode non abstraite
}
}
Un trait peut être utilisé par une classe. Pour utiliser un trait, utilisez le mot clé use
:
class MaClasse {
// Utilisation du trait
use MonTrait;
}
Un trait peut être utilisé par plusieurs classes. Un trait peut également utiliser un autre trait.
trait MonTrait1 {
// Code du trait 1
}
trait MonTrait2 {
// Code du trait 2
}
trait MonTrait3 {
// Code du trait 3
use MonTrait1, MonTrait2;
}
class MaClasse1 {
// Utilisation du trait 1
use MonTrait1;
}
class MaClasse2 {
// Utilisation du trait 2
use MonTrait2;
}
class MaClasse3 {
// Utilisation du trait 3
use MonTrait3;
}
Un namespace est un moyen d'encapsuler des éléments. Il est utilisé pour éviter les conflits de noms entre les classes, les fonctions et les constantes.
Pour définir un namespace, utilisez le mot clé namespace
:
namespace MonNamespace;
Un namespace peut contenir des classes, des fonctions et des constantes.
namespace MonNamespace;
class MaClasse {
// Code de la classe
}
function maFonction() {
// Code de la fonction
}
const MA_CONSTANTE = 'Valeur de la constante';
Un namespace peut être utilisé par une classe, une fonction ou une constante. Pour utiliser un namespace, utilisez le mot clé use
:
namespace MonNamespace;
// Utilisation du namespace
use MonNamespace;
class MaClasse {
// Utilisation du namespace
use MonNamespace;
}
function maFonction() {
// Utilisation du namespace
use MonNamespace;
}
// Utilisation du namespace
use MonNamespace;
echo MA_CONSTANTE;
Un namespace peut être utilisé par plusieurs classes, fonctions ou constantes.
namespace MonNamespace;
// Utilisation du namespace
use MonNamespace;
class MaClasse1 {
// Utilisation du namespace
use MonNamespace;
}
class MaClasse2 {
// Utilisation du namespace
use MonNamespace;
}
function maFonction1() {
// Utilisation du namespace
use MonNamespace;
}
function maFonction2() {
// Utilisation du namespace
use MonNamespace;
}
echo MA_CONSTANTE;
L'auto-chargement des classes est utilisé pour charger automatiquement les classes. Il est utilisé pour éviter d'avoir à inclure manuellement les fichiers de classe.
Pour définir une fonction d'auto-chargement, utilisez la fonction spl_autoload_register()
:
spl_autoload_register(
function($className){
require "../model/".$className.".php";
}
);
La fonction d'auto-chargement est appelée chaque fois qu'une classe est instanciée. Elle reçoit le nom de la classe en paramètre. On peut utiliser le namespace de la classe pour déterminer le chemin du fichier de la classe.
Il faut vérifier si le fichier existe avant de l'inclure et bien sûr, il faut inclure le fichier avant d'instancier la classe.
Il faut mettre nos modèles dans un dossier model
et nos contrôleurs dans un dossier controller
et dans le fichier index.php
du contrôleur frontal public
, on peut y inclure le fichier autoload.php
et instancier nos classes.
spl_autoload_register(function ($className) {
// par exemple si on est dans le dossier public
$file = '../model/' . str_replace('\\', '/', $className) . '.php';
if (file_exists($file)) {
require_once $file;
}
});
// Instanciation de la classe avec son namespace
$maClasse = new MonNamespace\MaClasse();
// ou on peut utiliser le namespace dans le fichier
use MonNamespace\MaClasse;
$className2 = new MaClasse();
// si on a 2 classes avec le même nom dans 2 namespaces différents, on peut éviter les conflits en utilisant le mot clé as
use MonNamespace1\MaClasse as MaClasse1;
use MonNamespace2\MaClasse as MaClasse2;
$className1 = new MaClasse1();
$className2 = new MaClasse2();
Voici une méthode plus complète gérant le namespace
et l'auto-chargement des classes :
// RACINE_PATH se trouve à la racine du projet,
// par exemple dans config.php
// avec const RACINE_PATH = __DIR__
spl_autoload_register(function ($class) {
$class = str_replace('\\', '/', $class);
require RACINE_PATH.'/' .$class . '.php';
});
La fonction d'auto-chargement peut être définie dans un fichier séparé. Dans ce cas, le fichier doit être inclus avant d'instancier une classe.
// Inclusion du fichier contenant la fonction d'auto-chargement
require_once 'autoload.php';
// Instanciation de la classe
$maClasse = new MaClasse();
Une exception est une erreur qui se produit lors de l'exécution d'un script. Elle est utilisée pour gérer les erreurs et les exceptions.
Pour définir une exception, utilisez le mot clé throw
:
throw new Exception('Message de l\'exception');
Une exception peut être attrapée par un bloc try...catch
. Un bloc try...catch
est utilisé pour attraper une exception et la gérer.
try {
// Code du bloc try
} catch (Exception $e) {
// Code du bloc catch
}
Pour gérer l'exception, on peut utiliser la méthode getMessage()
de l'objet exception :
try {
throw new Exception('Message de l\'exception');
} catch (Exception $e) {
echo $e->getMessage();
}
Exemple d'utilisation des exceptions personnalisées :
<?php
class DivisionParZeroException extends Exception
{
public function __construct($message =
"Division par zéro impossible")
{
parent::__construct($message);
}
}
class Division
{
public function diviser($a, $b)
{
if ($b == 0) {
throw new DivisionParZeroException();
}
return $a / $b;
}
}
$division = new Division();
try {
echo $division->diviser(10, 0);
} catch (DivisionParZeroException $e) {
echo $e->getMessage();
}
Le mapping de tables SQL en classes PHP est utilisé pour mapper les tables SQL en classes PHP. Cela permet de manipuler les données de la base de données en utilisant des objets.
Prenons un exemple simple avec une table user
:
CREATE TABLE user (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL
);
Nous allons créer une classe User
qui va représenter la table user
:
class User {
// Propriétés
private int $id;
private string $name;
private string $email;
// Constructeur
public function __construct(int $id, string $name,
string $email) {
$this->setId($id);
$this->setName($name);
$this->setEmail($email);
}
// getters
public function getId() {
return $this->id;
}
public function getName() {
return $this->name;
}
public function getEmail() {
return $this->email;
}
// setters
public function setId(int $id) {
$this->id = $id;
}
public function setName(string $name) {
$this->name = trim(strip_tags($name));
}
public function setEmail(string $email) {
$this->email = filter_var($email,
FILTER_VALIDATE_EMAIL));
}
}
On peut utiliser une classe abstraite comme parent nous permettant l'hydratation
de nos classes
<?php
class AbstractModel
{
// constructeur - Appelé lors de l'instanciation
public function __construct(array $tab)
{
// tentative d'hydration des données de Personnage
$this->hydrate($tab);
}
// création de notre hydratation, en partant d'un tableau associatif et de ses clefs,
// on va régénérer le nom des setters existants
protected function hydrate(array $assoc)
{
// tant qu'on a des éléments dans le tableau
foreach ($assoc as $clef => $valeur) {
// création du nom de la méthode
$methodeName = "set" . str_replace("_", "", ucfirst($clef));
// si la méthode existe
if (method_exists($this, $methodeName)) {
$this->$methodeName($valeur);
}
}
}
}
Ce qui donnera pour le cas User
class User extends AbstractModel {
// Propriétés
private int $id;
private string $name;
private string $email;
// getters
public function getId() {
return $this->id;
}
public function getName() {
return $this->name;
}
public function getEmail() {
return $this->email;
}
// setters
public function setId(int $id) {
$this->id = $id;
}
public function setName(string $name) {
$this->name = trim(strip_tags($name));
}
public function setEmail(string $email) {
$this->email = filter_var($email,
FILTER_VALIDATE_EMAIL));
}
}
Un manager est une classe qui permet de manipuler les données d'une table SQL. Il permet de faire le lien entre les objets et la base de données.
Nous allons créer une classe UserManager
qui va permettre de manipuler les données de la table users
:
class UserManager
{
private PDO $pdo;
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
public function getUser(int $id): User
{
$stmt = $this->pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute(['id' => $id]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
return new User($user['id'], $user['name'], $user['email']);
}
public function getUsers(): array
{
$stmt = $this->pdo->query('SELECT * FROM users');
$users = [];
while ($user = $stmt->fetch(PDO::FETCH_ASSOC)) {
$users[] = new User($user['id'], $user['name'], $user['email']);
}
return $users;
}
public function addUser(User $user): void
{
$stmt = $this->pdo->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
$stmt->execute(['name' => $user->getName(), 'email' => $user->getEmail()]);
}
public function updateUser(User $user): void
{
$stmt = $this->pdo->prepare('UPDATE users SET name = :name, email = :email WHERE id = :id');
$stmt->execute(['id' => $user->getId(), 'name' => $user->getName(), 'email' => $user->getEmail()]);
}
public function deleteUser(int $id): void
{
$stmt = $this->pdo->prepare('DELETE FROM users WHERE id = :id');
$stmt->execute(['id' => $id]);
}
}