Parámetros y argumentos de funciones

Los parámetros de una función son declarados en la firma de dicha función. Cualquier información puede ser pasada a las funciones mediante la lista de argumentos, la cual es una lista de expresiones delimitadas por comas. Los argumentos son evaluados de izquierda a derecha y el resultado es asignado a los parámetros de la función, antes de que la función sea llamada (evaluación ansiosa).

PHP admite el paso de argumentos por valor (lo predeterminado), el paso por referencia, y valores de argumentos predeterminados. Las Listas de argumentos de longitud variable y Argumentos por nombre también están soportados.

Ejemplo #1 Pasar arrays a funciones

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

Desde PHP 8.0.0, la lista de argumentos de una función puede incluir una coma final, la cual será ignorada. Esto es particularmente útil en casos donde la lista de argumentos es larga o contiene nombres de variables extensos, lo que facilita listar los argumentos de forma vertical.

Ejemplo #2 Lista de argumentos de función con coma final

<?php
function recibe_muchos_args(
$primer_arg,
$segundo_arg,
$un_nombre_de_argumento_muy_largo,
$arg_con_valor_por_defecto = 5,
$otra_vez = 'un string por defecto', // Esta coma final no era permitida antes de PHP 8.0.0.
)
{
// ...
}
?>

Paso de argumentos por referencia

Por defecto, los argumentos de las funciones son pasados por valor (así, si el valor del argumento dentro de la función cambia, este no cambia fuera de la función). Para permitir a una función modificar sus argumentos, éstos deben pasarse por referencia.

Para hacer que un argumento a una función sea siempre pasado por referencia hay que anteponer al nombre del argumento el signo 'et' (&) en la definición de la función:

Ejemplo #3 Paso de parámetros de una función por referencia

<?php
function añadir_algo(&$cadena)
{
$cadena .= 'y algo más.';
}
$cad = 'Esto es un string, ';
añadir_algo($cad);
echo
$cad; // imprime 'Esto es un string, y algo más.'
?>

Es un error pasar una expresión constante como argumento a un parámetro que espera ser pasado por referencia.

Valores de argumentos predeterminados

Una función puede definir valores predeterminados para argumentos usando una sintaxis similar a la asignación de una variable. El valor predeterminado es usado solo cuando no se pasa el argumento del parametro. Nota que cuando se pasa null no se usa el valor predeterminado.

Ejemplo #4 Uso de parámetros predeterminados en funciones

<?php
function hacer_café($tipo = "capuchino")
{
return
"Hacer una taza de $tipo.\n";
}
echo
hacer_café();
echo
hacer_café(null);
echo
hacer_café("espresso");
?>

El resultado del ejemplo sería:

Hacer una taza de capuchino.
Hacer una taza de .
Hacer una taza de espresso.

Los parámetros predeterminados puedes ser valores, arrays, el tipo especial null, y desde PHP 8.1.0, objetos usando la sintaxis new ClassName().

Ejemplo #5 Usar tipos no escalares como valores predeterminados

<?php
function hacer_café($tipos = array("capuchino"), $fabricanteCafé = NULL)
{
$aparato = is_null($fabricanteCafé) ? "las manos" : $fabricanteCafé;
return
"Hacer una taza de ".join(", ", $tipos)." con $aparato.\n";
}
echo
hacer_café();
echo
hacer_café(array("capuchino", "lavazza"), "una tetera");
?>

El resultado del ejemplo sería:

Hacer una taza de capuchino con las manos.
Hacer una taza de capuchino, lavazza con una tetera.

Ejemplo #6 Usando objetos como valores predeterminados (desde PHP 8.1.0)

<?php
class CafeteraNormal {
public function
infusionar() {
return
"Haciendo café.\n";
}
}
class
CafeteraElegante {
public function
infusionar() {
return
"Elaboramos un café delicioso solo para ti.\n";
}
}
function
hacerCafe($coffeeMaker = new CafeteraNormal)
{
return
$coffeeMaker->infusionar();
}
echo
hacerCafe();
echo
hacerCafe(new CafeteraElegante);
?>

El resultado del ejemplo sería:

Haciendo café.
Elaboramos un café delicioso solo para ti.

El valor predeterminado debe ser una expresión constante, no (por ejemplo) una variable, un miembro de una clase o una llamada a una función.

Obsérvese que cuando se emplean argumentos predeterminados, cualquiera de ellos debería estar a la derecha de los argumentos no predeterminados; si no, las cosas pueden no funcionar como se espera. Observe el siguiente ejemplo:

Ejemplo #7 Uso incorrecto de argumentos predeterminados en una función

<?php
function hacerYogur($container = "bol", $flavour)
{
return
"Hacer un $container de yogur $tipo de $flavour.\n";
}

echo
hacerYogur("frambuesa"); // "frambuesa" es $container, no $flavour
?>

El resultado del ejemplo sería:

Fatal error: Uncaught ArgumentCountError: Too few arguments
 to function hacerYogur(), 1 passed ...

Ahora, compare el ejemplo de arriba con este:

Ejemplo #8 Uso correcto de argumentos predeterminados en una función

<?php
function hacerYogur($flavour, $container = "bol")
{
return
"Haciendo un $container de yogur de $flavour.\n";
}

echo
hacerYogur("frambuesa"); // "frambuesa" es $flavour
?>

El resultado del ejemplo sería:

Haciendo un bol de yogur de frambuesa.

Desde PHP 8.0.0, los argumentos con nombre pueden ser usados para omitir varios parámetros opcionales.

