namespace.Par exemple:
<?php
namespace MonNamespace\MonSousNamespace;
class MaClasse
{
}
$objet = new MonNamespace\MonSousNamespace\MaClasse;
On peut aussi utiliser le mot-clé use pour importer un namespace.
<?php
use MonNamespace\MonSousNamespace\MaClasse;
$objet = new MaClasse;
Si on souhaites charger une classe de PHP après avoir déclaré un namespace, il faudra alors préfixer la classe par un antislash \.
<?php
namespace MonNamespace;
$objet = new \PDO;
Quand on fait:
$objet = new MaClasse;
la variable $objet ne contient pas l'objet à proprement parler.
Quand on instancie une classe, la variable stockant l'objet ne stocke en fait pas l'objet lui-même, mais un identifiant qui représente cet objet.
<?php
class MaClasse
{
public $attribut1;
public $attribut2;
}
$a = new MaClasse;
$b = $a; // On assigne à $b l'identifiant de $a, donc $a et $b représentent le même objet.
$a->attribut1 = 'Hello';
echo $b->attribut1; // Affiche Hello.
$b->attribut2 = 'Salut';
echo $a->attribut2; // Affiche Salut.
$a contient l'identifiant représentant l'objet créé.
On assigne à $b la valeur de $a.
$a et $b font donc référence à la même instance.
$objet1 = $objet2 ne permet pas de "copier un objet". Pour copier toutes les valeurs
d'un objet, il faut utiliser le clonage d'objet :
<?php
$copie = clone $origine; // On copie le contenu de l'objet $origine dans l'objet $copie.
__clone du nouvel objet sera appelée (si elle est définie). (Au même titre que __construct lorsque l’on appelle new)__clone du nouvel objet créé qui est appelée, pas la méthode __clone de l'objet à cloner.<?php
class MaClasse
{
private static $instances = 0; //variable statique, valeur commune à tous les objets de cette classe
public function __construct()
{
self::$instances++;
}
public function __clone()
{
self::$instances++;
}
public static function getInstances()
{
return self::$instances;
}
}
$a = new MaClasse;
$b = clone $a;
echo 'Nombre d\'instances de MaClasse : ', MaClasse::getInstances();
Nombre d'instances de MaClasse : 2
<?php
if ($objet1 == $objet2)
{
echo '$objet1 et $objet2 sont identiques !';
}
else
{
echo '$objet1 et $objet2 sont différents !';
}
true, il faut que :
$objet1 et $objet2 aient les mêmes attributs et les mêmes valeurs.$objet1 et $objet2 soient des instances de la même classe.==Exemple :
<?php
class A
{
public $attribut1;
public $attribut2;
}
class B
{
public $attribut1;
public $attribut2;
}
$a = new A;
$a->attribut1 = 'Hello';
$a->attribut2 = 'Salut';
$b = new B;
$b->attribut1 = 'Hello';
$b->attribut2 = 'Salut';
$c = new A;
$c->attribut1 = 'Hello';
$c->attribut2 = 'Salut';
if ($a == $b) ? echo '$a == $b' : echo '$a != $b';
echo ' <br/>';
if ($a == $c) ? echo '$a == $c' : echo '$a != $c';
$a != $b <br/> $a == $c
Quel est le résultat de ce code ?
$a == $b <br/> $a == $c$a != $b <br/> $a == $c$a != $b <br/> $a != $cResponses: 0
$a et $b ont les mêmes attributs et les mêmes valeurs mais ne sont pas des instances de la même classe.$a et $c sont bien identiques.
===<?php
class A
{
public $attribut1;
public $attribut2;
}
$a = new A;
$a->attribut1 = 'Hello';
$a->attribut2 = 'Salut';
$b = new A;
$b->attribut1 = 'Hello';
$b->attribut2 = 'Salut';
$c = $a;
if ($a === $b) ? echo '$a === $b' : echo '$a !== $b';
echo '<br />';
if ($a === $c) ? echo '$a === $c' : echo '$a !== $c';
$a !== $b<br />$a === $c
Quel est le résultat de ce code ?
$a === $b <br/> $a === $c$a !== $b <br/> $a !== $c$a !== $b <br/> $a === $cResponses: 0
== renvoie maintenant false.$a et $c font référence à la même instance, la condition renvoie donc true.
$valeur sera la valeur de l'attribut actuellement lu.$attribut aura pour valeur le nom de l'attribut actuellement lu et $valeur sera sa valeur.<?php
class MaClasse
{
public $attribut1 = 'Premier attribut public';
public $attribut2 = 'Deuxième attribut public';
protected $attributProtege1 = 'Premier attribut protégé';
protected $attributProtege2 = 'Deuxième attribut protégé';
private $attributPrive1 = 'Premier attribut privé';
private $attributPrive2 = 'Deuxième attribut privé';
function listeAttributs()
{
foreach ($this as $attribut => $valeur)
{
echo '<strong>', $attribut, '</strong> => ', $valeur, '<br />';
}
}
}
class Enfant extends MaClasse
{
function listeAttributs() { // Redéclaration de la fonction
foreach ($this as $attribut => $valeur)
{
echo '<strong>', $attribut, '</strong> => ', $valeur, '<br />';
}
}
}
$classe = new MaClasse;
$enfant = new Enfant;
echo '---- Liste les attributs depuis l\'intérieur de la classe principale ----<br />';
$classe->listeAttributs();
echo '<br />---- Liste les attributs depuis l\'intérieur de la classe enfant ----<br />';
$enfant->listeAttributs();
echo '<br />---- Liste les attributs depuis le script global ----<br />';
foreach ($classe as $attribut => $valeur)
{
echo '<strong>', $attribut, '</strong> => ', $valeur, '<br />';
}
clone.== vérifie que les deux objets sont issus de la même classe et que les
valeurs de chaque attribut sont identiques, tandis que l'opérateur === vérifie que les deux identifiants d'objet sont les mêmes.Exemple
<?php
interface Movable
{
public function move($dest);
}
implements.<?php
interface Movable
{
public function move($dest);
}
class Personnage implements Movable
{
}
Dans ce cas, si on instancie Personnage :
PHP Fatal error: Class Personnage contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Movable::move) in Standard input code on line 6
Personnage n'a pas implémenté la méthode présente dans l'interface Movable
extends,implements<?php
interface iA
{
public function test1();
}
interface iB
{
public function test2();
}
class A implements iA, iB
{
// Pour ne générer aucune erreur, il va falloir écrire les méthodes de iA et de iB.
public function test1()
{
}
public function test2()
{
}
}
<?php
interface iInterface
{
const MA_CONSTANTE = 'Hello !';
}
echo iInterface::MA_CONSTANTE; // Affiche Hello !
class MaClasse implements iInterface
{
}
echo MaClasse::MA_CONSTANTE; // Affiche Hello !
extends. On ne peut pas réécrire ni une méthode ni une constante qui a déjà été listée dans l'interface parente :<?php
interface iA
{
public function test1();
}
interface iB extends iA
{
public function test1 ($param1, $param2); // Erreur fatale : impossible de réécrire cette méthode.
}
interface iC extends iA
{
public function test2();
}
class MaClasse implements iC
{
// Pour ne générer aucune erreur, on doit écrire les méthodes de iC et aussi de iA.
public function test1()
{
}
public function test2()
{
}
}
<?php
interface iA
{
public function test1();
}
interface iB
{
public function test2();
}
interface iC extends iA, iB
{
public function test3();
implementsextends, puis les interfaces à implémenter avec le mot-clé implements<?php
function additionner($a, $b)
{
if (!is_numeric($a) || !is_numeric($b))
{
// On lance une nouvelle exception grâce à throw et on instancie un objet de la classe Exception.
throw new Exception('Les deux paramètres doivent être des nombres');
}
return $a + $b;
}
echo additionner(12, 3), '<br />';
echo additionner('azerty', 54), '<br />';
echo additionner(4, 8);
15 Fatal error: Uncaught Exception 'Exception' with message 'Les deux paramètres doivent être des nombres' in Standard input code:7
<?php
function additionner($a, $b)
{
if (!is_numeric($a) || !is_numeric($b))
{
throw new Exception('Les deux paramètres doivent être des nombres');
}
return $a + $b;
}
try // Nous allons essayer d'effectuer les instructions situées dans ce bloc.
{
echo additionner(12, 3), '<br />';
echo additionner('azerty', 54), '<br />';
echo additionner(4, 8);
}
catch (Exception $e) // Nous allons attraper les exceptions "Exception" s'il y en a une qui est levée.
{
echo 'Une exception a été lancée. Message d\'erreur : ', $e->getMessage();
}
echo 'Fin du script'; // Ce message s'affiche, ça prouve bien que le script est exécuté jusqu'au bout.
15 Une exception a été lancée. Message d'erreur : Les deux paramètres doivent être des nombresFin du script
try n'a pas été exécutée.Exception est la classe de base pour toute exception qui doit être lancée.Exception<?php
class Exception
{
protected $message = 'exception inconnu'; // Message de l'exception.
protected $code = 0; // Code de l'exception défini par l'utilisateur.
protected $file; // Nom du fichier source de l'exception.
protected $line; // Ligne de la source de l'exception.
final function getMessage(); // Message de l'exception.
final function getCode(); // Code de l'exception.
final function getFile(); // Nom du fichier source.
final function getLine(); // Ligne du fichier source.
final function getTrace(); // Un tableau de backtrace().
final function getTraceAsString(); // Chaîne formattée de trace.
/* Remplacable */
function __construct ($message = NULL, $code = 0);
function __toString(); // Chaîne formatée pour l'affichage.
}
__construct et __toString.<?php
class MonException extends Exception
{
public function __construct($message, $code = 0)
{
parent::__construct($message, $code);
}
public function __toString()
{
return $this->message;
}
}
function additionner($a, $b)
{
if (!is_numeric($a) || !is_numeric($b))
{
throw new MonException('Les deux paramètres doivent être des nombres'); // On lance une exception "MonException".
}
return $a + $b;
}
try // Nous allons essayer d'effectuer les instructions situées dans ce bloc.
{
echo additionner(12, 3), '<br />';
echo additionner('azerty', 54), '<br />';
echo additionner(4, 8);
}
catch (MonException $e) // Nous allons attraper les exceptions "MonException"
{
echo $e; // On affiche le message d'erreur grâce à la méthode __toString que l'on a écrite.
}
echo '<br />Fin du script'; // Ce message s'affiche, ça prouve bien que le script est exécuté jusqu'au bout.
15 Les deux paramètres doivent être des nombres Fin du script
<?php
function additionner($a, $b)
{
if (!is_numeric($a) || !is_numeric($b))
{
// On lance une exception "MonException".
throw new MonException('Les deux paramètres doivent être des nombres');
}
if (func_num_args() > 2)
{
// Cette fois-ci, on lance une exception "Exception".
throw new Exception('Pas plus de deux arguments ne doivent être passés à la fonction');
}
return $a + $b;
}
try // Nous allons essayer d'effectuer les instructions situées dans ce bloc.
{
echo additionner(12, 3), '<br />';
echo additionner(15, 54, 45), '<br />';
}
catch (MonException $e) // Attrape les exceptions "MonException" s'il y en a une qui est levée.
{
echo '[MonException] : ', $e; // Affiche le message d'erreur grâce à la méthode __toString écrite.
}
catch (Exception $e) // Si l'exception n'est toujours pas attrapée, alors nous allons essayer d'attraper l'exception "Exception".
{
echo '[Exception] : ', $e->getMessage(); // La méthode __toString() nous affiche trop d'informations, nous voulons juste le message d'erreur.
}
echo '<br />Fin du script'; // Ce message s'affiche, cela prouve bien que le script est exécuté jusqu'au bout.
15 [Exception] : Pas plus de deux arguments ne doivent être passés à la fonction Fin du script
<?php
try
{
$db = new PDO('mysql:host=localhost;dbname=tests', 'root', ''); // Tentative de connexion.
echo 'Connexion réussie !'; // Si la connexion a réussi, alors cette instruction sera exécutée.
}
catch (PDOException $e) // On attrape les exceptions PDOException.
{
echo 'La connexion a échoué.<br />';
echo 'Informations : [', $e->getCode(), '] ', $e->getMessage(); // On affiche le n° de l'erreur ainsi que le message.
}
<?php
$db = new PDO('mysql:host=localhost;dbname=tests', 'root', '');
try
{
// Quelques opérations sur la base de données
}
finally
{
echo 'Action effectuée quoi qu\'il arrive';
}
try et catch.throw.Writer et Mailer: La première est chargée d'écrire du texte dans un fichier, tandis
que la seconde envoie un texte par mail.<?php
class Writer
{
public function write($text)
{
$text = '<p>Date : '.date('d/m/Y').'</p>'."\n".'<p>'.nl2br($text).'</p>';
file_put_contents('fichier.txt', $text);
}
}
<?php
class Mailer
{
public function send($text)
{
$text = '<p>Date : '.date('d/m/Y').'</p>'."\n".'<p>'.nl2br($text).'</p>';
mail('login@fai.tld', 'Test avec les traits', $text);
}
}
<?php
trait MonTrait
{
public function hello()
{
echo 'Hello world !';
}
}
class A
{
use MonTrait;
}
class B
{
use MonTrait;
}
$a = new A;
$a->hello(); // Affiche « Hello world ! ».
$b = new B;
$b->hello(); // Affiche aussi « Hello world ! ».
use<?php
trait HTMLFormater
{
public function format($text)
{
return '<p>Date : '.date('d/m/Y').'</p>'."\n".'<p>'.nl2br($text).'</p>';
}
}
class Writer
{
use HTMLFormater;
public function write($text)
{
file_put_contents('fichier.txt', $this->format($text));
}
}
class Mailer
{
use HTMLFormater;
public function send($text)
{
mail('login@fai.tld', 'Test avec les traits', $this->format($text));
}
}
$w = new Writer;
$w->write('Hello world!');
$m = new Mailer;
$m->send('Hello world!');
<?php
trait HTMLFormater
{
public function formatHTML($text)
{
return '<p>Date : '.date('d/m/Y').'</p>'."\n".'<p>'.nl2br($text).'</p>';
}
}
trait TextFormater
{
public function formatText($text)
{
return 'Date : '.date('d/m/Y')."\n".$text;
}
}
class Writer
{
use HTMLFormater, TextFormater;
public function write($text)
{
file_put_contents('fichier.txt', $this->formatHTML($text));
}
}
<?php
class Writer
{
use HTMLFormater, TextFormater
{
HTMLFormater::format insteadof TextFormater;
}
public function write($text)
{
file_put_contents('fichier.txt', $this->format($text));
}
}
<?php
trait MonTrait
{
public function speak()
{
echo 'Je suis un trait !';
}
}
class Mere
{
public function speak()
{
echo 'Je suis une classe mère !';
}
}
class Fille extends Mere
{
use MonTrait;
}
$fille = new Fille;
$fille->speak(); // Affiche « Je suis un trait ! »
Je suis un trait !
<?php
trait MonTrait
{
public function sayHello()
{
echo 'Hello !';
}
}
class MaClasse
{
use MonTrait;
public function sayHello()
{
echo 'Bonjour !';
}
}
$objet = new MaClasse;
$objet->sayHello(); // Affiche « Bonjour ! ».
<?php
trait MonTrait
{
protected $attr = 'Hello !';
public function showAttr()
{
echo $this->attr;
}
}
class MaClasse
{
use MonTrait;
}
$fille = new MaClasse;
$fille->showAttr();
<?php
trait MonTrait
{
protected $attr = 'Hello !';
}
class MaClasse
{
use MonTrait;
protected $attr = 'Hello !'; // Lèvera une erreur
private $attr = 'Hello !'; // Lèvera une erreur
}
<?php
trait A
{
public function saySomething()
{
echo 'Je suis le trait A !';
}
}
trait B
{
use A;
public function saySomething()
{
echo 'Je suis saySomething() le trait B !';
}
public function saySomethingElse()
{
echo 'Je suis le trait B !';
}
}
class MaClasse
{
use B;
}
$o = new MaClasse;
$o->saySomething(); // Affiche « Je suis le trait B ! »
$o->saySomethingElse(); // Affiche « Je suis le trait B ! »
Je suis saySomething() le trait B !Je suis le trait B !
<?php
trait A
{
public function saySomething()
{
echo 'Je suis le trait A !';
}
}
class MaClasse
{
use A
{
saySomething as protected;
}
}
$o = new MaClasse;
$o->saySomething(); // Lèvera une erreur fatale car on tente d'accéder à une méthode protégée.
<?php
trait A
{
public function saySomething()
{
echo 'Je suis le trait A !';
}
}
class MaClasse
{
use A
{
saySomething as sayWhoYouAre;
}
}
$o = new MaClasse;
$o->sayWhoYouAre(); // Affichera « Je suis le trait A ! »
$o->saySomething(); // Affichera « Je suis le trait A ! »
<?php
trait A
{
public function saySomething()
{
echo 'Je suis le trait A !';
}
}
class MaClasse
{
use A
{
saySomething as protected sayWhoYouAre;
}
}
$o = new MaClasse;
$o->saySomething(); // Affichera « Je suis le trait A ! ».
$o->sayWhoYouAre(); // Lèvera une erreur fatale, car l'alias créé est une méthode protégée.
<?php
trait A
{
abstract public function saySomething();
}
abstract class Mere
{
use A;
}
// Jusque-là, aucune erreur n'est levée.
class Fille extends Mere
{
// Par contre, une erreur fatale est ici levée, car la méthode saySomething() n'a pas été implémentée.
}
useinsteadof<?php
$magicien = new Magicien(['nom' => 'vyk12', 'type' => 'magicien']);
$classeMagicien = new ReflectionObject($magicien);
if ($classeMagicien->hasProperty('magie'))
{
echo 'La classe Magicien possède un attribut $magie';
}
else
{
echo 'La classe Magicien ne possède pas d\'attribut $magie';
}
if ($classeMagicien->hasMethod('lancerUnSort'))
{
echo 'La classe Magicien implémente une méthode lancerUnSort()';
}
else
{
echo 'La classe Magicien n\'implémente pas de méthode lancerUnSort()';
}
if ($classePersonnage->hasConstant('NOUVEAU'))
{
echo 'La classe Personnage possède une constante NOUVEAU';
}
else
{
echo 'La classe Personnage ne possède pas de constante NOUVEAU';
}
//récupère toutes les constantes
echo '<pre>', print_r($classePersonnage->getConstants(), true), '</pre>';
<?php
$classeMagicien = new ReflectionClass('Magicien');
if ($parent = $classeMagicien->getParentClass())
{
echo 'La classe Magicien a un parent : il s\'agit de la classe ', $parent->getName();
}
else
{
echo 'La classe Magicien n\'a pas de parent';
}
<?php
if ($classeMagicien->isSubclassOf('Personnage'))
{
echo 'La classe Magicien a pour parent la classe Personnage';
}
else
{
echo 'La classe Magicien n\'a la classe Personnage pour parent';
}
<?php
$classePersonnage = new ReflectionClass('Personnage');
// Est-elle abstraite ?
if ($classePersonnage->isAbstract())
{ echo 'La classe Personnage est abstraite'; }
else
{ echo 'La classe Personnage n\'est pas abstraite'; }
// Est-elle finale ?
if ($classePersonnage->isFinal())
{ echo 'La classe Personnage est finale'; }
else
{ echo 'La classe Personnage n\'est pas finale'; }
<?php
$classeIMagicien = new ReflectionClass('iMagicien');
if ($classeIMagicien->isInterface())
{
echo 'La classe iMagicien est une interface';
}
else
{
echo 'La classe iMagicien n\'est pas une interface';
}
<?php
if ($classeMagicien->implementsInterface('iMagicien'))
{
echo 'La classe Magicien implémente l\'interface iMagicien';
}
else
{
echo 'La classe Magicien n\'implémente pas l\'interface iMagicien';
}
Cette section va vous montrer une possibilité intéressante de la POO en PHP : la résolution statique à la volée.
C'est une notion un peu complexe à comprendre au premier abord, alors n'hésitez pas à relire plusieurs fois.
Effectuons d'abord un petit flash-back sur self::.
Vous vous souvenez à quoi il sert ? À appeler un attribut, une méthode statique ou une constante de la classe dans laquelle est contenu self::.
<?php
class Mere
{
public static function lancerLeTest()
{
self::quiEstCe();
}
public static function quiEstCe()
{
echo 'Je suis la classe <strong>Mere</strong> !';
}
}
class Enfant extends Mere
{
public static function quiEstCe()
{
echo 'Je suis la classe <strong>Enfant</strong> !';
}
}
Enfant::lancerLeTest();
Je suis la classe <strong>Mere</strong> !
Quel est le résultat de ce code ?
Je suis la classe *Mere* !Je suis la classe *Enfant* !Responses: 0
<?php
class Mere
{
public static function lancerLeTest()
{
self::quiEstCe();
}
public static function quiEstCe()
{
echo 'Je suis la classe <strong>Mere</strong> !';
}
}
class Enfant extends Mere
{
public static function quiEstCe()
{
echo 'Je suis la classe <strong>Enfant</strong> !';
}
}
Enfant::lancerLeTest();
Je suis la classe <strong>Mere</strong> !
lancerLeTest de la classe EnfantquiEstCe de la classeMere.self:: fait appel à la méthode statique de la classe dans laquelle est contenu self::, donc de la classe parente.static::.static:: a exactement le même effet que self::, à l'exception près que static:: appelle l'élément de la classe qui est appelée pendant l'exécution.lancerLeTest depuis la classe Enfant et que dans cette méthode j'utilise static:: au lieu de self::, c'est la méthode quiEstCe de la classe Enfant qui sera appelée et non de la classe Mere !<?php
class Mere
{
public static function lancerLeTest()
{
static::quiEstCe();
}
public static function quiEstCe()
{
echo 'Je suis la classe <strong>Mere</strong> !';
}
}
class Enfant extends Mere
{
public static function quiEstCe()
{
echo 'Je suis la classe <strong>Enfant</strong> !';
}
}
Enfant::lancerLeTest();
Je suis la classe <strong>Enfant</strong> !
static::.<?php
class Mere
{
public function lancerLeTest()
{
static::quiEstCe();
}
public function quiEstCe()
{
echo 'Je suis la classe <strong>Mere</strong> !';
}
}
class Enfant extends Mere
{
public function quiEstCe()
{
echo 'Je suis la classe <strong>Enfant</strong> !';
}
}
$enfant = new Enfant;
$enfant->lancerLeTest();
Je suis la classe <strong>Enfant</strong> !
<?php
class A
{
public static function appelerQuiEstCe(){
static::quiEstCe();
}
public static function quiEstCe(){
echo 'A';
}
}
class B extends A
{
public static function test(){
// parent::quiEstCe();
parent::appelerQuiEstCe();
}
public static function quiEstCe(){
echo 'B';
}
}
class C extends B
{
public static function quiEstCe(){
echo 'C';
}
}
C::test();
?>
C
Quel est le résultat de ce code ?
Responses: 0
<?php
class A
{
public static function appelerQuiEstCe(){
static::quiEstCe();
}
public static function quiEstCe(){
echo 'A';
}
}
class B extends A
{
public static function test(){
// parent::quiEstCe();
parent::appelerQuiEstCe();
}
public static function quiEstCe(){
echo 'B';
}
}
class C extends B
{
public static function quiEstCe(){
echo 'C';
}
}
C::test();
?>
C
test de la classe BappelerQuiEstCe de la classe A (avec parent:: )quiEstCe de la classe qui a appelé la méthode appelerQuiEstCequiEstCe de la classe C est donc appelée car c'est depuis la classe C qu'on a appelé la méthode test.<?php
class TestParent
{
public function __construct()
{
static::qui();
}
public static function qui()
{
echo 'TestParent';
}
}
class TestChild extends TestParent
{
public function __construct()
{
static::qui();
}
public function test()
{
$o = new TestParent();
}
public static function qui()
{
echo 'TestChild';
}
}
$o = new TestChild;
$o->test();
?>
TestChildTestParent
Quel est le résultat de ce code ?
TestParentTestParentTestChildTestChildTestChildTestParentTestParentTestChildResponses: 0
<?php
class TestParent
{
public function __construct()
{
static::qui();
}
public static function qui()
{
echo 'TestParent';
}
}
class TestChild extends TestParent
{
public function __construct()
{
static::qui();
}
public function test()
{
$o = new TestParent();
}
public static function qui()
{
echo 'TestChild';
}
}
$o = new TestChild;
$o->test();
?>
TestChildTestParent
qui de la classe TestChild puisque c'est la méthode __construct de la classe TestChild qui a été appelée ;qui de la classe TestParent puisque c'est la méthode __construct de cette classe qui a été appelée.