# Programmation PHP/Programmation orientée objet

* Introduction
* Installer PHP
* Composer
* IDE
** PhpStorm
** NetBeans
** Eclipse
** Visual Studio Code
* Bases du langage
** Commentaires
** Premier programme
** Variables
** Variables superglobales
** Constantes
** Opérateurs
** Fonctions
** Tableaux
** Structures de contrôle
** Boucles
* Programmation avancée
** Dates
** Sessions
** Cookies
** Cache
*** Memcached
*** Redis
** Formulaire
** Fichiers
*** Objets COM
*** Images
** Mails
** Sécurité
** Programmation orientée objet
** Bases de données
*** Microsoft SQL Server
*** MySQL
*** PDO
*** SQLite
** Expressions rationnelles
** Code de haute qualité
*** Analyse statique de programmes
** Exceptions
** Xdebug
** Mots réservés
* Apprendre par l'exemple
** Utilisation de variables
** Un sommaire simple
** Interaction avec un formulaire
** Afficher le résultat d'une requête BDD
** Modifier une table
** Faire un livre d'or
** Faire un mini forum de discussion
** Parser avec DomXml
** Coder en MVC
** Faire un webservice
** Vérification RIO
** AJAX
** Sommaire en Ajax
** Mise à jour périodique d'un cadre
** Mini CMS
** Introduction
** Développement
*** Les couches choisies
*** Code de service
*** Modélisation
*** Implémentation
*** La vue
*** Ajaxification
*** Premier noyau
*** Fournir les données
*** IHM
** Rétrospective
** Conclusion
* Extensions PHP
** cURL
** DOMDocument
** JSON
** MING
** SPL
* Bibliothèques externes
** ADODB
** DOMPDF
** FPDF
** PHPExcel
** PHPMailer
** PHPWord
** RabbitMQ
* Cadriciels
** CakePHP
** PEAR
** Symfony
** Frameworks de tests
*** PHPUnit
*** SimpleTest
*** Behat
* Logiciels métier
* Problèmes connus
* Introduction
* Installer PHP
* Composer
* IDE
** PhpStorm
** NetBeans
** Eclipse
** Visual Studio Code
* Bases du langage
** Commentaires
** Premier programme
** Variables
** Variables superglobales
** Constantes
** Opérateurs
** Fonctions
** Tableaux
** Structures de contrôle
** Boucles
* Programmation avancée
** Dates
** Sessions
** Cookies
** Cache
*** Memcached
*** Redis
** Formulaire
** Fichiers
*** Objets COM
*** Images
** Mails
** Sécurité
** Programmation orientée objet
** Bases de données
*** Microsoft SQL Server
*** MySQL
*** PDO
*** SQLite
** Expressions rationnelles
** Code de haute qualité
*** Analyse statique de programmes
** Exceptions
** Xdebug
** Mots réservés
* Apprendre par l'exemple
** Utilisation de variables
** Un sommaire simple
** Interaction avec un formulaire
** Afficher le résultat d'une requête BDD
** Modifier une table
** Faire un livre d'or
** Faire un mini forum de discussion
** Parser avec DomXml
** Coder en MVC
** Faire un webservice
** Vérification RIO
** AJAX
** Sommaire en Ajax
** Mise à jour périodique d'un cadre
** Mini CMS
** Introduction
** Développement
*** Les couches choisies
*** Code de service
*** Modélisation
*** Implémentation
*** La vue
*** Ajaxification
*** Premier noyau
*** Fournir les données
*** IHM
** Rétrospective
** Conclusion
* Extensions PHP
** cURL
** DOMDocument
** JSON
** MING
** SPL
* Bibliothèques externes
** ADODB
** DOMPDF
** FPDF
** PHPExcel
** PHPMailer
** PHPWord
** RabbitMQ
* Cadriciels
** CakePHP
** PEAR
** Symfony
** Frameworks de tests
*** PHPUnit
*** SimpleTest
*** Behat
* Logiciels métier
* Problèmes connus
[ Modifier le sommaire ]

## Introduction

