PHP 8.4.2 Released!

Funktionsparameter und -argumente

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, d. h. mit der sog. eager-Evaluation (dt. eifrige Auswertung).

PHP unterstützt die Weitergabe von Parametern als Werte (das ist der Standard), als Verweise und als Vorgabewerte. Eine variable Anzahl von Parametern und benannte Parameter werden ebenfalls unterstützt.

Beispiel #1 Arrays an Funktionen übergeben

<?php
function nimm_array($eingabe)
{
echo
"$eingabe[0] + $eingabe[1] = ", $eingabe[0]+$eingabe[1];
}
?>

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.

Beispiel #2 Liste von Funktionsparametern mit nachgestelltem Komma

<?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.
)
{
// ...
}
?>

Parameter als Verweise übergeben

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.

Wenn eine Funktion einen Parameter generell als Verweis behandeln soll, setzt man in der Funktionsdefinition ein kaufmännisches Und (&) vor den Parameternamen:

Beispiel #3 Übergeben von Funktionsparametern als Verweis

<?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.'
?>

Es ist ein Fehler, einen konstanten Ausdruck als Argument an einen Parameter zu übergeben, der eigentlich als Referenz übergeben werden müsste.

Vorgabewerte für Parameter

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 nicht der Standardwert zugewiesen wird.

Beispiel #4 Einsatz von Vorgabeparametern in Funktionen

<?php
function machkaffee($typ = "Cappuccino")
{
return
"Ich mache eine Tasse $typ.\n";
}
echo
machkaffee();
echo
machkaffee(null);
echo
machkaffee("Espresso");
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

Ich mache eine Tasse Cappuccino.
Ich mache eine Tasse .
Ich mache eine Tasse Espresso.

Die Standardwerte der Parameter können skalare Werte, Arrays, der spezielle Typ null und seit PHP 8.1.0 auch Objekte sein, die die new ClassName()-Syntax verwenden.

Beispiel #5 Nichtskalare Typen als Vorgabewert

<?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");
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

Ich mache eine Tasse Cappuccino mit der Hand.
Ich mache eine Tasse Cappuccino, Lavazza mit der Teekanne.

Beispiel #6 Verwendung von Objekten als Standardwerte (seit PHP 8.1.0)

<?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);
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

Koche Kaffee.
Bereite einen schönen Kaffee für Dich zu.

Der Vorgabewert muss ein konstanter Ausdruck sein, darf also zum Beispiel keine Variable, keine Eigenschaft einer Klasse und kein Funktionsaufruf sein.

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:

Beispiel #7 Ungültige Verwendung von Funktionsparametern mit Vorgabewerten

<?php
function mach_joghurt($typ = "rechtsdrehendes", $geschmack)
{
return
"Mache einen Becher $typ $geschmack-Joghurt.\n";
}

echo
mach_joghurt("Brombeer"); // "Brombeer" ist $typ, nicht $geschmack
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

Fatal error: Uncaught ArgumentCountError: Too few arguments
 to function makeyogurt(), 1 passed in example.php on line 42

Zum Vergleich mit obigem Beispiel::

Beispiel #8 Richtiger Einsatz von Funktionsparametern mit Vorgabewerten

<?php
function mach_joghurt($geschmack, $typ = "rechtsdrehendes")
{
return
"Mache einen Becher $typ $geschmack-Joghurt.\n";
}

echo
mach_joghurt("Brombeer"); // "Brombeer" ist $geschmack
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

Mache einen Becher rechtsdrehendes Brombeer-Joghurt.

Seit PHP 8.0.0 können benannte Argumente verwendet werden, um mehrere optionale Parameter zu überspringen.

Beispiel #9 Korrekte Verwendung von Funktionsparametern mit Vorgabewerten

<?php
function makeyogurt($container = "bowl", $flavour = "raspberry", $style = "Greek")
{
return
"Making a $container of $flavour $style yogurt.\n";
}

echo
makeyogurt(style: "natural");
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

Making a bowl of raspberry natural yogurt.

Seit PHP 8.0.0 wird die Angabe von obligatorischen Parametern nach optionalen Parametern missbilligt. 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 Type $param = null, wobei der Standardwert null den Typ implizit nullbar macht. Diese Verwendung ist seit PHP 8.4.0 veraltet und stattdessen sollte ein expliziter nullable Typ verwendet werden.

Beispiel #10 Angabe von optionalen Parametern nach obligatorischen Parametern

<?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

?>

Hinweis: Seit PHP 7.1.0 wird ein ArgumentCountError ausgelöst, wenn ein Parameter weggelassen wird, für den kein Standardwert angegeben ist; in früheren Versionen löste es eine Warnung aus.

