Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Apprendre à développer un site web avec PHP et MySQL
  3. L’objet
Extrait - Apprendre à développer un site web avec PHP et MySQL Exercices pratiques et corrigés (5e édition)
Extraits du livre
Apprendre à développer un site web avec PHP et MySQL Exercices pratiques et corrigés (5e édition) Revenir à la page d'achat du livre

L’objet

Introduction

L’objectif de ce chapitre n’est pas de vous expliquer toutes les subtilités de la programmation orientée objet (POO) mais simplement de voir les bases pour vous permettre de programmer un code simple ou de comprendre comment fonctionne un code objet existant.

Pour l’instant, le code vu est de type procédural, c’est-à-dire que vous créez des fonctions que vous appelez au moment où vous en avez besoin, tout cela dans l’ordre chronologique.

En POO, presque tout est objet et tous les objets interagissent entre eux.

Un objet a des caractéristiques appelées attributs et des actions appelées méthodes.

Par exemple, l’objet Animal a les attributs couleur et poids. Il a aussi comme méthodes se_deplacer et manger.

Pour construire ces objets, il faut utiliser une classe.

Les classes

1. Introduction

Une classe sert à fabriquer des objets à partir d’un modèle. Ces objets ont leurs propres attributs et certaines méthodes.

Par exemple, la classe Animal a les attributs couleur et poids et les méthodes manger ou se_deplacer.

images/08PHP01.png

Lorsque vous allez créer des exemplaires d’animaux à partir de la classe Animal, vous allez créer une instance de cette classe. Instancier une classe revient à créer un objet d’un certain type (Animal) avec certains attributs (couleur, poids).

Création d’une classe en PHP :

<?php 
   class Animal // mot-clé class suivi du nom de la classe. 
   { 
       // Déclaration des attributs et méthodes. 
   } 
?> 

Il est conseillé de mettre une classe par fichier PHP ayant le même nom que la classe.

2. L’encapsulation

En POO, tous vos attributs doivent être cachés aux autres personnes utilisant vos classes. Si vous travaillez en équipe et que vous avez créé la classe Animal, les autres développeurs ne doivent pas pouvoir changer directement les attributs de votre classe. Ainsi, les attributs couleur et poids sont cachés aux autres classes. Ils sont donc déclarés privés. La classe Animal a des méthodes pour lire ou écrire dans ces attributs. C’est le principe de l’encapsulation. Cela permet d’avoir un code plus protégé lorsque vous travaillez en équipe.

La classe Animal, ayant les propriétés couleur et poids, a une méthode pour modifier sa couleur, une méthode pour lire sa couleur, une méthode pour modifier son poids, une méthode pour lire son poids ainsi que d’autres méthodes comme manger ou se_deplacer (voir la section Mettre à jour et lire les attributs de l’instance plus loin dans ce chapitre).

3. Visibilité des attributs et des méthodes

Il existe trois types de mots-clés pour définir la visibilité d’un attribut ou d’une méthode :

  • private : seul le code de votre classe peut voir et accéder à cet attribut ou méthode.

  • public : toutes les autres classes peuvent voir et accéder à...

L’héritage

1. Introduction

L’héritage est un concept très important en POO. Cela permet de réutiliser le code d’une classe sans le retaper.

Une classe fille hérite d’une classe mère, c’est-à-dire que la classe fille accède alors à tous les attributs et les méthodes publiques de la classe mère.

Par exemple, la classe Mammifère hérite de la classe Animal et la classe Voiture hérite de la classe Véhicule.

Si vous pouvez dire que la classe A est une sous-catégorie de la classe B, alors vous pouvez certainement faire en sorte que la classe A (Mammifère ou Voiture) hérite de la classe B (Animal ou Véhicule).

Par la suite, les classes Poisson et Chat sont prises comme exemple pour hériter de la classe Animal.

images/08PHP02.png

Pour créer la classe Poisson qui hérite de la classe Animal, il faut utiliser le mot-clé extends entre le nom de la classe fille et le nom de la classe mère.