Une classe est un format de variable non scalaire, comprenant trois types de composants :
* des constantes, accessibles par réflexion avec $maClasse::getConstants.
* des variables appelées "propriétés", accessibles avec $maClasse::getProperties.
* des fonctions appelées "méthodes", accessibles avec $maClasse::getMethods.
La programmation orientée objet s’effectue en deux étapes : la définition des classes, puis leur utilisation. Une fois la classe définie, il est en effet possible de créer des objets, appelés "instances", au format de la classe définie. Toutefois, les composants déclarés avec le mot static sont persistants, et accessibles sans instanciation préalable.

### Opérateur objet

Pour accéder aux propriétés et méthodes d'un objet, on utilise l'opérateur object : ->.

### Opérateur de résolution de portée

Pour accéder aux constantes, propriétés et méthodes statiques d'une classe, on utilise l'opérateur de résolution de portée : ::.
Cet opérateur peut également être précédé de noms de classes ou des mots réservés suivants :
* $this : l'objet courant.
* parent : la classe parente.
* static : la classe courante.
* self : la classe parente puis la courante s'il n'y a rien.
Le mot-réservé static a donc deux sens : un pour les déclarations et un pour les appels.

## Inclusion

À l'instar d'une bibliothèque de fonctions, une classe est généralement stockée dans un fichier dédié, qui peut porter son nom.
Elle s'inclut donc dans un programme de la même manière qu'une bibliothèque :
Mais la syntaxe à privilégier est celle par espace de nom :
En PHP, l'inclusion doit précéder les appels du code qui y figure.

## Instanciation

Une fois la classe incluse, on peut l'appeler.
* Directement pour une classe statique.
* Après instanciation sinon. Elle est réalisée par le mot-clé "new".
Par défaut, PHP fournit déjà la classe suivante pour créer des objets anonymes :

## Définition des classes

Définir une nouvelle classe adopte la syntaxe suivante :
Il est possible d’attribuer une valeur par défaut. Le code dans la classe est alors var $variable1 = valeur;. Cette syntaxe est économe puisqu'elle évite d'initialiser la variable à chaque appel des méthodes qui l'utilisent.
La définition de méthodes de classe est identique à celle de n’importe quelle fonction à la différence que lorsqu’elle fait référence à une variable de sa classe, $variable doit être :
* $this->variable pour cibler l'objet instancié (et $this::constante, $this->méthode).
* self::variable pour cibler la classe statique.
De même pour exécuter une autre méthode de sa classe. ex :
Pour utiliser une variable qui n'est pas dans la classe ou exécuter les méthodes d'une autre classe, il faut les redéclarer avec global :

## Utilisation d’un objet

Attention : la classe est la définition d’un format de variable personnalisable. Le code n’est pas exécuté et il est impensable d’introduire le code suivant qui n’aurait aucun sens :
Une fois la classe définie, il va falloir créer des variables objet du format de la classe définie. On crée un objet par le code suivant :
Il faut bien entendu avoir préalablement défini la classe client. La variable $objet contient donc un objet. Pour accéder à une variable pour lui faire subir des modifications, il suffit d’entrer le code suivant :
Il est possible de lui faire subir les mêmes opérations qu’à une variable normale. De même pour exécuter une fonction :
Autant les méthodes une fois définies ne peuvent pas être modifiées, autant il est possible d’ajouter ou de supprimer des variables dans l’objet :
L’objet est unique, de sorte que s’il est enregistré dans une autre variable et qu’une modification lui est faite, elle sera visible pour les deux variables :
Pour dupliquer une variable de type objet, il faut donc entrer le code suivant :
La nouvelle variable sera différente de l’ancienne mais aura les mêmes valeurs.
Il est également possible d'exécuter la méthode d'un objet sans avoir créé de variable auparavant :

## Héritage