Ejemplo #9 Uso correcto de funciones con parámetros opcionales

<?php
function hacerYogur($container = "bol", $flavour = "frambuesa", $style = "griego")
{
return
"Haciendo un $container de yogurt $style de $flavour.\n";
}

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

El resultado del ejemplo sería:

Haciendo un bol de yogurt natural de frambuesa.

Desde PHP 8.0.0, declarar parámetros obligatorios despues de parámetros opcionales se considera obsoleto. Esto normalmente suele resolverse eliminando el valor predeterminado, ya que nunca se utilizará. La única excepción a esta regla son los parámetros de la forma Tipo $param = null, cuando el valor null es el valor predeterminado explicamente de un tipo nullable. Este uso está obsoleto desde PHP 8.4.0, y se debería usar explicatemente un tipo nullable en su lugar.

Ejemplo #10 Declarando parámetros opcionales despues de parámetros obligatorios

<?php

function foo($a = [], $b) {} // No usado por omisión; obsoleto desde PHP 8.0.0
function foo($a, $b) {} // Funcionalidad equivalente, sin notificación de obsolescencia

function bar(A $a = null, $b) {} // Desde PHP 8.1.0, $a es requerido implicitamente
// (porque está antes del requerido),
// pero nullable implicicamente (obsoleto desde PHP 8.4.0),
// porque el valor predeterminado es null
function bar(?A $a, $b) {} // Forma recomendada

?>

Nota: Desde PHP 7.1.0, omitir un parámetro que no especifique un valor predeterminado lanza un ArgumentCountError; en versiones anteriores lanzaba un E_WARNING.

Nota: Los parámetros que esperan los argumentos pasados por referencia pueden tener un valor predeterminado.

Listas de argumentos de longitud variable

PHP tiene soporte para argumentos de longitud variable en funciones definidas por el usuario mediante el uso del símbolo ....

La lista de parámetros puede incluir el símbolo ... para indicar que la función acepta un número variable de argumentos. Los argumentos serán pasados a la variable dada como un array:

Ejemplo #11 Usando ... para acceder a argumentos variables

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

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

El resultado del ejemplo sería:

10

... puede ser usado tambien llamando a funciones para convertir un array, un Traversable o un literal entre la lista de argumentos:

Ejemplo #12 Usando ... para proporcionar los argumentos

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

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

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

El resultado del ejemplo sería:

3
3

Puedes especificar parámetros posicionales normales antes del símbolo .... En este caso, solo los argumentos finales que no coincidan con un argumento posicional serán añadidos al array generado por ....

También es posible añadir una declaración de tipo antes del símbolo .... Si esta está presente, entonces todos los argumentos capturados por ... deben coincidir con el tipo de parámetro indicado.

Ejemplo #13 Argumentos variables con declaración de tipo

<?php
function totalIntervalos($unit, DateInterval ...$intervals) {
$time = 0;
foreach (
$intervals as $interval) {
$time += $interval->$unit;
}
return
$time;
}

$a = new DateInterval('P1D');
$b = new DateInterval('P2D');
echo
totalIntervalos('d', $a, $b).' días';

// Esto fallará, ya que null no es un objeto del tipo DateInterval.
echo totalIntervalos('d', null);
?>

El resultado del ejemplo sería:

3 días
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

Por último, los argumentos variables tambien pueden ser pasados por referencia, usando el simbolo 'et' (&) antes de ....

Argumentos con nombre

PHP 8.0.0 introdujo argumentos con nombre como una extensión de los parámetros posicionales existentes. Los argumentos con nombre permiten pasar argumentos a una función con el nombre del parámetro, en lugar de su posición. Esto hace que el significado del argumento sea autodocumentado, hace que los argumentos sean independientes del orden y permite omitir valores predeterminados de forma arbitraria.

Los argumentos con nombre se pasan anteponiendo el valor con el nombre del parámetro seguido de dos puntos. Se permite el uso de palabras clave reservadas como nombres de parámetros. El nombre del parámetro debe ser un identificador, no se puede especificar dinámicamente

Ejemplo #14 Sintaxis de argumentos con nombre

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

// NO válido.
function_name($variableStoringParamName: $value);
?>

Ejemplo #15 Argumentos posicionales vs argumentos con nombre

<?php
// Usando argumentos posicionales:
array_fill(0, 100, 50);

// Usando argumentos con nombre:
array_fill(start_index: 0, count: 100, value: 50);
?>

No importa el orden en que se pasan los argumentos con nombre.

Ejemplo #16 El mismo ejemplo que el anterior con un orden diferente de parámetros.

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

Los argumentos con nombre se pueden combinar con argumentos posicionales. En este caso, los argumentos con nombre deben ir después de los argumentos posicionales. También es posible especificar solo algunos de los argumentos opcionales de una función, independientemente de su orden.

Ejemplo #17 Combinando argumentos con nombre con argumentos posicionales

<?php
htmlspecialchars
($string, double_encode: false);
// Es lo mismo que
htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', false);
?>

Pasar un argumento al mismo parámetro con nombre varias veces da como resultado una excepción Error.

Ejemplo #18 Se produce un error al pasar un argumento al mismo parámetro con nombre varias veces

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

?>

Desde PHP 8.1.0, es posible utilizar argumentos con nombre después de desempaquetarlos. Un argumento con nombre no debe sobrescribir un argumento ya desempaquetado.

Ejemplo #19 Uso de argumentos con nombre después de desempaquetar

<?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)); // Error. El parámetro con nombre $b sobrescribe el argumento anterior
?>
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
7 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