mirror of
https://github.com/macintoshplus/doc-fr.git
synced 2026-03-25 17:32:07 +01:00
528 lines
17 KiB
XML
528 lines
17 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- $Revision$ -->
|
|
<!-- EN-Revision: 3926279f825d418fdd2e7079968507d8b0c62b7d Maintainer: yannick Status: ready -->
|
|
<!-- Reviewed: no -->
|
|
<sect1 xml:id="language.oop5.magic" xmlns="http://docbook.org/ns/docbook">
|
|
<title>Méthodes magiques</title>
|
|
<para>
|
|
Les méthodes magiques sont des méthodes spéciales qui écrasent l'action
|
|
par défaut de PHP quand certaines actions sont réalisées sur un objet.
|
|
</para>
|
|
<caution>
|
|
<simpara>
|
|
Toutes les méthodes commençant par <literal>__</literal> sont réservé par PHP.
|
|
Ainsi, il n'est pas recommandé d'utiliser un tel nom de méthode sauf lors
|
|
de l'écrasage du comportement de PHP.
|
|
</simpara>
|
|
</caution>
|
|
<para>
|
|
Les méthodes suivantes sont considérées magiques :
|
|
<!-- Should be an itemized list ? -->
|
|
<link linkend="object.construct">__construct()</link>,
|
|
<link linkend="object.destruct">__destruct()</link>,
|
|
<link linkend="object.call">__call()</link>,
|
|
<link linkend="object.callstatic">__callStatic()</link>,
|
|
<link linkend="object.get">__get()</link>,
|
|
<link linkend="object.set">__set()</link>,
|
|
<link linkend="object.isset">__isset()</link>,
|
|
<link linkend="object.unset">__unset()</link>,
|
|
<link linkend="object.sleep">__sleep()</link>,
|
|
<link linkend="object.wakeup">__wakeup()</link>,
|
|
<link linkend="object.serialize">__serialize()</link>,
|
|
<link linkend="object.unserialize">__unserialize()</link>,
|
|
<link linkend="object.tostring">__toString()</link>,
|
|
<link linkend="object.invoke">__invoke()</link>,
|
|
<link linkend="object.set-state">__set_state()</link>
|
|
<link linkend="object.clone">__clone()</link>, et
|
|
<link linkend="object.debuginfo">__debugInfo()</link>.
|
|
</para>
|
|
|
|
<warning>
|
|
<simpara>
|
|
Toutes les méthodes magiques, à l'exception de
|
|
<link linkend="object.construct">__construct()</link>,
|
|
<link linkend="object.destruct">__destruct()</link>, et
|
|
<link linkend="object.clone">__clone()</link>,
|
|
<emphasis>doivent</emphasis> être déclaré en tant que <literal>public</literal>,
|
|
sinon une <constant>E_WARNING</constant> est émise.
|
|
Antérieur à PHP 8.0.0, aucun diagnostic n'était émis pour les méthodes magiques
|
|
<link linkend="object.sleep">__sleep()</link>,
|
|
<link linkend="object.wakeup">__wakeup()</link>,
|
|
<link linkend="object.serialize">__serialize()</link>,
|
|
<link linkend="object.unserialize">__unserialize()</link>, et
|
|
<link linkend="object.set-state">__set_state()</link>.
|
|
</simpara>
|
|
</warning>
|
|
<warning>
|
|
<para>
|
|
Si des déclarations de types sont utilisé dans la définition d'une méthode
|
|
magique, elles doivent être identique à la signature décrit dans ce document.
|
|
Sinon, une erreur fatale est émise.
|
|
Antérieur à PHP 8.0.0, aucun diagnostic n'était émis.
|
|
Cependant, <link linkend="object.construct">__construct()</link> et
|
|
<link linkend="object.destruct">__destruct()</link> ne doivent pas déclarer
|
|
un type de retour ; sinon une erreur fatale est émise.
|
|
</para>
|
|
</warning>
|
|
|
|
<sect2 xml:id="language.oop5.magic.sleep">
|
|
<title>
|
|
<link linkend="object.sleep">__sleep()</link> et
|
|
<link linkend="object.wakeup">__wakeup()</link>
|
|
</title>
|
|
|
|
<methodsynopsis xml:id="object.sleep">
|
|
<modifier>public</modifier> <type>array</type><methodname>__sleep</methodname>
|
|
<void/>
|
|
</methodsynopsis>
|
|
<methodsynopsis xml:id="object.wakeup">
|
|
<modifier>public</modifier> <type>void</type><methodname>__wakeup</methodname>
|
|
<void/>
|
|
</methodsynopsis>
|
|
|
|
<para>
|
|
<function>serialize</function> vérifie si la classe a une méthode avec le
|
|
nom magique <link linkend="object.sleep">__sleep()</link>.
|
|
Si c'est le cas, cette méthode sera exécutée avant toute linéarisation. Elle peut
|
|
nettoyer l'objet, et elle est supposée retourner un tableau avec les noms de toutes
|
|
les variables de l'objet qui doivent être linéarisées.
|
|
Si la méthode ne retourne rien, alors &null; sera linéarisé, et une alerte de type
|
|
<constant>E_NOTICE</constant> sera émise.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
Il n'est pas possible pour <link linkend="object.sleep">__sleep()</link> de retourner
|
|
des noms de propriétés privées des classes parentes. Le faire
|
|
résultera en une erreur de niveau <constant>E_NOTICE</constant>.
|
|
Utilisez <link linkend="object.serialize">__serialize()</link> à la place.
|
|
</para>
|
|
</note>
|
|
<para>
|
|
Le but avoué de <link linkend="object.sleep">__sleep()</link> est de valider des données en attente
|
|
ou d'effectuer des opérations de nettoyage.
|
|
De plus, cette fonction est utile si un objet très large n'a pas besoin
|
|
d'être sauvegardés dans sa totalité.
|
|
</para>
|
|
<para>
|
|
Réciproquement, la fonction <function>unserialize</function> vérifie
|
|
la présence d'une méthode dont le nom est le nom magique
|
|
<link linkend="object.wakeup">__wakeup()</link>. Si elle est présente, cette fonction
|
|
peut reconstruire toute ressource que l'objet pourrait posséder.
|
|
</para>
|
|
<para>
|
|
Le but avoué de <link linkend="object.wakeup">__wakeup()</link> est de rétablir
|
|
toute connexion de base de données qui aurait été perdue
|
|
durant la linéarisation et d'effectuer des tâches de réinitialisation.
|
|
</para>
|
|
<example>
|
|
<title>Utilisation de sleep() et wakeup()</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Connection
|
|
{
|
|
protected $link;
|
|
private $dsn, $username, $password;
|
|
|
|
public function __construct($dsn, $username, $password)
|
|
{
|
|
$this->dsn = $dsn;
|
|
$this->username = $username;
|
|
$this->password = $password;
|
|
$this->connect();
|
|
}
|
|
|
|
private function connect()
|
|
{
|
|
$this->link = new PDO($this->dsn, $this->username, $this->password);
|
|
}
|
|
|
|
public function __sleep()
|
|
{
|
|
return array('dsn', 'username', 'password');
|
|
}
|
|
|
|
public function __wakeup()
|
|
{
|
|
$this->connect();
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.magic.serialize">
|
|
<title>
|
|
<link linkend="object.serialize">__serialize()</link> et
|
|
<link linkend="object.unserialize">__unserialize()</link>
|
|
</title>
|
|
|
|
<methodsynopsis xml:id="object.serialize">
|
|
<modifier>public</modifier> <type>array</type><methodname>__serialize</methodname>
|
|
<void/>
|
|
</methodsynopsis>
|
|
<methodsynopsis xml:id="object.unserialize">
|
|
<modifier>public</modifier> <type>void</type><methodname>__unserialize</methodname>
|
|
<methodparam><type>array</type><parameter>data</parameter></methodparam>
|
|
</methodsynopsis>
|
|
|
|
<para>
|
|
<function>serialize</function> vérifie si la classe a une méthode avec le
|
|
nom magique <link linkend="object.serialize">__serialize()</link>.
|
|
Si c'est le cas, cette méthode sera exécutée avant toute linéarisation.
|
|
Elle doit construire et retourner un &array; associatif de paire clé/valeur
|
|
qui représente la forme linéarisée de l'objet. Si aucun tableau n'est
|
|
retournée une <classname>TypeError</classname> sera lancée.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
Si <link linkend="object.serialize">__serialize()</link> et
|
|
<link linkend="object.sleep">__sleep()</link> sont tout les deux définie
|
|
dans le même objet, alors seulement <link linkend="object.serialize">__serialize()</link>
|
|
sera appelé.
|
|
<link linkend="object.sleep">__sleep()</link> sera ignoré. Si l'objet
|
|
implémente l'interface <link linkend="class.serializable">Serializable</link>,
|
|
la méthode <literal>serialize()</literal> de l'interface sera ignorée et
|
|
<link linkend="object.serialize">__serialize()</link> sera utilisé à la place.
|
|
</para>
|
|
</note>
|
|
<para>
|
|
L'utilisation prévue de <link linkend="object.serialize">__serialize()</link>
|
|
est de définir une représentation arbitraire de l'objet pour le linéariser
|
|
facilement. Les éléments du tableau peuvent correspondre aux propriétés de
|
|
l'objet mais cei n'est pas requis.
|
|
</para>
|
|
<para>
|
|
inversement, <function>unserialize</function> vérifie la présence d'une
|
|
fonction avec le nom magique
|
|
<link linkend="object.unserialize">__unserialize()</link>.
|
|
Si présent, cette fonction sera passé le tableau restauré qui a été retournée
|
|
depuis <link linkend="object.serialize">__serialize()</link>. Il peut alors
|
|
restaurer les propriétés de l'objet depuis ce tableau comme approprié.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
Si <link linkend="object.unserialize">__unserialize()</link> et
|
|
<link linkend="object.wakeup">__wakeup()</link> sont tout les deux définie
|
|
dans le même objet, alors seulement <link linkend="object.unserialize">__unserialize()</link>
|
|
sera appelée.
|
|
<link linkend="object.wakeup">__wakeup()</link> sera ignorée.
|
|
</para>
|
|
</note>
|
|
<note>
|
|
<para>
|
|
Cette fonctionnalité est disponible à partir de PHP 7.4.0.
|
|
</para>
|
|
</note>
|
|
<example>
|
|
<title>Serialize et unserialize</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Connection
|
|
{
|
|
protected $link;
|
|
private $dsn, $username, $password;
|
|
|
|
public function __construct($dsn, $username, $password)
|
|
{
|
|
$this->dsn = $dsn;
|
|
$this->username = $username;
|
|
$this->password = $password;
|
|
$this->connect();
|
|
}
|
|
|
|
private function connect()
|
|
{
|
|
$this->link = new PDO($this->dsn, $this->username, $this->password);
|
|
}
|
|
|
|
public function __serialize(): array
|
|
{
|
|
return [
|
|
'dsn' => $this->dsn,
|
|
'user' => $this->username,
|
|
'pass' => $this->password,
|
|
];
|
|
}
|
|
|
|
public function __unserialize(array $data): void
|
|
{
|
|
$this->dsn = $data['dsn'];
|
|
$this->username = $data['user'];
|
|
$this->password = $data['pass'];
|
|
|
|
$this->connect();
|
|
}
|
|
}?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.magic.tostring">
|
|
<title><link linkend="object.tostring">__toString()</link></title>
|
|
<methodsynopsis xml:id="object.tostring">
|
|
<modifier>public</modifier> <type>string</type><methodname>__toString</methodname>
|
|
<void/>
|
|
</methodsynopsis>
|
|
|
|
<para>
|
|
La méthode <link linkend="object.tostring">__toString()</link> détermine comment l'objet
|
|
doit réagir lorsqu'il est traité comme une chaîne de caractères.
|
|
Par exemple, ce que <literal>echo $obj;</literal> affichera.
|
|
</para>
|
|
<warning>
|
|
<para>
|
|
À partir de PHP 8.0.0, la valeur de retour suit les sémantiques standard
|
|
de PHP, signifiant que la valeur sera convertie en une <type>string</type>
|
|
si possible et si le
|
|
<link linkend="language.types.declarations.strict">typage stricte</link>
|
|
est désactivé.
|
|
</para>
|
|
<para>
|
|
À partir de PHP 8.0.0, toute classe qui contient une méthode
|
|
<link linkend="object.tostring">__toString()</link> implémente aussi
|
|
implicitement l'interface <interfacename>Stringable</interfacename>,
|
|
et passera donc les vérifications de types pour cette interface.
|
|
Implémenter quand même explicitement l'interface est recommandé.
|
|
</para>
|
|
<para>
|
|
En PHP 7.4, la valeur de retour <emphasis>doit</emphasis> être une
|
|
<type>string</type>, sinon une <classname>Error</classname> est lancé.
|
|
</para>
|
|
<para>
|
|
Antérieur à PHP 7.4.0, la valeur de retour <emphasis>doit</emphasis>
|
|
être une <type>string</type>, sinon une <constant>E_RECOVERABLE_ERROR</constant>
|
|
fatale est émise.
|
|
</para>
|
|
</warning>
|
|
<warning>
|
|
<simpara>
|
|
Il était impossible de lancer une exception depuis la méthode
|
|
<link linkend="object.tostring">__toString()</link> antérieur à PHP 7.4.0.
|
|
Cela entraînera une erreur fatale.
|
|
</simpara>
|
|
</warning>
|
|
<example>
|
|
<title>Exemple simple</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// Déclaration d'une classe simple
|
|
class ClasseTest
|
|
{
|
|
public $foo;
|
|
|
|
public function __construct($foo)
|
|
{
|
|
$this->foo = $foo;
|
|
}
|
|
|
|
public function __toString()
|
|
{
|
|
return $this->foo;
|
|
}
|
|
}
|
|
|
|
$class = new ClasseTest('Bonjour');
|
|
echo $class;
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Bonjour
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.magic.invoke">
|
|
<title><link linkend="object.invoke">__invoke()</link></title>
|
|
<methodsynopsis xml:id="object.invoke">
|
|
<type>mixed</type><methodname>__invoke</methodname>
|
|
<methodparam rep="repeat"><parameter>values</parameter></methodparam>
|
|
</methodsynopsis>
|
|
|
|
<para>
|
|
La méthode <link linkend="object.invoke">__invoke()</link> est appelée lorsqu'un script tente
|
|
d'appeler un objet comme une fonction.
|
|
</para>
|
|
<example>
|
|
<title>Exemple avec <link linkend="object.invoke">__invoke()</link></title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class CallableClass
|
|
{
|
|
public function __invoke($x)
|
|
{
|
|
var_dump($x);
|
|
}
|
|
}
|
|
$obj = new CallableClass;
|
|
$obj(5);
|
|
var_dump(is_callable($obj));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
int(5)
|
|
bool(true)
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.magic.set-state">
|
|
<title><link linkend="object.set-state">__set_state()</link></title>
|
|
<methodsynopsis xml:id="object.set-state">
|
|
<modifier>static</modifier> <type>object</type><methodname>__set_state</methodname>
|
|
<methodparam><type>array</type><parameter>properties</parameter></methodparam>
|
|
</methodsynopsis>
|
|
|
|
<para>
|
|
Cette méthode <link linkend="language.oop5.static">statique</link> est appelée
|
|
pour les classes exportées par la fonction <function>var_export</function>.
|
|
</para>
|
|
<para>
|
|
Le seul paramètre de cette méthode est un tableau contenant les propriétés
|
|
exportées sous la forme <literal>['property' => value, ...]</literal>.
|
|
</para>
|
|
<example>
|
|
<title>Utilisation de <link linkend="object.set-state">__set_state()</link></title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
|
|
class A
|
|
{
|
|
public $var1;
|
|
public $var2;
|
|
|
|
public static function __set_state($an_array)
|
|
{
|
|
$obj = new A;
|
|
$obj->var1 = $an_array['var1'];
|
|
$obj->var2 = $an_array['var2'];
|
|
return $obj;
|
|
}
|
|
}
|
|
|
|
$a = new A;
|
|
$a->var1 = 5;
|
|
$a->var2 = 'foo';
|
|
|
|
$b = var_export($a, true);
|
|
var_dump($b);
|
|
eval('$c = ' . $b . ';');
|
|
var_dump($c);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
string(60) "A::__set_state(array(
|
|
'var1' => 5,
|
|
'var2' => 'foo',
|
|
))"
|
|
object(A)#2 (2) {
|
|
["var1"]=>
|
|
int(5)
|
|
["var2"]=>
|
|
string(3) "foo"
|
|
}
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<note>
|
|
<simpara>
|
|
Lors de l'exportation d'un objet, <function>var_export</function> ne
|
|
vérifie pas si <link linkend="object.set-state">__set_state()</link> est
|
|
implémenté par la classe de l'objet, ainsi la réimportation d'objets
|
|
résultera en une exception <classname>Error</classname>,
|
|
si __set_state() n'est pas implémenté.
|
|
En particulier, cela affecte certaines classes internes.
|
|
</simpara>
|
|
<simpara>
|
|
Il est de la responsabilité du programmeur de vérifier que seuls les objets dont la classe implémente __set_state() seront ré-importés.
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="language.oop5.magic.debuginfo">
|
|
<title><link linkend="object.debuginfo">__debugInfo()</link></title>
|
|
<methodsynopsis xml:id="object.debuginfo">
|
|
<type>array</type><methodname>__debugInfo</methodname>
|
|
<void/>
|
|
</methodsynopsis>
|
|
<para>
|
|
Cette méthode est appelée par <function>var_dump</function> lors
|
|
du traitement d'un objet pour récupérer les propriétés qui
|
|
doivent être affichées. Si la méthode n'est pas définie dans un objet,
|
|
alors toutes les propriétés publiques, protégées et privées seront
|
|
affichées.
|
|
</para>
|
|
<example>
|
|
<title>Utilisation de <link linkend="object.debuginfo">__debugInfo()</link></title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class C {
|
|
private $prop;
|
|
|
|
public function __construct($val) {
|
|
$this->prop = $val;
|
|
}
|
|
|
|
public function __debugInfo() {
|
|
return [
|
|
'propSquared' => $this->prop ** 2,
|
|
];
|
|
}
|
|
}
|
|
|
|
var_dump(new C(42));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
object(C)#1 (1) {
|
|
["propSquared"]=>
|
|
int(1764)
|
|
}
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</sect2>
|
|
|
|
</sect1>
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|