PHP était initialement un langage à héritage simple, c'est-à-dire qu'une classe ne peut hériter que d'au plus une seule autre classe.
L'héritage consiste à transmettre les propriétés et méthodes d’une classe mère à une classe fille, en déclarant cette dernière avec extends. Ex :
L'héritage permet le polymorphisme, qui consiste à utiliser des variables ou méthodes dans des classes de plusieurs types, grâce à l'héritage.
Les classes filles bénéficieront automatiquement de toutes les propriétés et des méthodes de leur classe mère (qui n'a pas de limite dans le nombre de ses filles).
Les interfaces peuvent par contre bénéficier d'un héritage multiple.
On peut aussi invoquer les méthodes parentes depuis la classe enfant :

### Traits

Depuis PHP 5.4.0, une structure de données appelée "trait" permet l'héritage multiple. Exemple d'utilisation :
Les traits sont limités par rapport aux classes :
* Un trait ne peut pas contenir de constante.
* Un trait ne peut pas hériter d'une classe, il doit utiliser un autre trait à la place.
De plus, ce type d'injection de dépendance est contraire au principe SOLID d'inversion des dépendances.

### Final

Pour empêcher une classe ou une méthode d'être étendue (et en faire donc une classe finale ou une méthode finale), on peut la déclarer avec le mot-clé final. Ex :

## Classes abstraites

La classe abstraite ne peut pas être instanciée, mais elle peut être appelée en statique. Comme pour l'héritage classiques, ses classes filles accèdent à ses attributs et méthodes publics et protégés.
Voici un exemple de classe abstraite :
Dans cet exemple, on voit que les méthodes d'une classe abstraite peuvent contenir du code, mais les méthodes abstraites non (elles ne définissent que les arguments
Les méthodes abstraites sont obligatoirement à implémenter par les classes filles.

## Closures

Apparues avec PHP 5.3, les closures sont des classes avec des méthodes gérant les fonctions anonymes.

## Classes anonymes

Apparues avec PHP 7, les classes anonymes sont des classes sans nom, déclarées lors de l'exécution.

## Interfaces

Voici un exemple d'interface :
Et son utilisation : la classe doit reprendre les méthodes de l'interface sous peine d'erreur.
* Les méthodes d'une interface ne peuvent pas contenir de code.
* Une classe ou une interface ne peut implémenter qu'une ou plusieurs interfaces (donc pas d'implémentation de classe).
* Une interface ne peut hériter que d'une autre interface.
* Toutes les méthodes d'une interface doivent être publiques.
* Si un objet hérite et implémente, toujours le déclarer en plaçant le extends avant le implements.

## Namespaces

Exemple d'espace de noms :
Pour utiliser un namespace, "use" conserve son nom mais on peut le changer avec "as" :
Depuis PHP7 on peut même importer plusieurs classes, fonctions ou constantes sur la même ligne :

## Portée des variables

Il est possible depuis PHP5 de préciser l'accès à certaines variables ou méthodes, en les déclarant à la place de var avec :
* public : visible dans tout le programme.
* protected : visible uniquement dans les instances de la classe et de ses sous-classes.
* private : visible uniquement dans les instances de la classe.
Exemple :
En effet, il faut gagner de l’argent avant d’en ajouter à la banque (quoique...).
Ce code retournera un message d’erreur s'il est exécuté sous PHP5 ou une version ultérieure.

## Les méthodes prédéfinies

Il existe quelques méthodes prédéfinies qui s’exécutent automatiquement à des périodes de la vie de l’objet. Elles sont appelées méthodes magiques, et leurs noms commencent toujours par deux underscores :
* __call : à chaque appel d'une méthode de la classe.
* __callStatic : à chaque appel statique d'une méthode de la classe.
* __clone : lors du clonage de l'objet (via la fonction "clone").
* __construct : à l'instanciation de la classe.
* __debugInfo : modifie les résultats des var_dump.
* __destruct : à la suppression de l'objet instancié.
* __get : à la lecture de propriétés inexistantes ou interdites.
* __invoke : à l'appel de l'objet comme une fonction (ex : echo $object(1)).
* __isset : à l'appel de isset (ou empty) sur des propriétés inexistantes ou interdites.
* __serialize : à l'appel de serialize.
* __set : à l'écriture de propriétés inexistantes ou interdites.
* __set_state : modifie les résultats des var_export.
* __sleep : à l'appel de serialize, pour en modifier le résultat.
* __toString : à l'appel de l'objet comme une chaine de caractères (ex : echo $object).
* __unserialize : à l'appel de serialize.
* __unset : à l'appel de unset sur des propriétés inexistantes ou interdites.
* __wakeup : à l'appel de unserialize, pour en modifier le résultat.

### Constructeur et destructeur
#### __construct

    Cette méthode s’exécute lors de la création de l’objet. On entre alors les attributs potentiels de la fonction lors de sa création. Cette méthode est appelée "le constructeur"

#### __destruct

    Cette méthode s’exécute au contraire au moment de la destruction de la variable. Elle est appelée "le destructeur".