Créer un fichier Poisson.class.php et taper le code ci-dessous :

<?php 
class Poisson extends Animal 
    { 
 
    } 
?> 

Il faut maintenant lui ajouter un attribut privé correspondant à la variable vivant_en_mer puis les accesseurs get et set et enfin la méthode publique nager().

<?php 
class Poisson extends Animal 
    { 
        private bool $vivant_en_mer; //type du poisson 
 
        //accesseurs 
        public function getType(): string 
        { 
             if ($this->vivant_en_mer){ 
             return "vivant_en_mer"; 
        } 
        else if ($this->vivant_en_mer===false){ 
             return "ne_vivant_pas_en_mer"; 
        }else {return "";} ...

Les classes abstraites

Les classes abstraites s’écrivent en ajoutant le mot-clé abstract devant le mot-clé class. Une classe abstraite ne peut pas être instanciée, c’est-à-dire qu’il n’est pas possible de créer une instance. Vous pouvez écrire des méthodes abstraites. Ce sont des méthodes dont uniquement la signature est écrite, précédée du mot-clé abstract : abstract visibilité function nomMéthode(attribut type_attribut...). Vous pouvez aussi implémenter des méthodes normales dans les classes abstraites. Ces classes servent donc uniquement à obliger les classes héritant de la classe abstraite à redéfinir les méthodes déclarées abstraites dans la classe abstraite et à factoriser les méthodes implémentées.

Dans l’exemple suivant, la classe Animal est abstraite car vous ne voulez pas créer (instancier) des animaux mais uniquement des poissons ou des chats.

Ajouter aussi une méthode abstraite respire() dans la classe Animal :

<?php 
abstract class Animal 
   { 
       // Déclaration des attributs 
       private string $couleur = "gris"; 
       private int $poids = 10; 
 
       //constantes de classe 
   ...

Substitution de méthodes abstraites

Depuis PHP 7.2, il est possible de substituer une méthode abstraite dans une classe héritant d’une autre classe abstraite.

Par exemple :

<?php  
abstract class Animal { 
 
   //déclaration de la méthode abstraite courir 
   abstract function courir(int $kilometre): void;   
  
} 
abstract class Chien extends Animal { 
   //substitution de la méthode abstraite courir 
   abstract function courir($kilometre): void; //Type omis  
  
}   
?> 

Les types des paramètres des méthodes substituées dans les classes abstraites comme dans les interfaces peuvent être omis car les types de paramètres sont contravariants.

Les interfaces

Les interfaces sont semblables aux classes abstraites. Elles ne peuvent pas être instanciées, mais vous ne pouvez pas implémenter de méthode dans les interfaces. Vous ne pouvez pas non plus déclarer de variables dans les interfaces. Ces classes servent donc uniquement à obliger les classes héritant de l’interface à redéfinir les méthodes déclarées dans l’interface. Ces méthodes sont forcément publiques. Une interface se déclare avec le mot-clé interface :

Voici le code de l’interface action :

<?php 
interface action { 
  function courir(): void; 
  
  function manger(): void; 
} 
?> 

Pour signaler qu’une classe implémente une ou plusieurs interfaces, vous devez ajouter le mot-clé implements suivi du nom des interfaces.

Voici un exemple signalant que la classe Chat implémente l’interface action :

<?php 
class Chat extends Animal implements action 
   { 
   ... 
 
   //méthodes de l'interface 
   function courir(): void { 
      echo "Le chat court.<br />"; 
   } 
 
   function manger(): void { 
     echo...

Les énumérations

Les énumérations ou Enums permettent de définir un type personnalisé limité à un nombre de valeurs possibles.

Il existe les énumérations basiques :

enum Couleur { 
        case Trèfle; 
        case Carreau; 
        case Coeur; 
        case Pique; 
} 

et les "Back Enums" qui possèdent une valeur pour chaque cas :

enum Couleur: string { 
        case Trèfle = 'T'; 
        case Carreau = 'CA'; 
        case Coeur = 'CO'; 
        case Pique = 'P'; 
} 

Vous pouvez parcourir tous les éléments de l’énumération grâce à la fonction cases() :

foreach (Couleur::cases() as $case) { 
    echo $case->name,': ',$case->value."\n"; 
} 

Il existe deux méthodes assez pratiques pour retrouver une énumération.

La première est la méthode from() qui permet de retrouver l’énumération à partir...

Les classes readonly

Lorsqu’une classe est déclarée readonly, toutes ses propriétés sont en lecture seule. Cela peut être pertinent lorsque vous voulez transférer des données dans la classe une seule fois.

Vous ne pouvez donc affecter des valeurs aux propriétés en lecture seule qu’une seule fois :

$poisson = new Poisson("gris",10); 
$poisson?setPoids(15); //provoque une erreur 

Les classes readonly ne peuvent hériter que de classes readonly.

Les classes abstraites et finales peuvent aussi être readonly. Le mot-clé readonly se place entre abstract (ou final) et class.

Il est aussi possible de rendre uniquement certaines propriétés en lecture seule.

Pour cela, il suffit d’ajouter le mot-clé readonly devant son type :

class Poisson extends Animal 
{ 
    public function __construct(public readonly bool 
$vivant_en_mer) { } 
} 
 
$poisson = new Poisson(true); 
$poisson->vivant_en_mer = false; //provoque une erreur 
//car la valeur a déjà été affectée dans le constructeur 

Les classes finales

Lorsqu’une classe est finale, vous ne pouvez pas créer de classe fille héritant de cette classe. Cela n’a guère d’intérêt en pratique.

Il faut pour cela ajouter le mot-clé final devant le mot-clé class.

Par exemple, si vous ne créez pas de classe héritant de la classe Poisson, vous pouvez la mettre final :

<?php 
final class Poisson extends Animal  
   { 
       private bool $vivant_en_mer; //type du poisson 
 
       //accesseurs 
       ...
       //méthode 
       public function nager(): void 
       { 
           echo "Je nage <br />"; 
       } 
 
       public function respire(): void 
       { 
           echo "Le poisson respire.<br />"; 
       } 
 
   } 
?> 

Il est possible aussi de déclarer des méthodes finales. Ces méthodes ne pourront pas alors être substituées.

Vous avez vu dans la section sur la substitution un exemple où la méthode manger_animal(Animal $animal_mangé)...

Les méthodes magiques

Une méthode magique est une méthode qui est appelée automatiquement lorsqu’un évènement se produit.

Par exemple, __construct est une méthode magique. Elle s’exécute automatiquement lorsque vous instanciez la classe contenant __construct.

Les méthodes magiques __get et __set permettent de lire ou de modifier des attributs qui n’existent pas ou dont l’accès est interdit.

Reprenez l’exemple au départ du chapitre avec la classe Animal :

images/08PHP01.png

Cette fois, l’attribut couleur est privé mais l’attribut poids est public :

<?php 
class Animal 
    { 
        // Déclaration des attributs 
        private string $couleur = "gris"; 
        public int $poids = 10; 
 
        public function __construct(string $couleur, int $poids) 
// Constructeur 
//demandant 2 paramètres. 
        { 
          echo 'Appel du constructeur.<br />'; 
          $this->couleur = $couleur; // Initialisation de la couleur. 
          $this->poids = $poids; // Initialisation du poids. 
 
        } 
 
 
        //méthodes publiques 
        public function manger(): void 
        { 
 
        } 
 
        public function se_deplacer(): void 
        { 
 
        } 
} 
?> 

Lorsque vous créez une instance de la classe Animal, vous pouvez accéder à l’attribut poids car il est public mais pas à l’attribut couleur car il est privé.

La page utilisation.php :

<?php 
 
//chargement des classes ...

Les classes anonymes

Cette fonctionnalité, arrivée avec PHP 7, permet d’utiliser une classe sans avoir à définir entièrement une classe. Cette classe n’a pas de nom et est utilisée une seule fois. Cela se fait grâce à l’instruction new class.

Par exemple :

//création de la classe anonyme
$classe_anonyme = new Class { 
    public $message = "Bonjour"; 
 
     public function getMessage() { 
        return "Salut"; 
    } 
  
}; 
 
echo $classe_anonyme->getMessage(); 

Affiche :

Salut.

Autre exemple montrant la différence entre PHP 5.6 et PHP 7 :

//Première solution avant PHP 7 
//création de la classe Message
class Message 
{  
    public function Affiche_message($msg) 
    { 
         echo $msg; 
    }
} 
class Util 
{ 
    public $message;  
    public function setMessage(Message $message) { 
        $this->message = $message;  
    }
}
$util = new Util(); 
$util->setMessage(new Message()); 
//Affichage du message 
$util->message->Affiche_message("Bonjour"); ...

Les traits

Cette fonctionnalité permet de réutiliser du code dans deux classes indépendantes. Sa syntaxe est :

trait nom_du_trait { 
   //définition des propriétés et méthodes. 
} 

Prenez l’exemple de deux classes indépendantes Facture et Indemnite ayant une méthode Calcul_taux_tva.

<?php 
//déclaration du trait 
trait MonTrait 
{ 
  public function Calcul_ttc(float $montant) : float 
 { 
    return $montant*1.2; //retourne le montant TTC 
  } 
} 
 
class Facture 
{ 
 use MonTrait; 
} 
 
class Indemnite 
{ 
  use MonTrait; 
} 
 
$facture = new Facture; 
//affichage du montant TTC de la facture 
echo $facture->Calcul_ttc(10)."<br />"; 
 
$indemnite = new Indemnite; 
//affichage du montant TTC de l'indemnité 
echo $indemnite->Calcul_ttc(20); 
?> 

Affiche :

12

24

Cela permet aux deux classes Facture et Indemnite d’utiliser la même méthode calcul_ttc sans recourir à l’héritage.

Depuis PHP 8, il est possible d’utiliser des méthodes abstraites et des constantes dans les traits :

<?php 
//déclaration du trait  
trait...

Uniform Variable Syntax

Cette syntaxe de variable uniforme vous permet de résoudre certaines incohérences sur l’évaluation des expressions. Il est possible d’accéder à une propriété avec cette syntaxe :

$obj->{$properties['name']}; 

Par exemple :

<?php 
//Déclaration de la classe Objet 
class Objet { public $couleur ="rouge"; } 
//Instanciation de la classe Objet 
$obj = new Objet(); 
$properties['name'] = "couleur"; 
echo $obj->{$properties['name']}; 
?> 

Affiche :

rouge

En effet, $obj->{$properties[’name’]} revient à écrire $obj->couleur.

Depuis PHP 7, il est possible d’attacher des appels statiques.

Par exemple :

<?php 
//Déclaration de la classe 1 
class classe1 { static $nom1 = 'classe2'; } 
//Déclaration de la classe 2 
class classe2 { static $nom2 = 'Bonjour'; } 
//Déclaration de la méthode permettant d'afficher Bonjour 
classe2::$nom2 = function () { echo "Bonjour !"; }; 
$classe1 = 'classe1'; 
//Appel statique 
($classe1::$nom1::$nom2)(); 
?> 

Affiche :

Bonjour !

Depuis PHP 8.1, il est possible de créer un objet directement dans les paramètres...

Les espaces de noms

Lorsque vous travaillez sur des projets de taille importante en équipe, il est utile de modulariser les classes et les fonctions. Ainsi, chaque développeur peut travailler sur son propre module. Les namespaces (espaces de noms) permettent cette modularisation. Un namespace est une sorte de dossier virtuel dans lequel vous stockez vos objets. Il est ainsi possible de mettre des classes ou des fonctions de même nom dans des namespaces différents. 

Un namespace est déclaré avec le mot-clé namespace suivi de son nom en début de fichier.

Par exemple :

Espace_nom.php

<?php 
// Définition de l'espace de noms. 
namespace Bibliotheque; 
// Définition d'une constante. 
const PI = 3.1416; 
// Définition d'une fonction. 
function maFonction() { 
echo "Bonjour";3 
} 
// Définition d'une classe. 
class maClasse { 
/* 
... 
*/ 
} 
 
?> 

Utilisation_espace_nom.php

<?php 
include('espace_nom.php'); 
Bibliotheque\maFonction(); //Appel du namespace Bibliotheque 
à la racine 
?> 

Affiche :

Bonjour

La constante __NAMESPACE__ retourne le nom de l’espace de noms courant.

Il est possible de créer des sous-espaces de noms en écrivant :

namespace Espace1\SousEspace1; 

Les chemins pour...

Autoload

La fonction spl_autoload_register() permet d’éviter d’inclure manuellement toutes les classes en début de chaque page PHP. Cette fonction prend en paramètre votre fonction permettant d’inclure les classes nécessaires. 

Par exemple :

<?php 
//Affectation de la fonction gérant l'autoload 
spl_autoload_register('monAutoload'); 
 
function monAutoload($className) 
{ 
    //Les classes sont dans le dossier class 
    $path = '/class/';  
    //Le nom des fichiers doit correspondre au nom de la classe  
    include $path.$className.'.php'; 
} 
//Instanciation de la classe 
$myClass = new MyClass(); 
?> 

Exercices

1. Énoncés

Exercice 1 (facile)

Créer les cinq classes du schéma suivant en tenant compte de leur héritage. Toutes les méthodes sont publiques et les attributs privés.

images/08PHP05.png

Exercice 2 : suite du 1 (facile)

Créer les accesseurs de tous les attributs. Créer un constructeur dans la classe Vehicule prenant en paramètres la couleur et le poids. Modifier la méthode rouler() pour qu’elle affiche "Le véhicule roule". Modifier la méthode ajouter_personne(poids_personne) pour qu’elle change le poids du véhicule en fonction du poids de la personne passé en paramètre.

Créer une page affichage.php créant un véhicule noir de 1500 kg. Le faire rouler.

Ajouter une personne de 70 kg et afficher le nouveau poids du véhicule.

Exercice 3 : suite du 2 (difficulté moyenne)

Implémenter la méthode repeindre(couleur) pour changer la couleur définie dans la classe Vehicule. Implémenter la méthode mettre_essence(nombre_litre) pour changer le poids défini dans la classe Vehicule. Pour cet exercice, un litre correspond à un kilogramme.

Implémenter les méthodes ajouter_pneu_neige(nombre) et enlever_pneu_neige(nombre) modifiant l’attribut nombre_pneu_neige.

Implémenter la méthode ajouter_remorque(longueur_remorque) modifiant l’attribut longueur.

Dans la page affichage.php, créer une voiture verte de 1400 kg. Ajouter deux personnes de 65 kg chacune. Afficher sa couleur et son nouveau poids.

Repeindre la voiture en rouge et ajouter deux pneus neige.

Afficher sa couleur et son nombre de pneus neige.

Créer un objet Deux_roues noir de 120 kg. Ajouter une personne de 80 kg. Mettre 20 litres d’essence.

Afficher la couleur et le poids du deux-roues.

Créer un camion bleu de 10000 kg d’une longueur de 10 mètres avec 2 portes. Lui ajouter une remorque de 5 mètres et une personne de 80 kg.

Afficher sa couleur, son poids, sa longueur et son nombre de portes.

Exercice 4 : suite du 3 (difficulté moyenne)

Rendre la classe Vehicule et sa méthode ajouter_personne(poids_personne) abstraites.

Définir la méthode ajouter_personne(poids_personne) dans la classe Deux_roues pour que cette méthode ajoute le poids de la personne plus 2 kg correspondant au casque du deux-roues....