Hinweis: Parameter, die ein Argument per Verweis erwarten, dürfen einen Standardwert haben.

Variable Anzahl von Argumenten

PHP unterstützt eine variable Anzahl an Argumenten in benutzerdefinierten Funktionen durch Verwendung des ...-Tokens.

Eine Liste von Parametern kann das Token ... enthalten, um anzugeben, dass die Funktion eine variable Anzahl von Argumenten akzeptiert. Die Argumente werden als Array an die entsprechende Variable übergeben:

Beispiel #11 Verwendung von ... für den Zugriff auf variable Argumente

<?php
function sum(...$numbers) {
$acc = 0;
foreach (
$numbers as $n) {
$acc += $n;
}
return
$acc;
}

echo
sum(1, 2, 3, 4);
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

10

Das Token ... kann auch dazu verwendet werden, um ein Array oder ein Traversable-Objekt als Liste von Argumenten zu übergeben:

Beispiel #12 Verwendung von ... zur Übergabe einer Argumentenliste

<?php
function add($a, $b) {
return
$a + $b;
}

echo
add(...[1, 2])."\n";

$a = [1, 2];
echo
add(...$a);
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

3
3

Die Definition von regulären, positionierten Parametern vor dem ... 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 ... erzeugte Array übernommen.

Es ist zudem auch möglich, dem ...-Token eine Typdeklaration voranzustellen. Ist dies der Fall, dann müssen alle Argumente, die von ... erfasst werden, vom entsprechenden Typ sein.

Beispiel #13 Variable Argumente mit Typdeklaration

<?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);
?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

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

Durch ein voran gestelltes & ist auch die Übergabe von variablen Argumenten als Referenz möglich.

Benannte Argumente

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.

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.

Beispiel #14 Syntax benannter Argumente

<?php
myFunction
(paramName: $value);
array_foobar(array: $value);

// Wird NICHT unterstützt
function_name($variableStoringParamName: $value);
?>

Beispiel #15 Positionsargumente im Vergleich zu benannten Argumenten

<?php
// Verwendung von Positionsargumenten:
array_fill(0, 100, 50);

// Verwendung von benannten Argumenten:
array_fill(start_index: 0, count: 100, value: 50);
?>

Die Reihenfolge, in der die benannten Argumente übergeben werden, spielt keine Rolle.

Beispiel #16 Das gleiche Beispiel wie oben mit einer anderen Reihenfolge der Parameter

<?php
array_fill
(value: 50, count: 100, start_index: 0);
?>

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.

Beispiel #17 Kombinieren von benannten Argumenten mit Positionsargumenten

<?php
htmlspecialchars
($string, double_encode: false);
// Ist das Gleiche wie
htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', false);
?>

Die mehrfache Übergabe eines Arguments an denselben benannten Parameter führt zu einer Error-Exception.

Beispiel #18 Die mehrfache Übergabe eines Arguments an denselben benannten Parameter erzeugt einen Fehler

<?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

?>

Seit PHP 8.1.0 ist es möglich, benannte Argumente nach dem Entpacken von Argumenten zu verwenden. Ein bereits entpacktes Argument darf nicht durch einen benanntes Argument überschrieben werden.

Beispiel #19 Verwendung benannter Argumente nach dem Entpacken

<?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
?>
add a note

User Contributed Notes 8 notes

up
131
php at richardneill dot org
9 years ago
To experiment on performance of pass-by-reference and pass-by-value, I used this script. Conclusions are below.

#!/usr/bin/php
<?php
function sum($array,$max){ //For Reference, use: "&$array"
$sum=0;
for (
$i=0; $i<2; $i++){
#$array[$i]++; //Uncomment this line to modify the array within the function.
$sum += $array[$i];
}
return (
$sum);
}

$max = 1E7 //10 M data points.
$data = range(0,$max,1);

$start = microtime(true);
for (
$x = 0 ; $x < 100; $x++){
$sum = sum($data, $max);
}
$end = microtime(true);
echo
"Time: ".($end - $start)." s\n";