Voici un exemple utilisant les méthodes :
Sous php4, le constructeur avait pour nom celui de la classe. Sous php5, si la fonction __construct n’est pas trouvée, l’interpréteur cherchera une méthode du même nom que la classe.

### Copie en profondeur

Il existe une méthode qui s’exécute lors d’une duplication de l’objet. Son nom est __clone.
En effet, elle est utile car par défaut si $x = $y, $x n'est qu'une référence à $y et changer $x changera $y.

### __get, __set, __call

Ces méthodes permettent de rendre dynamique l'utilisation de la classe, et permettent la surcharge magique.

#### __call

La méthode __call s'exécute quand une méthode appelée est inaccessible ou inexistante. Exemple :

#### _get

Cette méthode s'exécute quand une variable appelée est inaccessible ou inexistante. L'exemple ci-dessous lui permet de retourner une donnée dépendant du contenu de la variable $nom. Important : le contenu de la variable $nom ne sera pas prioritaire sur le nom d'une variable interne à la classe.
On voit ici que PHP va chercher en priorité à retourner une variable interne, mais si elle est privée ou inexistante, il prendra le résultat du __get.
Ne jamais accéder à une variable de classe privée dans son __get sous peine de boucle infinie.
Exemple de réécriture de la méthode __get ci-dessus pour accéder à la variable privée :

#### __set

Cette méthode s'exécute quand on modifie une variable inaccessible ou inexistante. Exemple :

### __sleep et __wakeup

Ces méthodes ne fonctionnent plus avec l'interface Serializable depuis PHP 8.1, au profit de serialize et unserialize.
Elles permettent respectivement de sauvegarder et restaurer l'état d'un objet, pour qu'il soit fonctionnel après une sérialisation / désérialisation. C'est utile par exemple pour se reconnecter à une base de données.

### __invoke

Cette méthode rend la classe invocable, c'est-à-dire qu'après instanciation, elle s'exécute si on l'appelle comme une méthode. Ex :

## Quelques fonctions intégrées

Voici quelques fonctions en relation avec la programmation orientée objet qui peuvent vous être utiles.

### self

Une classe peut s'instancier elle-même avec new self;.

### class_exists

Vérifie qu’une classe existe. Renvoie une valeur booléenne. ex :

### get_class_methods

Retourne toutes les méthodes d’une classe sous forme de tableau. Ex :

### get_class_vars

Retourne tous les attributs d'une classe (dont la portée est accessible, donc généralement les publiques), ainsi que leurs valeurs par défaut sous forme de tableau. Ex :
Peut donc servir pour un "foreach" propriétés de la classe.
Pour récupérer ou filtrer les attributs privés, utiliser \ReflectionClass::getProperties :

### get_object_vars

Idem avec les valeurs courantes de l'objet instance de classe.

### method_exists($classe, $méthode)

Teste sur une méthode existe dans une classe.

### serialize et unserialize

Assurent la transformation du flux de données, en précisant les types des variables et index des tableaux. Exemple :
Le préfixe "a:2" signifie "array of 2 lines", et il est obligatoire pour désérialiser.

## Références

* ↑ http://php.net/manual/fr/language.oop5.paamayim-nekudotayim.php
* ↑ https://www.php.net/manual/fr/language.oop5.static.php#104823
* ↑ https://www.php.net/manual/fr/filesystem.configuration.php
* ↑ Sébastien Rohaut, Algorithmique : Techniques fondamentales de programmation (avec des exemples en PHP), Editions ENI, 2009 (lire en ligne)
* ↑ http://php.net/manual/fr/language.oop5.basic.php
* ↑ http://php.net/manual/fr/language.oop5.abstract.php
* ↑ http://php.net/manual/fr/class.closure.php
* ↑ https://secure.php.net/manual/fr/language.oop5.anonymous.php
* ↑ https://www.safaribooksonline.com/library/view/php-5-power/013147149X/013147149X_ch03lev1sec14.html
* ↑ http://php.net/manual/fr/language.oop5.magic.php
* ↑ http://php.net/manual/fr/language.oop5.overloading.php
* ↑ https://www.php.net/manual/en/class.serializable.php
* ↑ https://www.php.net/manual/fr/reflectionclass.getproperties.php