mirror of
https://github.com/php/doc-de.git
synced 2026-04-25 07:58:12 +02:00
1787 lines
50 KiB
XML
1787 lines
50 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!-- EN-Revision: dd87866772c31671146ff778140dc0955c55005c Maintainer: cmb Status: ready -->
|
|
<!-- Reviewed: yes -->
|
|
<!-- Rev-Revision: b95e76e41de2ffe5c75e04be1b187d80ca745359 Reviewer: samesch -->
|
|
<!-- Credits: hholzgra, tom, updated to fix build by theseer -->
|
|
<chapter xml:id="language.functions" xmlns="http://docbook.org/ns/docbook">
|
|
<title>Funktionen</title>
|
|
|
|
<sect1 xml:id="functions.user-defined">
|
|
<title>Benutzerdefinierte Funktionen</title>
|
|
<para>
|
|
Eine Funktion wird definiert mit dem Schlüsselwort
|
|
<literal>function</literal>, einem Namen, einer Liste von Parametern (die
|
|
auch leer sein können), die durch Kommata (<literal>,</literal>) getrennt
|
|
und in Klammern eingeschlossen sind, gefolgt vom Funktionskörper, der in
|
|
geschweiften Klammern eingeschlossen ist, wie im folgenden Beispiel:
|
|
</para>
|
|
<example>
|
|
<title>Deklarieren einer neuen Funktion namens <literal>foo</literal></title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo($arg_1, $arg_2, /* ..., */ $arg_n)
|
|
{
|
|
echo "Beispielfunktion.\n";
|
|
return $retval;
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<note>
|
|
<para>
|
|
Seit PHP 8.0.0 kann die Liste der Parameter ein Komma am Ende enthalten:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo($arg_1, $arg_2,) { }
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
</note>
|
|
<simpara>
|
|
Innerhalb des Funktionskörpers kann jeder beliebige korrekte PHP-Code
|
|
vorkommen, sogar andere Funktionen und
|
|
<link linkend="language.oop5.basic.class">Klassen</link>-Definitionen.
|
|
</simpara>
|
|
<para>
|
|
Für Funktionsnamen gelten in PHP die gleichen Regeln wie für andere
|
|
Bezeichner. Ein gültiger Funktionsname beginnt mit einem Buchstaben oder
|
|
Unterstrich gefolgt von einer beliebigen Anzahl von Buchstaben, Ziffern
|
|
und Unterstrichen. Als regulärer Ausdruck wird dies so ausgedrückt:
|
|
<code>^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>.
|
|
</para>
|
|
&tip.userlandnaming;
|
|
<simpara>
|
|
Es ist nicht erforderlich, dass Funktionen bereits definiert sein müssen,
|
|
wenn auf sie verwiesen wird, <emphasis>außer</emphasis> wenn eine Funktion
|
|
nur bedingt definiert wird, wie in den beiden untenstehenden Beispielen
|
|
gezeigt.
|
|
</simpara>
|
|
<para>
|
|
Wenn eine Funktion nur unter bestimmten Bedingungen definiert wird, wie in
|
|
den beiden folgenden Beispielen, muss die Definition dieser Funktion noch
|
|
<emphasis>vor</emphasis> deren Aufruf abgearbeitet werden.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Bedingte Funktionen</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$makefoo = true;
|
|
|
|
/* Wir können foo() von hier aus nicht aufrufen, da sie
|
|
noch nicht existiert, aber wir können bar() aufrufen */
|
|
|
|
bar();
|
|
|
|
if ($makefoo) {
|
|
function foo()
|
|
{
|
|
echo "Ich existiere nicht, bis mich die Programmausführung erreicht hat.\n";
|
|
}
|
|
}
|
|
|
|
/* Nun können wir foo() sicher aufrufen,
|
|
da $makefoo als true ausgewertet wurde */
|
|
|
|
if ($makefoo) foo();
|
|
|
|
function bar()
|
|
{
|
|
echo "Ich existiere sofort nach Programmstart.\n";
|
|
}
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Funktionen innerhalb von Funktionen</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo()
|
|
{
|
|
function bar()
|
|
{
|
|
echo "Ich existiere nicht, bis foo() aufgerufen wurde.\n";
|
|
}
|
|
}
|
|
|
|
/* Wir können bar() noch nicht
|
|
aufrufen, da es nicht existiert */
|
|
|
|
foo();
|
|
|
|
/* Nun können wir auch bar() aufrufen, da sie durch die
|
|
Abarbeitung von foo() verfügbar gemacht wurde */
|
|
|
|
bar();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Alle Funktionen und Klassen in PHP existieren im globalen Namensraum -
|
|
sie können außerhalb von Funktionen aufgerufen werden, selbst wenn sie
|
|
innerhalb einer Funktion definiert wurden und umgekehrt.
|
|
</para>
|
|
<simpara>
|
|
PHP unterstützt weder das Überladen von Funktionen, noch ist es möglich,
|
|
zuvor deklarierte Funktionen neu zu definieren oder die Definition zu
|
|
löschen.
|
|
</simpara>
|
|
<note>
|
|
<simpara>
|
|
Groß- und Kleinschreibung spielt zwar bei Funktionsnamen keine Rolle für
|
|
die ASCII-Zeichen <literal>A</literal> bis <literal>Z</literal>, es
|
|
empfiehlt sich aber trotzdem, bei Funktionsaufrufen die gleiche
|
|
Schreibweise wie in der Deklaration zu benutzen.
|
|
</simpara>
|
|
</note>
|
|
<simpara>
|
|
Sowohl
|
|
<link linkend="functions.variable-arg-list">eine variable Anzahl Parameter</link>
|
|
als auch
|
|
<link linkend="functions.arguments.default">Vorgabewerte für Parameter</link>
|
|
werden in Funktionen unterstützt. Siehe auch die Funktionsreferenzen für
|
|
<function>func_num_args</function>, <function>func_get_arg</function> und
|
|
<function>func_get_args</function> für weitere Informationen.
|
|
</simpara>
|
|
<para>
|
|
Es ist in PHP möglich, Funktionen rekursiv aufzurufen.
|
|
<example>
|
|
<title>Rekursive Funktionen</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function recursion($a)
|
|
{
|
|
if ($a < 20) {
|
|
echo "$a\n";
|
|
recursion($a + 1);
|
|
}
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<note>
|
|
<simpara>
|
|
Rekursive Funktions-/Methodenaufrufe mit einer Tiefe von über 100-200
|
|
können zu einem Stacküberlauf und damit zum Programmabbruch führen.
|
|
Insbesondere wird eine unbegrenzte Rekursion als Programmierfehler
|
|
erachtet.
|
|
</simpara>
|
|
</note>
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.arguments">
|
|
<title>Funktionsparameter und -argumente</title>
|
|
<simpara>
|
|
Die Funktionsparameter werden in der Signatur der Funktion deklariert.
|
|
Mit einer Liste von Argumenten kann man Informationen an eine Funktion
|
|
übergeben. Die Argumentenliste ist eine durch Kommas getrennte Liste von
|
|
Ausdrücken. Die Argumente werden von links nach rechts ausgewertet und das
|
|
Ergebnis wird den Parametern der Funktion zugewiesen, bevor die eigentliche
|
|
Funktion aufgerufen wird, &dh; mit der sog.
|
|
<emphasis>eager</emphasis>-Evaluation (dt. eifrige Auswertung).
|
|
</simpara>
|
|
<para>
|
|
PHP unterstützt die Weitergabe von Parametern als Werte (das ist der
|
|
Standard), als
|
|
<link linkend="functions.arguments.by-reference">Verweise</link> und als
|
|
<link linkend="functions.arguments.default">Vorgabewerte</link>. Eine
|
|
<link linkend="functions.variable-arg-list">variable Anzahl von Parametern</link>
|
|
und <link linkend="functions.named-arguments">benannte Parameter</link> werden
|
|
ebenfalls unterstützt.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
Seit PHP 7.3.0 ist es möglich, in der Argumentliste eines Funktionsaufrufs
|
|
ein nachgestelltes Komma zu verwenden:
|
|
<informalexample>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$v = foo(
|
|
$arg_1,
|
|
$arg_2,
|
|
);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</informalexample>
|
|
</para>
|
|
</note>
|
|
<para>
|
|
Seit PHP 8.0.0 kann die Liste der Funktionsparameter ein nachgestelltes
|
|
Komma enthalten, das ignoriert wird. Das ist besonders nützlich in Fällen,
|
|
in denen die Liste der Parameter lang ist oder lange Variablennamen
|
|
enthält, sodass es praktisch ist, die Parameter vertikal aufzulisten.
|
|
</para>
|
|
<example>
|
|
<title>Liste von Funktionsparametern mit nachgestelltem Komma</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', // Dieses nachgestellte Komma war vor 8.0.0
|
|
// nicht erlaubt.
|
|
)
|
|
{
|
|
// ...
|
|
}
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
<sect2 xml:id="functions.arguments.by-reference">
|
|
<title>Parameter als Verweise übergeben</title>
|
|
|
|
<simpara>
|
|
Normalerweise werden den Funktionen Werte als Parameter übermittelt. Wenn
|
|
man also den Wert dieser Parameter innerhalb der Funktion ändert, bleiben
|
|
sie außerhalb der Funktion unverändert. Wollen Sie aber erreichen, dass
|
|
die Änderung auch außerhalb der Funktion sichtbar wird, müssen Sie die
|
|
Parameter als Verweise (Referenzen) übergeben.
|
|
</simpara>
|
|
<para>
|
|
Wenn eine Funktion einen Parameter generell als Verweis behandeln soll,
|
|
setzt man in der Funktionsdefinition ein kaufmännisches Und (&) vor
|
|
den Parameternamen:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Übergeben von Funktionsparametern als Verweis</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function fuege_etwas_an(&$string)
|
|
{
|
|
$string .= 'und etwas mehr.';
|
|
}
|
|
$str = 'Dies ist ein String, ';
|
|
fuege_etwas_an($str);
|
|
echo $str; // Ausgabe: 'Dies ist ein String, und etwas mehr.'
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Es ist ein Fehler, einen konstanten Ausdruck als Argument an einen
|
|
Parameter zu übergeben, der eigentlich als Referenz übergeben werden
|
|
müsste.
|
|
</para>
|
|
</sect2>
|
|
<sect2 xml:id="functions.arguments.default">
|
|
<title>Vorgabewerte für Parameter</title>
|
|
|
|
<para>
|
|
Eine Funktion kann Standardwerte für Parameter definieren, indem sie eine
|
|
ähnliche Syntax wie bei der Zuweisung von Variablen verwendet. Der
|
|
Standardwert wird nur verwendet, wenn für den Parameter kein Argument
|
|
übergeben wurde. Es ist zu beachten, dass bei der Übergabe von &null;
|
|
<emphasis>nicht</emphasis> der Standardwert zugewiesen wird.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Einsatz von Vorgabeparametern in Funktionen</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function machkaffee($typ = "Cappuccino")
|
|
{
|
|
return "Ich mache eine Tasse $typ.\n";
|
|
}
|
|
echo machkaffee();
|
|
echo machkaffee(null);
|
|
echo machkaffee("Espresso");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Ich mache eine Tasse Cappuccino.
|
|
Ich mache eine Tasse .
|
|
Ich mache eine Tasse Espresso.
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Die Standardwerte der Parameter können skalare Werte,
|
|
<type>&array;</type>s, der spezielle Typ &null; und seit PHP 8.1.0 auch
|
|
Objekte sein, die die
|
|
<link linkend="language.oop5.basic.new">new ClassName()</link>-Syntax
|
|
verwenden.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Nichtskalare Typen als Vorgabewert</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function makecoffee($types = array("Cappuccino"), $coffeeMaker = NULL)
|
|
{
|
|
$device = is_null($coffeeMaker) ? "Hand" : $coffeeMaker;
|
|
return "Ich mache eine Tasse ".join(", ", $types)." mit der $device.\n";
|
|
}
|
|
echo makecoffee();
|
|
echo makecoffee(array("Cappuccino", "Lavazza"), "Teekanne");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Ich mache eine Tasse Cappuccino mit der Hand.
|
|
Ich mache eine Tasse Cappuccino, Lavazza mit der Teekanne.
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Verwendung von Objekten als Standardwerte (seit PHP 8.1.0)</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class DefaultCoffeeMaker {
|
|
public function brew() {
|
|
return "Koche Kaffee.\n";
|
|
}
|
|
}
|
|
class FancyCoffeeMaker {
|
|
public function brew() {
|
|
return "Bereite einen schönen Kaffee für Dich zu.\n";
|
|
}
|
|
}
|
|
function makecoffee($coffeeMaker = new DefaultCoffeeMaker)
|
|
{
|
|
return $coffeeMaker->brew();
|
|
}
|
|
echo makecoffee();
|
|
echo makecoffee(new FancyCoffeeMaker);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Koche Kaffee.
|
|
Bereite einen schönen Kaffee für Dich zu.
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
Der Vorgabewert muss ein konstanter Ausdruck sein, darf also zum Beispiel
|
|
keine Variable, keine Eigenschaft einer Klasse und kein Funktionsaufruf
|
|
sein.
|
|
</simpara>
|
|
<para>
|
|
Es ist zu beachten, dass optionale Parameter nach den erforderlichen
|
|
Parametern angegeben werden müssen, da sie sonst bei einem Aufruf nicht
|
|
weggelassen werden können. Das nachfolgende Beispiel verdeutlicht dies:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Ungültige Verwendung von Funktionsparametern mit Vorgabewerten</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function mach_joghurt($typ = "rechtsdrehendes", $geschmack)
|
|
{
|
|
return "Mache einen Becher $typ $geschmack-Joghurt.\n";
|
|
}
|
|
|
|
echo mach_joghurt("Brombeer"); // "Brombeer" ist $typ, nicht $geschmack
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Fatal error: Uncaught ArgumentCountError: Too few arguments
|
|
to function makeyogurt(), 1 passed in example.php on line 42
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Zum Vergleich mit obigem Beispiel::
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Richtiger Einsatz von Funktionsparametern mit Vorgabewerten</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function mach_joghurt($geschmack, $typ = "rechtsdrehendes")
|
|
{
|
|
return "Mache einen Becher $typ $geschmack-Joghurt.\n";
|
|
}
|
|
|
|
echo mach_joghurt("Brombeer"); // "Brombeer" ist $geschmack
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Mache einen Becher rechtsdrehendes Brombeer-Joghurt.
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Seit PHP 8.0.0 können
|
|
<link linkend="functions.named-arguments">benannte Argumente</link>
|
|
verwendet werden, um mehrere optionale Parameter zu überspringen.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Korrekte Verwendung von Funktionsparametern mit Vorgabewerten</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function makeyogurt($container = "bowl", $flavour = "raspberry", $style = "Greek")
|
|
{
|
|
return "Making a $container of $flavour $style yogurt.\n";
|
|
}
|
|
|
|
echo makeyogurt(style: "natural");
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
Making a bowl of raspberry natural yogurt.
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Seit PHP 8.0.0 wird die Angabe von obligatorischen Parametern nach
|
|
optionalen Parametern <emphasis>missbilligt</emphasis>. Dies kann im
|
|
Allgemeinen durch das Weglassen des Standardwertes gelöst werden, da er
|
|
nie verwendet wird. Eine Ausnahme von dieser Regel sind Parameter der Form
|
|
<code>Type $param = null</code>, wobei der Standardwert &null; den Typ
|
|
implizit nullbar macht. Diese Verwendung ist seit PHP 8.4.0 veraltet und
|
|
stattdessen sollte ein expliziter
|
|
<link linkend="language.types.declarations.nullable">nullable Typ</link>
|
|
verwendet werden.
|
|
<example>
|
|
<title>Angabe von optionalen Parametern nach obligatorischen Parametern</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
function foo($a = [], $b) {} // Standardwert wird nicht verwendet;
|
|
// seit PHP 8.0.0 veraltet
|
|
function foo($a, $b) {} // Funktionell identisch, aber ohne Veraltet-Hinweis
|
|
|
|
function bar(A $a = null, $b) {} // Seit PHP 8.1.0 ist $a implizit erforderlich
|
|
// (da es vor dem erforderlichen Parameter steht),
|
|
// aber implizit löschbar (seit PHP 8.4.0 veraltet),
|
|
// da der Standardparameterwert null ist
|
|
function bar(?A $a, $b) {} // Empfohlen
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
Seit PHP 7.1.0 wird ein <classname>ArgumentCountError</classname>
|
|
ausgelöst, wenn ein Parameter weggelassen wird, für den kein Standardwert
|
|
angegeben ist; in früheren Versionen löste es eine Warnung aus.
|
|
</simpara>
|
|
</note>
|
|
<note>
|
|
<simpara>
|
|
Parameter, die ein Argument per Verweis erwarten, dürfen einen Standardwert
|
|
haben.
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
|
|
<sect2 xml:id="functions.variable-arg-list">
|
|
<title>Variable Anzahl von Argumenten</title>
|
|
<simpara>
|
|
PHP unterstützt eine variable Anzahl an Argumenten in benutzerdefinierten
|
|
Funktionen durch Verwendung des <literal>...</literal>-Tokens.
|
|
</simpara>
|
|
<para>
|
|
Eine Liste von Parametern kann das Token <literal>...</literal>
|
|
enthalten, um anzugeben, dass die Funktion eine variable Anzahl von
|
|
Argumenten akzeptiert. Die Argumente werden als &array; an die
|
|
entsprechende Variable übergeben:
|
|
<example>
|
|
<title>Verwendung von <literal>...</literal> für den Zugriff auf variable Argumente</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>
|
|
Das Token <literal>...</literal> kann auch dazu verwendet werden, um ein
|
|
<type>&array;</type> oder ein <classname>Traversable</classname>-Objekt als
|
|
Liste von Argumenten zu übergeben:
|
|
<example>
|
|
<title>Verwendung von <literal>...</literal> zur Übergabe einer Argumentenliste</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>
|
|
Die Definition von regulären, positionierten Parametern vor dem
|
|
<literal>...</literal> ist natürlich weiterhin möglich. In einem solchen
|
|
Fall werden dann nur die zusätzlichen Werte, die zu keinem positionierten
|
|
Parameter gehören, in das durch <literal>...</literal> erzeugte Array
|
|
übernommen.
|
|
</para>
|
|
<para>
|
|
Es ist zudem auch möglich, dem <literal>...</literal>-Token eine
|
|
<link linkend="language.types.declarations">Typdeklaration</link>
|
|
voranzustellen. Ist dies der Fall, dann müssen alle Argumente, die von
|
|
<literal>...</literal> erfasst werden, vom entsprechenden Typ sein.
|
|
<example>
|
|
<title>Variable Argumente mit Typdeklaration</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).' days';
|
|
|
|
// Dieser Aufruf wird scheitern, da null keine Instanz von DateInterval ist
|
|
echo total_intervals('d', null);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
3 days
|
|
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>
|
|
Durch ein voran gestelltes <literal>&</literal> ist auch die Übergabe
|
|
von variablen Argumenten
|
|
<link linkend="functions.arguments.by-reference">als Referenz</link>
|
|
möglich.
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 xml:id="functions.named-arguments">
|
|
<title>Benannte Argumente</title>
|
|
<para>
|
|
PHP 8.0.0 führt benannte Argumente als eine Erweiterung der bestehenden
|
|
Positionsparameter ein. Benannte Argumente ermöglichen die Übergabe von
|
|
Argumenten an eine Funktion basierend auf dem Parameternamen und nicht
|
|
auf der Position des Parameters. Das macht die Bedeutung von Argumenten
|
|
selbsterklärend, macht die Argumente unabhängig von der Reihenfolge und
|
|
ermöglicht das willkürliche Überspringen von Standardwerten.
|
|
</para>
|
|
<para>
|
|
Benannte Argumente werden übergeben, indem dem Wert der Parametername
|
|
gefolgt von einem Doppelpunkt vorangestellt wird. Reservierte
|
|
Schlüsselwörter dürfen als Parameternamen verwendet werden. Der
|
|
Parametername muss ein Bezeichner sein; eine dynamische Angabe ist nicht
|
|
erlaubt.
|
|
</para>
|
|
<example>
|
|
<title>Syntax benannter Argumente</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
myFunction(paramName: $value);
|
|
array_foobar(array: $value);
|
|
|
|
// Wird NICHT unterstützt
|
|
function_name($variableStoringParamName: $value);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<example>
|
|
<title>Positionsargumente im Vergleich zu benannten Argumenten</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// Verwendung von Positionsargumenten:
|
|
array_fill(0, 100, 50);
|
|
|
|
// Verwendung von benannten Argumenten:
|
|
array_fill(start_index: 0, count: 100, value: 50);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Die Reihenfolge, in der die benannten Argumente übergeben werden, spielt
|
|
keine Rolle.
|
|
</para>
|
|
<example>
|
|
<title>Das gleiche Beispiel wie oben mit einer anderen Reihenfolge der Parameter</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
array_fill(value: 50, count: 100, start_index: 0);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Benannte Argumente können mit Positionsargumenten kombiniert werden. In
|
|
diesem Fall müssen die benannten Argumente nach den Positionsargumenten
|
|
kommen. Es ist auch möglich, nur einige der optionalen Argumente einer
|
|
Funktion anzugeben, unabhängig von ihrer Reihenfolge.
|
|
</para>
|
|
<example>
|
|
<title>Kombinieren von benannten Argumenten mit Positionsargumenten</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
htmlspecialchars($string, double_encode: false);
|
|
// Ist das Gleiche wie
|
|
htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', false);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Die mehrfache Übergabe eines Arguments an denselben benannten Parameter
|
|
führt zu einer <classname>Error</classname>-Exception.
|
|
</para>
|
|
<example>
|
|
<title>Die mehrfache Übergabe eines Arguments an denselben benannten Parameter erzeugt einen Fehler</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>
|
|
Seit PHP 8.1.0 ist es möglich, benannte Argumente nach dem Entpacken von
|
|
Argumenten zu verwenden. Ein bereits entpacktes Argument
|
|
<emphasis>darf nicht</emphasis> durch einen benanntes Argument
|
|
überschrieben werden.
|
|
</para>
|
|
|
|
<example>
|
|
<title>Verwendung benannter Argumente nach dem Entpacken</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)); // Fataler Fehler. Der benannte Parameter $b überschreibt das vorherige Argument
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.returning-values">
|
|
<title>Rückgabewerte</title>
|
|
<para>
|
|
Werte können mit der optionalen return-Anweisung zurückgegeben werden. Es
|
|
können Variablen jeden Typs zurückgegeben werden, auch Arrays oder
|
|
Objekte. Dies beendet die Funktion sofort und die Kontrolle wird wieder an
|
|
die aufrufende Zeile zurückgegeben. Für weitere Informationen siehe
|
|
<function>return</function>.
|
|
</para>
|
|
<note>
|
|
<para>
|
|
Wird <function>return</function> weggelassen, dann wird der Wert &null;
|
|
zurückgegeben.
|
|
</para>
|
|
</note>
|
|
|
|
<sect2>
|
|
<title>Einsatz von return</title>
|
|
<para>
|
|
<example>
|
|
<title>Einsatz von <function>return</function></title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function quadrat($zahl)
|
|
{
|
|
return $zahl * $zahl;
|
|
}
|
|
echo quadrat(4); // gibt '16' aus.
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Es ist nicht möglich, mehrere Werte von einer Funktion zurückzugeben. Ein
|
|
ähnliches Resultat kann man aber durch die Rückgabe eines Arrays
|
|
erreichen.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Rückgabe mehrerer Werte als Array</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function kleine_zahlen()
|
|
{
|
|
return [0, 1, 2];
|
|
}
|
|
// Bei der Umstrukturierung von Arrays wird jedes Element des Arrays
|
|
// einzeln erfasst.
|
|
[$null, $eins, $zwei] = kleine_zahlen();
|
|
|
|
// Vor 7.1.0 ist die einzige gleichwertige Alternative die Verwendung
|
|
// des list()-Konstrukts
|
|
list($null, $eins, $zwei) = kleine_zahlen();
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Um aus einer Funktion eine Referenz zurückzugeben, muss der
|
|
Referenz-Operator & sowohl in der Funktionsdeklaration, als auch bei
|
|
der Zuweisung des zurückgegebenen Wertes verwendet werden:
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Rückgabe von Referenzen aus Funktionen</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function &returniere_referenz()
|
|
{
|
|
return $einereferenz;
|
|
}
|
|
|
|
$neuereferenz =& returniere_referenz();
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
Weitere Informationen über Referenzen sind im Kapitel
|
|
<link linkend="language.references">Referenzen in PHP</link> zu finden.
|
|
</simpara>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.variable-functions">
|
|
<title>Variablenfunktionen</title>
|
|
<para>
|
|
PHP unterstützt das Konzept der Variablenfunktionen. Wenn Sie an das Ende
|
|
einer Variablen Klammern hängen, versucht PHP eine Funktion aufzurufen,
|
|
deren Name der aktuelle Wert der Variablen ist. Dies kann unter anderem
|
|
für Callbacks, Funktionstabellen usw. genutzt werden.
|
|
</para>
|
|
<para>
|
|
Variablenfunktionen funktionieren nicht mit Sprachkonstrukten wie
|
|
<function>echo</function>, <function>print</function>,
|
|
<function>unset</function>, <function>isset</function>,
|
|
<function>empty</function>, <function>include</function> und
|
|
<function>require</function>. Um diese Konstrukte als Variablenfunktionen
|
|
benutzen zu können, müssen Sie Ihre eigenen Wrapperfunktionen verwenden.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Beispiel für Variablenfunktionen</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
function foo() {
|
|
echo "In foo()<br />\n";
|
|
}
|
|
|
|
function bar($arg = '')
|
|
{
|
|
echo "In bar(); das Argument ist '$arg'.<br />\n";
|
|
}
|
|
|
|
// Dies ist eine Wrapperfunktion für echo
|
|
function echoit($string)
|
|
{
|
|
echo $string;
|
|
}
|
|
|
|
$func = 'foo';
|
|
$func(); // Dies ruft foo() auf
|
|
|
|
$func = 'bar';
|
|
$func('test'); // Dies ruft bar() auf
|
|
|
|
$func = 'echoit';
|
|
$func('test'); // Dies ruft echoit() auf
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Sie können auch die Methode eines Objektes mittels der Variablenfunktionen
|
|
aufrufen.
|
|
<example>
|
|
<title>Beispiel für eine Variablenmethode</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo
|
|
{
|
|
function Variable()
|
|
{
|
|
$name = 'Bar';
|
|
$this->$name(); // Dies ruft die Methode Bar() auf
|
|
}
|
|
|
|
function Bar()
|
|
{
|
|
echo "Das ist Bar";
|
|
}
|
|
}
|
|
|
|
$foo = new Foo();
|
|
$funcname = "Variable";
|
|
$foo->$funcname(); // Dies ruft $foo->Variable() auf
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
Werden statische Methoden aufgerufen, ist der Funktionsaufruf stärker als
|
|
der statische Eigenschaftsoperator:
|
|
<example>
|
|
<title>Beispiel für Variablenmethoden mit statischen Eigenschaften</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo
|
|
{
|
|
static $variable = 'statische Eigenschaft';
|
|
static function Variable()
|
|
{
|
|
echo 'Method Variable called';
|
|
}
|
|
}
|
|
|
|
echo Foo::$variable; // Dies gibt 'statische Eigenschaft' aus. Es bräuchte
|
|
// eine $variable im aktuellen Geltungsbereich.
|
|
$variable = "Variable";
|
|
Foo::$variable(); // Dies ruft $foo->Variable() auf, da $variable im
|
|
// aktuellen Geltungsbereich vorliegt.
|
|
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Komplexe Callables</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
class Foo
|
|
{
|
|
static function bar()
|
|
{
|
|
echo "bar\n";
|
|
}
|
|
function baz()
|
|
{
|
|
echo "baz\n";
|
|
}
|
|
}
|
|
|
|
$func = array("Foo", "bar");
|
|
$func(); // gibt "bar" aus
|
|
$func = array(new Foo, "baz");
|
|
$func(); // gibt "baz" aus
|
|
$func = "Foo::bar";
|
|
$func(); // gibt "bar" aus
|
|
?>
|
|
]]>
|
|
</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">Variable Variablen</link></member>
|
|
</simplelist>
|
|
</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.internal">
|
|
<title>Interne (eingebaute) Funktionen</title>
|
|
<para>
|
|
PHP enthält standardmäßig viele Funktionen und Konstrukte. Außerdem gibt
|
|
es viele Funktionen die voraussetzen, dass bestimmte PHP-Erweiterungen
|
|
einkompiliert wurden, andernfalls erhalten Sie beim Aufruf "undefined
|
|
function"-Fehlermeldungen. Um &zb;
|
|
<link linkend="ref.image">Grafik-Funktionen</link> wie
|
|
<function>imagecreatetruecolor</function> nutzen zu können, müssen Sie PHP
|
|
mit <productname>GD</productname>-Unterstützung kompilieren, oder um
|
|
<function>mysqli_connect</function> nutzen zu können, muss Ihr PHP mit
|
|
<link linkend="book.mysqli">MySQLi</link>-Unterstützung kompiliert sein.
|
|
Viele Kernfunktionen, &zb; die
|
|
<link linkend="ref.strings">String</link>- und
|
|
<link linkend="ref.var">Variablen</link>-Funktionen sind bereits in jeder
|
|
PHP-Version enthalten. Ein Aufruf von <function>phpinfo</function> oder
|
|
<function>get_loaded_extensions</function> zeigt Ihnen, welche
|
|
Erweiterungen in Ihrer PHP-Installation verfügbar sind. Beachten Sie
|
|
außerdem, dass viele Erweiterungen bereits standardmäßig aktiviert sind
|
|
und das PHP-Handbuch nach Erweiterungen unterteilt ist. Weitere
|
|
Informationen zur Einrichtung von PHP finden Sie in den Kapiteln
|
|
<link linkend="configuration">Konfiguration</link>,
|
|
<link linkend="install">Installation</link> und den Kapiteln zu den
|
|
einzelnen Erweiterungen.
|
|
</para>
|
|
<para>
|
|
Wie Funktionsprototypen zu lesen und zu verstehen sind, wird im Kapitel
|
|
<link linkend="about.prototypes">Wie man eine Funktionsdefinition (Prototyp) liest</link>
|
|
erklärt. Es ist wichtig zu erkennen, was eine Funktion zurückgibt und ob
|
|
die übergebenen Parameter verändert werden. So gibt &zb;
|
|
<function>str_replace</function> den bearbeiteten String zurück, während
|
|
<function>usort</function> die übergebene Variable direkt bearbeitet. Jede
|
|
Handbuchseite enthält auch spezifische Informationen zu jeder Funktion, wie
|
|
Informationen über ihre Parameter, die Rückgabewerte sowohl bei Erfolg als
|
|
auch im Fehlerfall, Änderungen des Verhaltens und die Verfügbarkeit. Die
|
|
Kenntnis dieser wichtigen (aber oft subtilen) Unterschiede ist von
|
|
entscheidender Bedeutung für das Schreiben korrekten PHP-Codes.
|
|
</para>
|
|
<note>
|
|
<simpara>
|
|
Wenn Funktionen andere Parameter erhalten als erwartet, &dh; wenn &zb;
|
|
ein <type>&array;</type> übergeben wird, obwohl ein <type>&string;</type>
|
|
erwartet wird, so ist der Rückgabewert undefiniert. In solchen Fällen ist
|
|
es üblich, dass &null; zurückgegeben wird. Dies ist aber nur eine
|
|
Konvention, auf die Sie sich nicht unbedingt verlassen können. Seit
|
|
PHP 8.0.0 sollte in diesem Fall eine
|
|
<classname>TypeError</classname>-Exception ausgelöst werden.
|
|
|
|
</simpara>
|
|
</note>
|
|
<note>
|
|
<para>
|
|
Bei eingebauten Funktionen sind skalare Typen im erzwingenden Modus
|
|
standardmäßig nullbar. Seit PHP 8.1.0 wird in diesem Modus davon
|
|
abgeraten, an eine interne Funktion für einen Parameter, der nicht als
|
|
nullbar deklariert ist, &null; zu übergeben. Um sich dem Verhalten
|
|
benutzerdefinierter Funktionen anzupassen, bei denen skalare Typen
|
|
explizit als nullbar deklariert werden müssen, wird in diesem Fall ein
|
|
entsprechender Missbilligungs-Hinweis ausgegeben.
|
|
</para>
|
|
|
|
<para>
|
|
Zum Beispiel erwartet die Funktion <function>strlen</function>, dass der
|
|
Parameter <literal>$string</literal> eine nicht-nullbare Zeichenkette
|
|
ist. Aus historischen Gründen erlaubt PHP, für diesen Parameter im
|
|
erzwingenden Modus &null; zu übergeben. Der Parameter wird dabei
|
|
stillschweigend in den Typ <type>&string;</type> umgewandelt, was den
|
|
Wert <literal>""</literal> ergibt. Im Gegensatz dazu wird im strikten
|
|
Modus ein <classname>TypeError</classname> ausgegeben.
|
|
</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">die Funktionsreferenz</link></member>
|
|
<member><function>get_extension_funcs</function></member>
|
|
<member><function>dl</function></member>
|
|
</simplelist>
|
|
</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.anonymous">
|
|
<title>Anonyme Funktionen</title>
|
|
<simpara>
|
|
Anonyme Funktionen, auch bekannt als <literal>Closures</literal>,
|
|
ermöglichen es, Funktionen ohne Funktionsnamen zu schreiben. Sie sind am
|
|
nützlichsten als Werte von <type>callable</type>-Parametern, haben aber
|
|
noch viele andere Verwendungsmöglichkeiten.
|
|
</simpara>
|
|
<simpara>
|
|
Anonyme Funktionen werden unter Verwendung der Klasse
|
|
<link linkend="class.closure"><classname>Closure</classname></link>
|
|
implementiert.
|
|
</simpara>
|
|
<example>
|
|
<title>Beispiel für eine anonyme Funktion</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
echo preg_replace_callback('~-([a-z])~', function ($match) {
|
|
return strtoupper($match[1]);
|
|
}, 'hallo-welt');
|
|
// gibt halloWelt aus
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<simpara>
|
|
Closures können auch als Werte von Variablen verwendet werden; PHP
|
|
konvertiert solche Ausdrücke automatisch in Instanzen der internen Klasse
|
|
<classname>Closure</classname>. Die Zuweisung einer Closure an eine
|
|
Variable verwendet die selbe Syntax wie andere Zuweisungen, einschließlich
|
|
des abschließenden Semikolons:
|
|
</simpara>
|
|
<example>
|
|
<title>Beispiel für die Zuweisung einer anonymen Funktion</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$greet = function($name) {
|
|
printf("Hallo %s\r\n", $name);
|
|
};
|
|
|
|
$greet('Welt');
|
|
$greet('PHP');
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<simpara>
|
|
Closures können auch Variablen aus dem Eltern-Gültigkeitsbereich erben.
|
|
Jede solche Variable muss an das <literal>use</literal>-Sprachkonstrukt
|
|
übergeben werden. Von PHP 7.1 an dürfen diese Variablen keine
|
|
&link.superglobals;, <varname>$this</varname> oder Variablen mit dem
|
|
gleichen Name wie ein Parameter sein. Die Deklaration des Rückgabetyps der
|
|
Funktion muss <emphasis>nach</emphasis> der <literal>use</literal>-Klausel
|
|
erfolgen.
|
|
</simpara>
|
|
<example>
|
|
<title>Erben von Variablen aus dem Eltern-Gültigkeitsbereich</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
$message = 'hallo';
|
|
|
|
// Kein "use"
|
|
$example = function () {
|
|
var_dump($message);
|
|
};
|
|
$example();
|
|
|
|
// $message vererben
|
|
$example = function () use ($message) {
|
|
var_dump($message);
|
|
};
|
|
$example();
|
|
|
|
// Der Wert einer geerbten Variable ist der Wert zum Zeitpunkt
|
|
// der Funktionsdefinition, nicht des Funktionsaufrufs
|
|
$message = 'welt';
|
|
$example();
|
|
|
|
// $message wiederherstellen
|
|
$message = 'hallo';
|
|
|
|
// Vererben per Referenz
|
|
$example = function () use (&$message) {
|
|
var_dump($message);
|
|
};
|
|
$example();
|
|
|
|
// Der geänderte Wert im Eltern-Gültigkeitsbereich
|
|
// wird in der aufgerufenen Funktion übernommen
|
|
$message = 'welt';
|
|
$example();
|
|
|
|
// Closures können auch reguläre Argumente akzeptieren
|
|
$example = function ($arg) use ($message) {
|
|
var_dump($arg . ' ' . $message);
|
|
};
|
|
$example("hallo");
|
|
|
|
// Die Deklaration des Rückgabetyps erfolgt nach der use-Klausel
|
|
$example = function () use ($message): string {
|
|
return "hallo $message";
|
|
};
|
|
var_dump($example());
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs.similar;
|
|
<screen>
|
|
<![CDATA[
|
|
Notice: Undefined variable: message in /example.php on line 10
|
|
NULL
|
|
string(5) "hallo"
|
|
string(5) "hallo"
|
|
string(5) "hallo"
|
|
string(4) "welt"
|
|
string(10) "hallo welt"
|
|
string(10) "hallo welt"
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
<para>
|
|
Seit PHP 8.0.0 darf die Liste der geerbten Variablen ein nachgestelltes
|
|
Komma enthalten, das ignoriert wird.
|
|
</para>
|
|
<simpara>
|
|
Das Erben von Variablen aus dem Eltern-Gültigkeitsbereich ist
|
|
<emphasis>nicht</emphasis> das gleiche wie die Verwendung von globalen
|
|
Variablen. Globale Variablen existieren im globalen Gültigkeitsbereich,
|
|
der immer der gleiche ist, unabhängig davon, welche Funktion ausgeführt
|
|
wird. Der Eltern-Gültigkeitsbereich einer Closure ist die Funktion, in der
|
|
die Closure deklariert wurde (nicht notwendigerweise die Funktion, aus der
|
|
sie aufgerufen wurde). Betrachten Sie das folgende Beispiel:
|
|
</simpara>
|
|
<example>
|
|
<title>Closures und Gültigkeitsbereiche</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
// Ein einfacher Einkaufswagen, der eine Liste von hinzugefügten Produkten
|
|
// und die Menge jedes Produkts enthält. Er enthält eine Methode, die den
|
|
// Gesamtpreis der Waren im Einkaufswagen unter Verwendung einer Closure
|
|
// als Callback berechnet.
|
|
class Einkaufswagen
|
|
{
|
|
const PREIS_BUTTER = 1.00;
|
|
const PREIS_MILCH = 3.00;
|
|
const PREIS_EIER = 6.95;
|
|
|
|
protected $produkte = array();
|
|
|
|
public function addiere($produkt, $menge)
|
|
{
|
|
$this->produkte[$produkt] = $menge;
|
|
}
|
|
|
|
public function ermittleMenge($produkt)
|
|
{
|
|
return isset($this->produkte[$produkt]) ? $this->produkte[$produkt] :
|
|
FALSE;
|
|
}
|
|
|
|
public function ermittleGesamt($steuer)
|
|
{
|
|
$gesamt = 0.00;
|
|
|
|
$callback =
|
|
function ($menge, $produkt) use ($steuer, &$gesamt)
|
|
{
|
|
$preisProStueck = constant(__CLASS__ . "::PREIS_" .
|
|
strtoupper($produkt));
|
|
$gesamt += ($preisProStueck * $menge) * ($steuer + 1.0);
|
|
};
|
|
|
|
array_walk($this->produkte, $callback);
|
|
return round($gesamt, 2);
|
|
}
|
|
}
|
|
|
|
$mein_einkaufswagen = new Einkaufswagen;
|
|
|
|
// Lege ein paar Waren in den Einkaufskorb
|
|
$mein_einkaufswagen->addiere('butter', 1);
|
|
$mein_einkaufswagen->addiere('milch', 3);
|
|
$mein_einkaufswagen->addiere('eier', 6);
|
|
|
|
// Gib die Gesamtsumme mit einer Mehrwertsteuer von 5% aus
|
|
print $mein_einkaufswagen->ermittleGesamt(0.05) . "\n";
|
|
// Das Ergebnis ist 54.29
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
<example>
|
|
<title>Automatisches Binden von <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>
|
|
Wird eine anonyme Funktion im Kontext einer Klasse deklariert, so wird
|
|
diese Klasse automatisch an jene gebunden, was <literal>$this</literal>
|
|
innerhalb des Geltungsbereichs verfügbar macht. Ist diese automatische
|
|
Bindung der aktuellen Klasse nicht erwünscht, dann können stattdessen
|
|
<link linkend="functions.anonymous-functions.static">statische anonyme Funktionen</link>
|
|
verwendet werden.
|
|
</para>
|
|
|
|
<sect2 xml:id="functions.anonymous-functions.static">
|
|
<title>Statische anonyme Funktionen</title>
|
|
<para>
|
|
Anonyme Funktionen können statisch deklariert werden. Dies verhindert,
|
|
dass die aktuelle Klasse automatisch an sie gebunden wird. Objekte können
|
|
zur Laufzeit ebenfalls nicht an sie gebunden werden.
|
|
</para>
|
|
<para>
|
|
<example>
|
|
<title>Versuch der Verwendung von <literal>$this</literal> innerhalb einer statischen anonymen Funktion</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>Versuch, ein Objekt an eine statische anonyme Funktion zu binden</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$func = static function() {
|
|
// function body
|
|
};
|
|
$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>
|
|
Closures, die von
|
|
<link linkend="language.oop5.magic">magischen Methoden</link>
|
|
erstellt werden, können benannte Parameter akzeptieren.
|
|
</entry>
|
|
</row>
|
|
<row>
|
|
<entry>7.1.0</entry>
|
|
<entry>
|
|
Anonyme Funktionen dürfen &link.superglobals;,
|
|
<varname>$this</varname> und alle Variablen mit dem gleichen Namen
|
|
wie Parameter nicht als freie Variablen verwenden.
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 role="notes">
|
|
&reftitle.notes;
|
|
<note>
|
|
<simpara>
|
|
Es ist möglich, <function>func_num_args</function>,
|
|
<function>func_get_arg</function> und <function>func_get_args</function>
|
|
innerhalb einer Closure zu verwenden.
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.arrow">
|
|
<title>Pfeilfunktionen</title>
|
|
<simpara>
|
|
Pfeilfunktionen wurden in PHP 7.4 als prägnantere Syntax für
|
|
<link linkend="functions.anonymous">anonyme Funktionen</link> eingeführt.
|
|
</simpara>
|
|
<simpara>
|
|
Sowohl anonyme Funktionen als auch Pfeilfunktionen sind unter Verwendung der
|
|
<link linkend="class.closure"><classname>Closure</classname></link>-Klasse
|
|
implementiert.
|
|
</simpara>
|
|
<simpara>
|
|
Pfeilfunktionen haben die grundsätzliche Form
|
|
<code>fn (argument_list) => expr</code>.
|
|
</simpara>
|
|
<simpara>
|
|
Pfeilfunktionen unterstützen dieselbe Funktionalität wie
|
|
<link linkend="functions.anonymous">anonyme Funktionen</link>,
|
|
außer, dass die Verwendung von Variablen des Eltern-Gültigkeitsbereichs
|
|
immer automatisch erfolgt.
|
|
</simpara>
|
|
<simpara>
|
|
Wenn eine Variable, die im Ausdruck verwendet wird, im
|
|
Eltern-Gültigkeitsbereich definiert ist, wird sie implizit per Wertübergabe
|
|
gebunden. Im folgenden Beispiel verhalten sich die Funktionen
|
|
<varname>$fn1</varname> und <varname>$fn2</varname> auf die gleiche Weise.
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Pfeilfunktionen binden Variablen automatisch per Wertübergabe</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$y = 1;
|
|
|
|
$fn1 = fn($x) => $x + $y;
|
|
// gleichwertig zur Verwendung von $y per Wertübergabe:
|
|
$fn2 = function ($x) use ($y) {
|
|
return $x + $y;
|
|
};
|
|
|
|
var_export($fn1(3));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
&example.outputs;
|
|
<screen>
|
|
<![CDATA[
|
|
4
|
|
]]>
|
|
</screen>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
Dies funktioniert auch, wenn Pfeilfunktionen verschachtelt werden:
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Pfeilfunktionen binden Variablen automatisch per Wertübergabe, selbst wenn sie verschachtelt sind</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$z = 1;
|
|
$fn = fn($x) => fn($y) => $x * $y + $z;
|
|
// gibt 51 aus
|
|
var_export($fn(5)(10));
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<simpara>
|
|
Ähnlich wie bei anonymen Funktion erlaubt die Pfeilfunktionssyntax
|
|
beliebige Funktionssignaturen, einschließlich Parameter- und
|
|
Rückgabetypen, Defaultwerte, variadische Parameter sowie Referenzübergabe
|
|
und -rückgabe. Alle folgenden sind gültige Beispiele von Pfeilfunktionen:
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Beispiele von Pfeilfunktionen</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>
|
|
Pfeilfunktionen verwenden die Wertübergabe-Bindung. Dies entspricht in
|
|
etwa der Verwendung von <code>use($x)</code> für jede Variable
|
|
<varname>$x</varname>, die in der Pfeilfunktion verwendet wird.
|
|
Wertübergabe-Bindung bedeutet, dass es nicht möglich ist, Werte aus dem
|
|
äußeren Geltungsbereich zu ändern.
|
|
<link linkend="functions.anonymous">Anonyme Funktionen</link> können statt
|
|
dessen für Referenzübergabe-Bindungen verwendet werden.
|
|
</simpara>
|
|
<para>
|
|
<example>
|
|
<title>Werte aus dem äußeren Geltungsbereich können nicht durch Pfeilfunktionen geändert werden</title>
|
|
<programlisting role="php">
|
|
<![CDATA[
|
|
<?php
|
|
|
|
$x = 1;
|
|
$fn = fn() => $x++; // hat keine Wirkung
|
|
$fn();
|
|
var_export($x); // gibt 1 aus
|
|
|
|
?>
|
|
]]>
|
|
</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>
|
|
Pfeilfunktionen sind verfügbar.
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 role="notes">
|
|
&reftitle.notes;
|
|
<note>
|
|
<simpara>
|
|
Es ist möglich <function>func_num_args</function>,
|
|
<function>func_get_arg</function> und <function>func_get_args</function>
|
|
innerhalb einer Pfeilfunktion zu verwenden.
|
|
</simpara>
|
|
</note>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="functions.first_class_callable_syntax">
|
|
<title>Callback-Funktionen als Objekte erster Klasse</title>
|
|
|
|
<para>
|
|
Callback-Funktionen als Objekte erster Klasse wurde mit PHP 8.1.0
|
|
eingeführt, um
|
|
<link linkend="functions.anonymous">anonyme Funktionen</link> aus
|
|
<link linkend="language.types.callable" >Callback-Funktionen</link> zu
|
|
erstellen. Sie ersetzt die bestehende Callback-Syntax, die Strings und
|
|
Arrays verwendet. Der Vorteil dieser Syntax ist, dass sie für die
|
|
statische Analyse zugänglich ist und den Gültigkeitsbereich an der Stelle
|
|
verwendet, an der die Callback-Funktion aufgerufen wird.
|
|
</para>
|
|
|
|
<para>
|
|
Die <code>CallableExpr(...)</code>-Syntax wird verwendet, um ein
|
|
<classname>Closure</classname>-Objekt aus einer Callback-Funktion zu
|
|
erzeugen. <code>CallableExpr</code> akzeptiert jeden Ausdruck, der in der
|
|
PHP-Grammatik direkt aufgerufen werden kann:
|
|
<example>
|
|
<title>Einfaches Beispiel für eine Callback-Funktion als Objekt erster Klasse</title>
|
|
<programlisting role="php">
|
|
<;
|
|
$f9 = [Foo::class, 'staticmethod'](...);
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Das <code>...</code> ist keine Auslassung, sondern Teil der Syntax.
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
<code>CallableExpr(...)</code> hat die gleiche Semantik wie
|
|
<methodname>Closure::fromCallable</methodname>. Das heißt, im Gegensatz zu
|
|
Callback-Funktionen, die Strings und Arrays verwenden, wird bei
|
|
<code>CallableExpr(...)</code> der Geltungsbereich an dem Punkt
|
|
berücksichtigt, an dem er erstellt wird:
|
|
<example>
|
|
<title>Vergleich des Anwendungsbereichs von <code>CallableExpr(...)</code> und traditionellen Callback-Funktionen</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();
|
|
// Fatal error: Call to private method Foo::privateMethod() from global scope
|
|
// Dies liegt daran, dass der Aufruf außerhalb von Foo erfolgt und die Sichtbarkeit ab diesem Punkt geprüft wird.
|
|
|
|
class Foo1 {
|
|
public function getPrivateMethod() {
|
|
// Verwendet den Bereich, in dem die Callback-Funktion aufgerufen wird.
|
|
return $this->privateMethod(...); // identisch mit Closure::fromCallable([$this, 'privateMethod']);
|
|
}
|
|
|
|
private function privateMethod() {
|
|
echo __METHOD__, "\n";
|
|
}
|
|
}
|
|
|
|
$foo1 = new Foo1;
|
|
$privateMethod = $foo1->getPrivateMethod();
|
|
$privateMethod(); // Foo1::privateMethod
|
|
?>
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Die Erzeugung von Objekten mit dieser Syntax (&zb;
|
|
<code>new Foo(...)</code>) wird nicht unterstützt, da die
|
|
<code>new Foo()</code>-Syntax nicht als Aufruf betrachtet wird.
|
|
</para>
|
|
</note>
|
|
|
|
<note>
|
|
<para>
|
|
Callback-Funktionen als Objekte erster Klasse können nicht mit dem
|
|
<link linkend="language.oop5.basic.nullsafe">Nullsafe-Operator</link>
|
|
kombiniert werden. Beides führt zu einem Fehler bei der Kompilierung:
|
|
<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
|
|
-->
|