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