/* Run times:
# PASS BY MODIFIED? Time
- ------- --------- ----
1 value no 56 us
2 reference no 58 us

3 valuue yes 129 s
4 reference yes 66 us

Conclusions:

1. PHP is already smart about zero-copy / copy-on-write. A function call does NOT copy the data unless it needs to; the data is
only copied on write. That's why #1 and #2 take similar times, whereas #3 takes 2 million times longer than #4.
[You never need to use &$array to ask the compiler to do a zero-copy optimisation; it can work that out for itself.]

2. You do use &$array to tell the compiler "it is OK for the function to over-write my argument in place, I don't need the original
any more." This can make a huge difference to performance when we have large amounts of memory to copy.
(This is the only way it is done in C, arrays are always passed as pointers)

3. The other use of & is as a way to specify where data should be *returned*. (e.g. as used by exec() ).
(This is a C-like way of passing pointers for outputs, whereas PHP functions normally return complex types, or multiple answers
in an array)

4. It's unhelpful that only the function definition has &. The caller should have it, at least as syntactic sugar. Otherwise
it leads to unreadable code: because the person reading the function call doesn't expect it to pass by reference. At the moment,
it's necessary to write a by-reference function call with a comment, thus:
$sum = sum($data,$max); //warning, $data passed by reference, and may be modified.

5. Sometimes, pass by reference could be at the choice of the caller, NOT the function definitition. PHP doesn't allow it, but it
would be meaningful for the caller to decide to pass data in as a reference. i.e. "I'm done with the variable, it's OK to stomp
on it in memory".
*/
?>
up
13
Simmo at 9000 dot 000
2 years ago
For anyone just getting started with php or searching, for an understanding, on what this page describes as a "... token" in Variable-length arguments:
https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list
<?php

func
($a, ...$b)

?>
The 3 dots, or elipsis, or "...", or dot dot dot is sometimes called the "spread operator" in other languages.

As this is only used in function arguments, it is probably not technically an true operator in PHP. (As of 8.1 at least?).

(With having an difficult to search for name like "... token", I hope this note helps someone).
up
18
LilyWhite
3 years ago
It is worth noting that you can use functions as function arguments

<?php
function run($op, $a, $b) {
return
$op($a, $b);
}

$add = function($a, $b) {
return
$a + $b;
};

$mul = function($a, $b) {
return
$a * $b;
};

echo
run($add, 1, 2), "\n";
echo
run($mul, 1, 2);
?>

Output:
3
2
up
16
Hayley Watson
7 years ago
There are fewer restrictions on using ... to supply multiple arguments to a function call than there are on using it to declare a variadic parameter in the function declaration. In particular, it can be used more than once to unpack arguments, provided that all such uses come after any positional arguments.

<?php

$array1
= [[1],[2],[3]];
$array2 = [4];
$array3 = [[5],[6],[7]];

$result = array_merge(...$array1); // Legal, of course: $result == [1,2,3];
$result = array_merge($array2, ...$array1); // $result == [4,1,2,3]
$result = array_merge(...$array1, $array2); // Fatal error: Cannot use positional argument after argument unpacking.
$result = array_merge(...$array1, ...$array3); // Legal! $result == [1,2,3,5,6,7]
?>

The Right Thing for the error case above would be for $result==[1,2,3,4], but this isn't yet (v7.1.8) supported.
up
28
gabriel at figdice dot org
8 years ago
A function's argument that is an object, will have its properties modified by the function although you don't need to pass it by reference.

<?php
$x
= new stdClass();
$x->prop = 1;

function
f ( $o ) // Notice the absence of &
{
$o->prop ++;
}

f($x);

echo
$x->prop; // shows: 2
?>

This is different for arrays:

<?php
$y
= [ 'prop' => 1 ];

function
g( $a )
{
$a['prop'] ++;
echo
$a['prop']; // shows: 2
}

g($y);

echo
$y['prop']; // shows: 1
?>
up
12
boan dot web at outlook dot com
6 years ago
Quote:

"The declaration can be made to accept NULL values if the default value of the parameter is set to NULL."

But you can do this (PHP 7.1+):

<?php
function foo(?string $bar) {
//...
}

foo(); // Fatal error
foo(null); // Okay
foo('Hello world'); // Okay
?>
up
4
Luna
2 years ago
When using named arguments and adding default values only to some of the arguments, the arguments with default values must be specified at the end or otherwise PHP throws an error:

<?php

function test1($a, $c, $b = 2)
{
return
$a + $b + $c;
}

function
test2($a, $b = 2, $c)
{
return
$a + $b + $c;
}

echo
test1(a: 1, c: 3)."\n"; // Works
echo test2(a: 1, c: 3)."\n"; // ArgumentCountError: Argument #2 ($b) not passed

?>

I assume that this happens because internally PHP rewrites the calls to something like test1(1, 3) and test2(1, , 3). The first call is valid, but the second obviously isn't.
up
5
Hayley Watson
7 years ago
If you use ... in a function's parameter list, you can use it only once for obvious reasons. Less obvious is that it has to be on the LAST parameter; as the manual puts it: "You may specify normal positional arguments BEFORE the ... token. (emphasis mine).

<?php
function variadic($first, ...$most, $last)
{
/*etc.*/}

variadic(1, 2, 3, 4, 5);
?>
results in a fatal error, even though it looks like the Thing To Do™ would be to set $first to 1, $most to [2, 3, 4], and $last to 5.
To Top