1
0
mirror of https://github.com/php/doc-fr.git synced 2026-03-23 22:52:18 +01:00
Files
archived-doc-fr/language/functions.xml

1786 lines
49 KiB
XML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: dd87866772c31671146ff778140dc0955c55005c Maintainer: yannick Status: ready -->
<!-- Reviewed: no -->
<chapter xml:id="language.functions" xmlns="http://docbook.org/ns/docbook">
<title>Les fonctions</title>
<sect1 xml:id="functions.user-defined">
<title>Les fonctions définies par l'utilisateur</title>
<para>
Une fonction est définie en utilisant le mot-clé <literal>function</literal>,
un nom, une liste de paramètres (qui peuvent être vides) séparés par des virgules
(<literal>,</literal>) entre parenthèses, suivis du corps de
la fonction entre accolades, comme suit :
</para>
<example>
<title>Déclaration d'une nouvelle fonction nommée <literal>foo</literal></title>
<programlisting role="php">
<![CDATA[
<?php
function foo($arg_1, $arg_2, /* ..., */ $arg_n)
{
echo "Exemple de fonction.\n";
return $retval;
}
?>
]]>
</programlisting>
</example>
<note>
<para>
À partir de PHP 8.0.0, la liste de paramètres peut avoir une virgule finale:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
function foo($arg_1, $arg_2,) { }
?>
]]>
</programlisting>
</informalexample>
</para>
</note>
<simpara>
Tout code PHP valide peut apparaître à l'intérieur du corps d'une fonction, y compris d'autres
fonctions et des définitions de
<link linkend="language.oop5.basic.class">classe</link>.
</simpara>
<para>
Les noms de fonctions suivent les mêmes règles que les autres labels en PHP.
Un nom de fonction valide commence par une lettre ou un souligné, suivi
par un nombre quelconque de lettres, de nombres ou de soulignés.
Ces règles peuvent être représentées par l'expression rationnelle suivante :
<code>^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>
</para>
&tip.userlandnaming;
<simpara>
Les fonctions n'ont pas besoin d'être définies avant d'être utilisées,
<emphasis>SAUF</emphasis> lorsqu'une fonction est définie
conditionnellement, comme montré dans les deux exemples suivants.
</simpara>
<para>
Lorsqu'une fonction est définie de manière conditionnelle, comme dans
les exemples ci-dessous, leur définition doit <emphasis>précéder</emphasis>
leur utilisation.
</para>
<para>
<example>
<title>Fonctions conditionnelles</title>
<programlisting role="php">
<![CDATA[
<?php
$makefoo = true;
/* Impossible d'appeler foo() ici,
car cette fonction n'existe pas.
Mais nous pouvons utiliser bar() */
bar();
if ($makefoo) {
function foo()
{
echo "Je n'existe pas tant que le programme n'est pas passé ici.\n";
}
}
/* Maintenant, nous pouvons appeler foo()
car $makefoo est évalué à vrai */
if ($makefoo) foo();
function bar()
{
echo "J'existe dès le début du programme.\n";
}
?>
]]>
</programlisting>
</example>
</para>
<para>
<example>
<title>Fonctions dans une autre fonction</title>
<programlisting role="php">
<![CDATA[
<?php
function foo()
{
function bar()
{
echo "Je n'existe pas tant que foo() n'est pas appelé.\n";
}
}
/* Impossible d'appeler bar() ici
car il n'existe pas. */
foo();
/* Maintenant, nous pouvons appeler bar(),
car l'utilisation de foo() l'a rendue
accessible. */
bar();
?>
]]>
</programlisting>
</example>
</para>
<para>
Toutes les fonctions et classes en PHP ont une portée globale - elles
peuvent être appelées à l'extérieur d'une fonction si elles ont été définies
à l'intérieur et vice-versa.
</para>
<simpara>
PHP ne supporte pas la surcharge, la destruction et la redéfinition de
fonctions déjà déclarées.
</simpara>
<note>
<simpara>
Les noms de fonctions sont insensibles à la casse pour les caractères ASCII
<literal>A</literal> à <literal>Z</literal>,
et il est généralement admis que les fonctions doivent
être appelées avec le nom utilisé dans leur déclaration,
y compris la casse.
</simpara>
</note>
<simpara>
Les <link linkend="functions.variable-arg-list">
listes variables d'arguments de fonction</link> et les
<link linkend="functions.arguments.default">valeurs par défaut
d'arguments</link> sont supportés : voir
les fonctions de références que sont
<function>func_num_args</function>,
<function>func_get_arg</function>, et
<function>func_get_args</function> pour plus d'informations.
</simpara>
<para>
Il est possible d'appeler des fonctions récursives en PHP.
<example>
<title>Fonctions récursives</title>
<programlisting role="php">
<![CDATA[
<?php
function recursion($a)
{
if ($a < 20) {
echo "$a\n";
recursion($a + 1);
}
}
?>
]]>
</programlisting>
</example>
<note>
<simpara>
Les appels de méthodes/fonctions récursives avec 100-200 degrés de
récursivité peuvent remplir la pile et ainsi, terminer le script courant.
À noter qu'une récursion infinie est considérée comme une erreur de
programmation.
</simpara>
</note>
</para>
</sect1>
<sect1 xml:id="functions.arguments">
<title>Paramètres et arguments de fonction</title>
<simpara>
Les paramètres de la fonction sont déclarés dans la signature de la fonction.
Des informations peuvent être passées à
une fonction en utilisant une liste d'arguments, dont chaque
expression est séparée par une virgule. Les arguments seront
évalués de gauche à droite, et le résultat est assigné aux paramètres de
la fonction, avant que la fonction ne soit effectivement appelée
(évaluation <emphasis>immédiate</emphasis>).
</simpara>
<!-- Note: this paragraph feels like it should be moved to the syntax part? -->
<para>
PHP supporte le passage d'arguments par valeur (comportement par défaut), <link
linkend="functions.arguments.by-reference">le passage par référence</link>, et <link
linkend="functions.arguments.default">des valeurs d'arguments par défaut</link>.
Une <link linkend="functions.variable-arg-list">liste variable d'arguments</link>,
ainsi que les <link linkend="functions.named-arguments">Arguments Nommés</link>
sont également supportés.
</para>
<note>
<para>
À partir de PHP 7.3.0, il est possible d'avoir une virgule finale dans la liste d'arguments
pour les appels de fonction :
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$v = foo(
$arg_1,
$arg_2,
);
?>
]]>
</programlisting>
</informalexample>
</para>
</note>
<para>
À partir de PHP 8.0.0, la liste des arguments de fonction peut inclure une
virgule finale, qui sera ignorée. Ceci est particulièrement pratique dans
les cas où la liste d'arguments est longue ou contient des noms de variables
longs, le rendant pratique pour lister les arguments verticalement.
</para>
<example>
<title>Liste des paramètres de la fonction avec une virgule finale</title>
<programlisting role="php">
<![CDATA[
<?php
function takes_many_args(
$first_arg,
$second_arg,
$a_very_long_argument_name,
$arg_with_default = 5,
$again = 'a default string', // Cette virgule finale n'était pas permise avant 8.0.0.
)
{
// ...
}
?>
]]>
</programlisting>
</example>
<sect2 xml:id="functions.arguments.by-reference">
<title>Passage d'arguments par référence</title>
<simpara>
Par défaut, les arguments sont passés
à la fonction par valeur (aussi, changer la valeur d'un argument dans la fonction ne
change pas sa valeur à l'extérieur de la fonction). Pour que les fonctions
puissent changer la valeur des arguments, il faut passer ces arguments par référence.
</simpara>
<para>
Pour qu'un argument soit toujours passé
par référence, il suffit d'ajouter un '<literal>&amp;</literal>'
devant le paramètre dans la déclaration de la fonction :
</para>
<para>
<example>
<title>Passage des arguments de fonction par référence</title>
<programlisting role="php">
<![CDATA[
<?php
function add_some_extra(&$string)
{
$string .= ', et un peu plus.';
}
$str = 'Ceci est une chaîne';
add_some_extra($str);
echo $str; // Affiche : 'Ceci est une chaîne, et un peu plus.'
?>
]]>
</programlisting>
</example>
</para>
<para>
Il est incorrect de passer une expression constante comme argument à un paramètre
qui attend d'être passé par référence.
</para>
</sect2>
<sect2 xml:id="functions.arguments.default">
<title>Valeurs par défaut des paramètres</title>
<para>
Une fonction peut définir des valeurs par défaut pour les paramètres en utilisant une syntaxe similaire
à celle de l'affectation d'une variable. La valeur par défaut est utilisée uniquement lorsque l'argument du paramètre n'est
pas passé. Il est à noter que passer &null; ne <emphasis>définit pas</emphasis>
la valeur par défaut.
</para>
<para>
<example>
<title>Valeur par défaut des arguments de fonctions</title>
<programlisting role="php">
<![CDATA[
<?php
function servir_cafe ($type = "cappuccino")
{
return "Servir un $type.\n";
}
echo servir_cafe();
echo servir_cafe(null);
echo servir_cafe("espresso");
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Servir un cappuccino.
Servir un .
Servir un espresso.
]]>
</screen>
</example>
</para>
<para>
Les valeurs par défaut des paramètres peuvent être des valeurs scalaires,
des &array;s, le type spécial &null;, et à partir de PHP 8.1.0,
des objets utilisant la syntaxe <link linkend="language.oop5.basic.new">new ClassName()</link>.
</para>
<para>
<example>
<title>Utilisation de type non-scalaire comme valeur par défaut</title>
<programlisting role="php">
<![CDATA[
<?php
function servir_cafe($types = array("cappuccino"), $coffeeMaker = NULL)
{
$device = is_null($coffeeMaker) ? "les mains" : $coffeeMaker;
return "Préparation d'une tasse de ".join(", ", $types)." avec $device.\n";
}
echo servir_cafe();
echo servir_cafe(array("cappuccino", "lavazza"), "une cafetière");
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Préparation d'une tasse de cappuccino avec les mains.
Préparation d'une tasse de cappuccino, lavazza avec une cafetière.
]]>
</screen>
</example>
</para>
<para>
<example>
<title>Utilisation d'objets comme valeurs par défaut (à partir de PHP 8.1.0)</title>
<programlisting role="php">
<![CDATA[
<?php
class DefaultCoffeeMaker {
public function brew() {
return 'Faire du café.\n';
}
}
class FancyCoffeeMaker {
public function brew() {
return 'Créer un beau café rien que pour vous.\n';
}
}
function makecoffee($coffeeMaker = new DefaultCoffeeMaker)
{
return $coffeeMaker->brew();
}
echo makecoffee();
echo makecoffee(new FancyCoffeeMaker);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Faire du café.
Créer un beau café rien que pour vous.
]]>
</screen>
</example>
</para>
<simpara>
La valeur par défaut d'un argument doit
obligatoirement être une constante, et ne peut être
ni une variable, ni un membre de classe, ni un appel de fonction.
</simpara>
<para>
Il est à noter que tous les paramètres optionnels doivent être spécifiés après les
paramètres obligatoires, sinon ils ne peuvent pas être omis dans les appels.
Considérons le code suivant :
</para>
<para>
<example>
<title>Utilisation incorrecte des paramètres de fonction par défaut</title>
<programlisting role="php">
<![CDATA[
<?php
function faireunyaourt ($container = "bol", $flavour)
{
return "Préparer un $container de yaourt à la $flavour.\n";
}
echo faireunyaourt("framboise"); // "framboise" est $container, pas $flavour
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Fatal error: Uncaught ArgumentCountError: Too few arguments
to function faireunyaourt(), 1 passed in example.php on line 42
]]>
</screen>
</example>
</para>
<para>
Maintenant comparons l'exemple précédent avec l'exemple suivant :
</para>
<para>
<example>
<title>Utilisation correcte des paramètres de fonction par défaut</title>
<programlisting role="php">
<![CDATA[
<?php
function faireunyaourt ($flavour, $container = "bol")
{
return "Préparer un $container de yaourt à la $flavour.\n";
}
echo faireunyaourt ("framboise"); // "framboise" est $flavour
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Préparer un bol de yaourt à la framboise.
]]>
</screen>
</example>
</para>
<para>
À partir de PHP 8.0.0, les <link linkend="functions.named-arguments">arguments nommés</link>
peuvent être utilisés pour passer outre plusieurs paramètres optionnels.
</para>
<para>
<example>
<title>Utilisation correcte des paramètres de fonction par défaut</title>
<programlisting role="php">
<![CDATA[
<?php
function faireunyaourt($container = "bol", $flavour = "framboise", $style = "Grec")
{
return "Préparer un $container de yaourt $style à la $flavour.\n";
}
echo faireunyaourt(style: "naturel");
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Préparer un bol de yaourt naturel à la framboise.
]]>
</screen>
</example>
</para>
<para>
À partir de PHP 8.0.0, déclarer des paramètres obligatoires après des arguments optionnels est <emphasis>obsolète</emphasis>.
Ce problème peut généralement être résolu en abandonnant la valeur par défaut, puisqu'elle ne sera jamais utilisée.
Une exception à cette règle concerne les paramètres de la forme <code>Type $param = null</code>,
où le &null; par défaut rend le type implicitement nullable.
Cet usage est déprécié à partir de PHP 8.4.0, et un
<link linkend="language.types.declarations.nullable">type nullable</link>
explicite doit être utilisé à la place.
<example>
<title>Déclaration des paramètres optionnels après les paramètres obligatoires</title>
<programlisting role="php">
<![CDATA[
<?php
function foo($a = [], $b) {} // Valeur par défaut non utilisée ; déconseillée à partir de PHP 8.0.0
function foo($a, $b) {} // Fonctionnellement équivalent, pas davertissement de dépréciation
function bar(A $a = null, $b) {} // À partir de PHP 8.1.0, $a est implicitement requis
// (car il précède un paramètre requis),
// mais implicitement nullable (déconseillé à partir de PHP 8.4.0),
// car la valeur par défaut du paramètre est null
function bar(?A $a, $b) {} // Recommandé
?>
]]>
</programlisting>
</example>
</para>
<note>
<simpara>
À partir de PHP 7.1.0, l'omission d'un paramètre qui ne spécifie pas une valeur par défaut lance
un <classname>ArgumentCountError</classname> ;
dans les versions précédentes, cela levait un avertissement.
</simpara>
</note>
<note>
<simpara>
Les arguments passés par référence peuvent avoir
une valeur par défaut.
</simpara>
</note>
</sect2>
<sect2 xml:id="functions.variable-arg-list">
<title>Liste d'argument à nombre variable</title>
<simpara>
PHP supporte les arguments à nombre variable dans les
fonctions définies par l'utilisateur en utilisant le token
<literal>...</literal>.
</simpara>
<para>
La liste des arguments peut inclure le
token <literal>...</literal> pour indiquer que cette fonction accepte
un nombre variable d'arguments. Les arguments seront passés dans la variable
fournie sous forme d'un &array;:
<example>
<title>Utilisation de <literal>...</literal> pour accéder aux arguments variables</title>
<programlisting role="php">
<![CDATA[
<?php
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
10
]]>
</screen>
</example>
</para>
<para>
<literal>...</literal> peut aussi être utilisé lors des appels de
fonctions pour extraire le &array; ou la variable
<classname>Traversable</classname> ou le littéral dans la liste d'arguments :
<example>
<title>Utilisation de <literal>...</literal> pour fournir des arguments</title>
<programlisting role="php">
<![CDATA[
<?php
function add($a, $b) {
return $a + $b;
}
echo add(...[1, 2])."\n";
$a = [1, 2];
echo add(...$a);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
3
3
]]>
</screen>
</example>
</para>
<para>
Il est possible de spécifier des paramètres classiques avant le mot clé
<literal>...</literal>. Dans ce cas, seuls les arguments finaux
qui ne correspondent pas à un argument classique seront ajoutés
au tableau généré par <literal>...</literal>.
</para>
<para>
Il est également possible d'ajouter une
<link linkend="language.types.declarations">déclaration de type</link>
avant le jeton <literal>...</literal>. Si ceci est présent,
alors tous les arguments capturés par <literal>...</literal>
doivent correspondre au type de paramètre.
<example>
<title>Transtypage d'arguments variables</title>
<programlisting role="php">
<![CDATA[
<?php
function total_intervals($unit, DateInterval ...$intervals) {
$time = 0;
foreach ($intervals as $interval) {
$time += $interval->$unit;
}
return $time;
}
$a = new DateInterval('P1D');
$b = new DateInterval('P2D');
echo total_intervals('d', $a, $b).' jours';
// Ceci échouera, car null n'est pas un objet DateInterval.
echo total_intervals('d', null);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
3 jours
Catchable fatal error: Argument 2 passed to total_intervals() must be an instance of DateInterval, null given, called in - on line 14 and defined in - on line 2
]]>
</screen>
</example>
</para>
<para>
Pour finir, il est possible de passer des arguments variables
<link linkend="functions.arguments.by-reference">par référence</link>
en préfixant le mot clé <literal>...</literal> d'un ET commercial
(<literal>&amp;</literal>).
</para>
</sect2>
<sect2 xml:id="functions.named-arguments">
<title>Arguments Nommés</title>
<para>
PHP 8.0.0 introduit les arguments nommés comme extension aux paramètres
positionnels existant. Les arguments nommés permettent de passer les
arguments à une fonction en s'appuyant sur le nom du paramètre, au lieu de
la position du paramètre. Ceci documente automatiquement la signification
de l'argument, rend l'ordre des arguments indépendant et permet d'ignorer
les valeurs par défaut arbitrairement.
</para>
<para>
Les arguments nommés sont passés en préfixant la valeur avec le nom du
paramètre suivi d'un deux-points. Utiliser des mots-clés réservés comme
nom de paramètre est autorisé. Le nom du paramètre doit être un identifiant,
le spécifiant de façon dynamique n'est pas permis.
</para>
<example>
<title>Syntaxe des arguments nommés</title>
<programlisting role="php">
<![CDATA[
<?php
myFunction(paramName: $value);
array_foobar(array: $value);
// NON supporté.
function_name($variableStoringParamName: $value);
?>
]]>
</programlisting>
</example>
<example>
<title>Arguments positionnels comparés aux arguments nommés</title>
<programlisting role="php">
<![CDATA[
<?php
// Utilisant les arguments positionnels :
array_fill(0, 100, 50);
// Utilisant les arguments nommés :
array_fill(start_index: 0, count: 100, value: 50);
?>
]]>
</programlisting>
</example>
<para>
L'ordre dans lequel les arguments nommés sont passés n'importe pas.
</para>
<example>
<title>Même exemple que ci-dessus, mais avec un ordre de paramètre différent</title>
<programlisting role="php">
<![CDATA[
<?php
array_fill(value: 50, count: 100, start_index: 0);
?>
]]>
</programlisting>
</example>
<para>
Les arguments nommés peuvent être combinés avec les arguments positionnels.
Auquel cas, les arguments nommés doivent venir après les arguments positionnels.
Il est aussi possible de spécifier seulement certains des arguments optionnels
d'une fonction, peu importe leur ordre.
</para>
<example>
<title>Combiner les arguments nommés avec les arguments positionnels</title>
<programlisting role="php">
<![CDATA[
<?php
htmlspecialchars($string, double_encode: false);
// Identique à
htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', false);
?>
]]>
</programlisting>
</example>
<para>
Passer le même argument plusieurs fois résulte en une
<classname>Error</classname> exception.
</para>
<example>
<title>Erreur déclenchée lorsqu'un argument est passé plusieurs fois au même paramètre nommé</title>
<programlisting role="php">
<![CDATA[
<?php
function foo($param) { ... }
foo(param: 1, param: 2);
// Error: Named parameter $param overwrites previous argument
foo(1, param: 2);
// Error: Named parameter $param overwrites previous argument
?>
]]>
</programlisting>
</example>
<para>
À partir de PHP 8.1.0, il est possible d'utiliser des arguments nommés après avoir décompressé les arguments.
Un argument nommé <emphasis>ne doit pas</emphasis> écraser un argument déjà déballé.
</para>
<example>
<title>Utiliser les arguments nommés après le déballage</title>
<programlisting role="php">
<![CDATA[
<?php
function foo($a, $b, $c = 3, $d = 4) {
return $a + $b + $c + $d;
}
var_dump(foo(...[1, 2], d: 40)); // 46
var_dump(foo(...['b' => 2, 'a' => 1], d: 40)); // 46
var_dump(foo(...[1, 2], b: 20)); // Erreur fatale. Le paramètre nommé $b écrase l'argument précédent.
?>
]]>
</programlisting>
</example>
</sect2>
</sect1>
<sect1 xml:id="functions.returning-values">
<title>Les valeurs de retour</title>
<para>
Les valeurs sont renvoyées en utilisant une
instruction de retour optionnelle. Tous les types de variables
peuvent être renvoyés, tableaux et objets compris. Cela fait
que la fonction finit son exécution immédiatement et passe
le contrôle à la ligne appelante. Voir
<function>return</function>
pour plus d'informations.
</para>
<note>
<para>
Si <function>return</function>
est omis, la valeur &null; sera retournée.
</para>
</note>
<sect2>
<title>Utilisation de return</title>
<para>
<example>
<title>Utilisation de <function>return</function></title>
<programlisting role="php">
<![CDATA[
<?php
function carre($num)
{
return $num * $num;
}
echo carre(4); // Affiche '16'
?>
]]>
</programlisting>
</example>
</para>
<para>
Une fonction ne peut pas renvoyer plusieurs valeurs en même temps, mais
il est possible d'obtenir le même résultat en renvoyant un tableau.
</para>
<para>
<example>
<title>Retourner un tableau d'une fonction</title>
<programlisting role="php">
<![CDATA[
<?php
function petit_nombre()
{
return [0, 1, 2];
}
// La déconstruction d'un tableau collectera chaque membre du tableau individuellement
[$zero, $one, $two] = petit_nombre();
// Avant PHP 7.1, la seule alternative équivalente est en utilisant la structure de langage list()
list ($zero, $un, $deux) = petit_nombre();
?>
]]>
</programlisting>
</example>
</para>
<para>
Pour retourner une référence d'une fonction, il faut utiliser
l'opérateur &amp; aussi bien dans la déclaration de la fonction que dans
l'assignation de la valeur de retour.
</para>
<para>
<example>
<title>Retourner une référence d'une fonction</title>
<programlisting role="php">
<![CDATA[
<?php
function &retourne_reference()
{
return $uneref;
}
$newref =& retourne_reference();
?>
]]>
</programlisting>
</example>
</para>
<simpara>
Pour plus d'informations sur les références, se référer à <link
linkend="language.references">l'explication sur les références</link>.
</simpara>
</sect2>
</sect1>
<sect1 xml:id="functions.variable-functions">
<title>Fonctions variables</title>
<para>
PHP supporte le concept de fonctions variables.
Cela signifie que si le nom d'une variable est suivi de parenthèses,
PHP recherchera une fonction de même nom et essaiera de l'exécuter.
Cela peut servir, entre autres, pour faire des fonctions de rappel, des tables de fonctions...
</para>
<para>
Les fonctions variables ne peuvent pas fonctionner avec les
éléments de langage comme les
<function>echo</function>, <function>print</function>,
<function>unset</function>, <function>isset</function>,
<function>empty</function>, <function>include</function>,
<function>require</function> etc. Il est nécessaire d'utiliser une
gestion de fonctions personnalisée pour utiliser un de ces éléments
de langage comme fonctions variables.
</para>
<para>
<example>
<title>Exemple de fonction variable</title>
<programlisting role="php">
<![CDATA[
<?php
function foo() {
echo "dans foo()<br />\n";
}
function bar($arg = '')
{
echo "Dans bar(); l'argument était '$arg'.<br />\n";
}
// Ceci est une fonction détournée de echo
function echoit($string)
{
echo $string;
}
$func = 'foo';
$func(); // Appel foo()
$func = 'bar';
$func('test'); // Appel bar()
$func = 'echoit';
$func('test'); // Appel echoit()
?>
]]>
</programlisting>
</example>
</para>
<para>
Il est aussi possible d'appeler les méthodes d'un objet en utilisant le système des
fonctions variables.
<example>
<title>Exemple de méthode variable</title>
<programlisting role="php">
<![CDATA[
<?php
class Foo
{
function Variable()
{
$name = 'Bar';
$this->$name(); // Appelle la méthode Bar()
}
function Bar()
{
echo "C'est Bar";
}
}
$foo = new Foo();
$funcname = "Variable";
$foo->$funcname(); // Appelle $foo->Variable()
?>
]]>
</programlisting>
</example>
</para>
<para>
Lors de l'appel à des méthodes statiques, l'appel de fonction est meilleur que
l'opérateur de propriété statique :
<example>
<title>Exemple de méthode variable avec des propriétés statiques</title>
<programlisting role="php">
<![CDATA[
<?php
class Foo
{
static $variable = 'static property';
static function Variable()
{
echo 'Method Variable called';
}
}
echo Foo::$variable; // Ceci affiche 'static property'. Il est nécessaire d'avoir une $variable dans le contexte.
$variable = "Variable";
Foo::$variable(); // Ceci appelle $foo->Variable(), lisant ainsi la $variable depuis le contexte.
?>
]]>
</programlisting>
</example>
</para>
<para>
<example>
<title>callables complexes</title>
<programlisting role="php">
<![CDATA[
<?php
class Foo
{
static function bar()
{
echo "bar\n";
}
function baz()
{
echo "baz\n";
}
}
$func = array("Foo", "bar");
$func(); // Affiche "bar"
$func = array(new Foo, "baz");
$func(); // Affiche "baz"
$func = "Foo::bar";
$func(); // Affiche "bar"
]]>
</programlisting>
</example>
</para>
<sect2 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><function>is_callable</function></member>
<member><function>call_user_func</function></member>
<member><function>function_exists</function></member>
<member><link linkend="language.variables.variable">Les variables variable</link></member>
</simplelist>
</para>
</sect2>
</sect1>
<sect1 xml:id="functions.internal">
<title>Fonctions internes</title>
<para>
PHP dispose de nombreuses fonctions et structures standards. Il y a aussi
des fonctions qui requièrent des extensions spécifiques de PHP, sans
lesquelles l'erreur fatale
<literal>undefined function</literal> sera obtenue. Par exemple, pour utiliser les
fonctions <link linkend="ref.image">d'images</link>,
telles que <function>imagecreatetruecolor</function>, le
support de <productname>GD</productname> dans PHP est nécessaire. Ou bien, pour utiliser
<function>mysqli_connect</function>, l'extension
<link linkend="book.mysqli">MySQLi</link> est requise. Il y a des fonctions de base qui
sont incluses dans toutes les versions de PHP, telles que les fonctions de
<link linkend="ref.strings">chaînes de caractères</link> et les fonctions
de <link linkend="ref.var">variables</link>. Utiliser
<function>phpinfo</function> ou
<function>get_loaded_extensions</function> pour savoir quelles sont les
extensions qui sont compilées avec PHP. Il est à noter que de
nombreuses extensions sont activées par défaut, et que le manuel PHP est
compartimenté par extension. Voir les chapitres de
<link linkend="configuration">configuration</link>,
<link linkend="install">installation</link> ainsi que les
détails particuliers à chaque extension, pour savoir comment les mettre en place.
</para>
<para>
Lire et comprendre le prototype d'une fonction est décrit dans l'annexe
<link linkend="about.prototypes">Comment lire la définition d'une
fonction (prototype)</link>.
Il est important de comprendre ce qu'une fonction retourne, ou si une
fonction travaille directement sur la valeur des paramètres fournis. Par
exemple, <function>str_replace</function> va retourner une chaîne modifiée,
tandis que <function>usort</function> travaille directement sur la variable
passée en paramètre. Chaque page du manuel a des informations spécifiques
sur chaque fonction, comme le nombre de paramètres, les évolutions de
spécifications, les valeurs retournées en cas de succès ou d'échec, et la
disponibilité en fonction des versions. Bien connaître ces différences,
parfois subtiles, est crucial pour bien programmer en PHP.
</para>
<note>
<simpara>
Si les paramètres donnés à une fonction ne sont pas corrects, comme le fait
de passer un &array; alors qu'une &string; est attendue, la valeur retournée
de la fonction est indéfinie. Dans ce cas, la fonction retournera la plupart
du temps une valeur &null; mais ce n'est juste qu'une convention et
ne peut être considéré comme une certitude.
À partir de PHP 8.0.0, une exception <classname>TypeError</classname>
est normalement lancée dans ce cas.
</simpara>
</note>
<note>
<para>
En mode coercitif, les types scalaires des fonctions internes sont nullables par défaut.
À partir PHP 8.1.0, passer &null; à un paramètre de fonction interne qui n'est pas déclaré
nullable est déconseillé et émet une notice de dépréciation en mode coercitif pour s'aligner
sur le comportement des fonctions définies par l'utilisateur, où les types scalaires doivent
être marqués comme nullables explicitement.
</para>
<para>
Par exemple, la fonction <function>strlen</function> attend du paramètre <literal>$string</literal>
soit de type &string; et non &null;.
Pour des raisons historiques, PHP autorise le passage de &null; pour ce paramètre en mode coercitif.
Le paramètre est alors implicitement converti en <type>string</type>, résultant en une valeur <literal>""</literal>.
Noter qu'une <classname>TypeError</classname> est émise en mode strict.
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
var_dump(strlen(null));
// "Deprecated: Passing null to parameter #1 ($string) of type string is deprecated" as of PHP 8.1.0
// int(0)
var_dump(str_contains("foobar", null));
// "Deprecated: Passing null to parameter #2 ($needle) of type string is deprecated" as of PHP 8.1.0
// bool(true)
?>
]]>
</programlisting>
</informalexample>
</note>
<sect2 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><function>function_exists</function></member>
<member><link linkend="funcref">l'index des fonctions</link></member>
<member><function>get_extension_funcs</function></member>
<member><function>dl</function></member>
</simplelist>
</para>
</sect2>
</sect1>
<sect1 xml:id="functions.anonymous">
<title>Fonctions anonymes</title>
<simpara>
Les fonctions anonymes, aussi appelées fermetures ou <literal>closures</literal>
permettent la création de fonctions sans préciser leur nom.
Elles sont particulièrement utiles comme fonctions de rappel <type>callable</type>,
mais leur utilisation n'est pas limitée à ce seul usage.
</simpara>
<simpara>
Les fonctions anonymes sont implémentées en utilisant la classe
<link linkend="class.closure"><classname>Closure</classname></link>.
</simpara>
<example>
<title>Exemples avec des fonctions anonymes</title>
<programlisting role="php">
<![CDATA[
<?php
echo preg_replace_callback('~-([a-z])~', function ($match) {
return strtoupper($match[1]);
}, 'bonjour-le-monde');
?>
]]>
</programlisting>
</example>
<simpara>
Les fonctions anonymes peuvent aussi être utilisées comme valeurs de
variables. PHP va automatiquement convertir ces expressions
en objets <classname>Closure</classname>. Assigner une fermeture
à une variable est la même chose qu'une affectation classique,
y compris pour le point-virgule final.
</simpara>
<example>
<title>Assignation de fonction anonyme à une variable</title>
<programlisting role="php">
<![CDATA[
<?php
$greet = function($name) {
printf("Bonjour %s\r\n", $name);
};
$greet('World');
$greet('PHP');
?>
]]>
</programlisting>
</example>
<simpara>
Les fonctions anonymes peuvent hériter des variables du contexte de leur
parent. Ces variables doivent alors être passées dans la construction
de langage <literal>use</literal>.
À partir de PHP 7.1, ces variables ne doivent pas inclure de &link.superglobals;,
<varname>$this</varname>, ou des variables ayant le même nom qu'un paramètre.
Une déclaration de type de retour pour la fonction doit être placée
<emphasis>après</emphasis> la clause <literal>use</literal>.
</simpara>
<example>
<title>Héritage de variable depuis le contexte parent</title>
<programlisting role="php">
<![CDATA[
<?php
$message = 'hello';
// Pas de "use"
$example = function () {
var_dump($message);
};
$example();
// Hérite $message
$example = function () use ($message) {
var_dump($message);
};
$example();
// La valeur de la variable héritée est définie lorsque la fonction est
// définie non quand elle est appelée
$message = 'world';
$example();
// Réinitialisation de la variable message
$message = 'hello';
// Héritage par référence
$example = function () use (&$message) {
var_dump($message);
};
$example();
// Le changement de valeur dans le contexte parent est reflété lors de
// l'appel de la fonction.
$message = 'world';
$example();
// Les fonctions anonymes acceptent également des arguments classiques
$example = function ($arg) use ($message) {
var_dump($arg . ' ' . $message);
};
$example("hello");
// La déclaration du type de retour vient après la clause use
$example = function () use ($message): string {
return "hello $message";
};
var_dump($example());
?>
]]>
</programlisting>
&example.outputs.similar;
<screen>
<![CDATA[
Notice: Undefined variable: message in /example.php on line 6
NULL
string(5) "hello"
string(5) "hello"
string(5) "hello"
string(5) "world"
string(11) "hello world"
string(11) "hello world"
]]>
</screen>
</example>
<para>
À partir de PHP 8.0.0, la liste des variables héritées du contexte peut
inclure une virgule finale, qui sera ignorée.
</para>
<simpara>
L'héritage du contexte parent
<emphasis>n'est pas</emphasis> la même chose que les variables
de l'environnement global. Les variables globales existent dans le
contexte global, qui est le même, quelle que soit la fonction qui
s'exécute. Le contexte parent d'une fonction anonyme est la fonction
dans laquelle la fonction a été déclarée (pas nécessairement celle
qui appelle). Voir l'exemple ci-dessous :
</simpara>
<example>
<title>Fonctions anonymes et contexte</title>
<programlisting role="php">
<![CDATA[
<?php
// Un panier d'achat simple, qui contient une liste de produits
// choisis et la quantité désirée de chaque produit. Il inclut
// une méthode qui calcule le prix total des éléments dans le panier
// en utilisant une fonction de rappel anonyme.
class Panier
{
const PRICE_BEURRE = 1.00;
const PRICE_LAIT = 3.00;
const PRICE_OEUF = 6.95;
protected $products = array();
public function add($product, $quantity)
{
$this->products[$product] = $quantity;
}
public function getQuantity($product)
{
return isset($this->products[$product]) ? $this->products[$product] :
FALSE;
}
public function getTotal($tax)
{
$total = 0.00;
$callback =
function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
array_walk($this->products, $callback);
return round($total, 2);
}
}
$mon_panier = new Panier;
// Ajout d'élément au panier
$mon_panier->add('beurre', 1);
$mon_panier->add('lait', 3);
$mon_panier->add('oeuf', 6);
// Affichage du prix avec 5.5% de TVA
print $mon_panier->getTotal(0.055) . "\n";
// Le résultat sera 54.29
?>
]]>
</programlisting>
</example>
<example>
<title>Liage automatique de <literal>$this</literal></title>
<programlisting role="php">
<![CDATA[
<?php
class Test
{
public function testing()
{
return function() {
var_dump($this);
};
}
}
$object = new Test;
$function = $object->testing();
$function();
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
object(Test)#1 (0) {
}
]]>
</screen>
</example>
<para>
Lorsque déclarée dans le contexte d'une classe, la classe
courante est automatiquement liée, la rendant <literal>$this</literal>
disponible dans le contexte de la fonction. Si ce liage automatique de
la classe courante n'est pas souhaité, alors les
<link linkend="functions.anonymous-functions.static">fonctions anonymes
statiques</link> peuvent être utilisées à la place.
</para>
<sect2 xml:id="functions.anonymous-functions.static">
<title>Les fonctions anonymes statiques</title>
<para>
Les fonctions anonymes peuvent être déclarées statiquement.
Ceci permet de ne pas lier automatiquement la classe courante à la fonction.
Les objets peuvent aussi ne pas être liés lors de l'exécution.
</para>
<para>
<example>
<title>Tentative d'usage de <literal>$this</literal> dans une fonction anonyme statique</title>
<programlisting role="php">
<![CDATA[
<?php
class Foo
{
function __construct()
{
$func = static function() {
var_dump($this);
};
$func();
}
};
new Foo();
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Notice: Undefined variable: this in %s on line %d
NULL
]]>
</screen>
</example>
</para>
<para>
<example>
<title>Tentative de liage d'un objet à une fonction anonyme statique</title>
<programlisting role="php">
<![CDATA[
<?php
$func = static function() {
// corps de la fonction
};
$func = $func->bindTo(new stdClass);
$func();
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Warning: Cannot bind an instance to a static closure in %s on line %d
]]>
</screen>
</example>
</para>
</sect2>
<sect2 role="changelog">
&reftitle.changelog;
<para>
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>&Version;</entry>
<entry>&Description;</entry>
</row>
</thead>
<tbody>
<row>
<entry>8.3.0</entry>
<entry>
Les fermetures créées à partir des <link linkend="language.oop5.magic">méthodes
magiques</link> peuvent accepter des paramètres nommés.
</entry>
</row>
<row>
<entry>7.1.0</entry>
<entry>
Les fonctions anonymes peuvent ne pas se fermer sur les &link.superglobals;,
<varname>$this</varname>, ou toute variable avec le même nom qu'un
paramètre.
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</sect2>
<sect2 role="notes">
&reftitle.notes;
<note>
<simpara>
Il est possible d'utiliser les fonctions <function>func_num_args</function>,
<function>func_get_arg</function> et <function>func_get_args</function>
dans une fonction anonyme.
</simpara>
</note>
</sect2>
</sect1>
<sect1 xml:id="functions.arrow">
<title>Fonction Fléchée</title>
<simpara>
Les fonctions fléchées ont été introduites en PHP 7.4 en tant que syntaxe
plus concise pour les
<link linkend="functions.anonymous">fonctions anonymes</link>.
</simpara>
<simpara>
Les fonctions anonymes comme les fonctions fléchées sont implémentées en
utilisant la classe
<link linkend="class.closure"><classname>Closure</classname></link>.
</simpara>
<simpara>
Les fonctions fléchées ont la forme basique
<code>fn (argument_list) =&gt; expr</code>.
</simpara>
<simpara>
Les fonctions fléchées supportent les mêmes fonctionnalités que les
<link linkend="functions.anonymous">fonctions anonymes</link>,
à l'exception que l'utilisation des variables de la portée parente est
automatique.
</simpara>
<simpara>
Quand une variable utilisée dans l'expression est définie dans la portée
parente, elle sera implicitement capturée par valeur.
Dans l'exemple suivant, les fonctions <varname>$fn1</varname> et
<varname>$fn2</varname> se comportent de façon identique.
</simpara>
<para>
<example>
<title>Les fonctions fléchées capturent les variables par valeur automatiquement</title>
<programlisting role="php">
<![CDATA[
<?php
$y = 1;
$fn1 = fn($x) => $x + $y;
// équivalent à utiliser $y par valeur :
$fn2 = function ($x) use ($y) {
return $x + $y;
};
var_export($fn1(3));
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
4
]]>
</screen>
</example>
</para>
<simpara>
Ceci fonctionne aussi si les fonctions fléchées sont imbriquées :
</simpara>
<para>
<example>
<title>Les fonctions fléchées capturent les variables par valeur automatiquement, même imbriquées</title>
<programlisting role="php">
<![CDATA[
<?php
$z = 1;
$fn = fn($x) => fn($y) => $x * $y + $z;
// Affiche 51
var_export($fn(5)(10));
?>
]]>
</programlisting>
</example>
</para>
<simpara>
Similairement aux fonctions anonymes,
la syntaxe des fonctions fléchées permet les signatures de fonction arbitraire,
ceci inclus les types de paramètres et de retour, valeur par défaut, variable,
aussi bien que le passage et retour par référence.
Tous les exemples suivants sont des fonctions fléchées valides :
</simpara>
<para>
<example>
<title>Exemples de fonctions fléchées</title>
<programlisting role="php">
<![CDATA[
<?php
fn(array $x) => $x;
static fn($x): int => $x;
fn($x = 42) => $x;
fn(&$x) => $x;
fn&($x) => $x;
fn($x, ...$rest) => $rest;
?>
]]>
</programlisting>
</example>
</para>
<simpara>
Les fonctions fléchées lient les variables par valeur.
Ceci est à peu près équivalent à effectuer un <code>use($x)</code> pour
chaque variable <varname>$x</varname> utilisée à l'intérieur de la fonction
fléchée.
Un liage par valeur signifie qu'il n'est pas possible de modifier une
valeur de la portée extérieure.
<link linkend="functions.anonymous">Les fonctions anonymes</link>
peuvent être utilisées à la place pour des liaisons par référence.
</simpara>
<para>
<example>
<title>
Valeurs de la portée extérieure ne peuvent pas être modifiées par les fonctions fléchées
</title>
<programlisting role="php">
<![CDATA[
<?php
$x = 1;
$fn = fn() => $x++; // N'a aucun effet
$fn();
var_export($x); // Affiche 1
?>
]]>
</programlisting>
</example>
</para>
<sect2 role="changelog">
&reftitle.changelog;
<para>
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>&Version;</entry>
<entry>&Description;</entry>
</row>
</thead>
<tbody>
<row>
<entry>7.4.0</entry>
<entry>
Les fonctions fléchées sont désormais disponibles.
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</sect2>
<sect2 role="notes">
&reftitle.notes;
<note>
<simpara>
Il est possible d'utiliser <function>func_num_args</function>,
<function>func_get_arg</function>, et <function>func_get_args</function>
depuis l'intérieur d'une fonction fléchée.
</simpara>
</note>
</sect2>
</sect1>
<sect1 xml:id="functions.first_class_callable_syntax">
<title>Syntaxe callable de première classe</title>
<para>
La syntaxe de callable de première classe est introduite à partir de PHP 8.1.0,
comme une manière de créer des <link linkend="functions.anonymous">fonctions anonymes</link>
depuis des <link linkend="language.types.callable">callable</link>.
Elle remplace la syntaxe des callables existante utilisant les chaînes et tableaux.
L'avantage de cette syntaxe est qu'elle est accessible à l'analyse statique
et utilise la portée du point où le callable est acquis.
</para>
<para>
La syntaxe <code>CallableExpr(...)</code> est utilisée pour créer un objet
<classname>Closure</classname> depuis le callable.
<code>CallableExpr</code> accepte toute expression qui peut être directement
appelée dans la grammaire de PHP :
<example>
<title>Syntaxe callable de première classe basique</title>
<programlisting role="php">
<![CDATA[
<?php
class Foo {
public function method() {}
public static function staticmethod() {}
public function __invoke() {}
}
$obj = new Foo();
$classStr = 'Foo';
$methodStr = 'method';
$staticmethodStr = 'staticmethod';
$f1 = strlen(...);
$f2 = $obj(...); // objet invocable
$f3 = $obj->method(...);
$f4 = $obj->$methodStr(...);
$f5 = Foo::staticmethod(...);
$f6 = $classStr::$staticmethodStr(...);
// callable traditionnel utilisant une chaîne, un tableau
$f7 = 'strlen'(...);
$f8 = [$obj, 'method'](...);
$f9 = [Foo::class, 'staticmethod'](...);
?>
]]>
</programlisting>
</example>
</para>
<note>
<para>
Les <code>...</code> font partie de la syntaxe et ne sont pas une omission.
</para>
</note>
<para>
<code>CallableExpr(...)</code> a les mêmes sémantiques que <methodname>Closure::fromCallable</methodname>.
C'est-à-dire, contrairement aux callables utilisant les chaînes et tableaux,
<code>CallableExpr(...)</code> respecte la portée du point où il est créé :
<example>
<title>Comparaison de portée de <code>CallableExpr(...)</code> et des callables traditionnels</title>
<programlisting role="php">
<![CDATA[
<?php
class Foo {
public function getPrivateMethod() {
return [$this, 'privateMethod'];
}
private function privateMethod() {
echo __METHOD__, "\n";
}
}
$foo = new Foo;
$privateMethod = $foo->getPrivateMethod();
$privateMethod();
// Erreur fatale : Call to private method Foo::privateMethod() from global scope
// Ceci est dû au fait que l'appel est effectué en dehors de Foo et la visibilité sera vérifiée depuis ce point.
class Foo1 {
public function getPrivateMethod() {
// Utilise la portée où le callable est acquis.
return $this->privateMethod(...); // identique à Closure::fromCallable([$this, 'privateMethod']);
}
private function privateMethod() {
echo __METHOD__, "\n";
}
}
$foo1 = new Foo1;
$privateMethod = $foo1->getPrivateMethod();
$privateMethod(); // Foo1::privateMethod
?>
]]>
</programlisting>
</example>
</para>
<note>
<para>
La création d'objets avec cette syntaxe (e.g <code>new Foo(...)</code>) n'est pas supportée,
car la syntaxe <code>new Foo()</code> n'est pas considérée comme un appel.
</para>
</note>
<note>
<para>
La syntaxe de callable de première classe ne peut pas être combinée avec
l'<link linkend="language.oop5.basic.nullsafe">opérateur nullsafe</link>.
Les deux cas suivants entraînent une erreur de compilation :
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$obj?->method(...);
$obj?->prop->method(...);
?>
]]>
</programlisting>
</informalexample>
</para>
</note>
</sect1>
</chapter>
<!-- 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
-->