1
0
mirror of https://github.com/php/doc-es.git synced 2026-03-23 23:12:09 +01:00
Files
archived-doc-es/language/functions.xml
Marcos Porto Mariño 668fe72be5 Fix white-space (#312)
2025-11-13 00:12:48 +01:00

1778 lines
48 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: dd87866772c31671146ff778140dc0955c55005c Maintainer: PhilDaiguille Status: ready -->
<!-- Reviewed: no -->
<chapter xml:id="language.functions" xmlns="http://docbook.org/ns/docbook">
<title>Las funciones</title>
<sect1 xml:id="functions.user-defined">
<title>Las funciones definidas por el usuario</title>
<para>
Una función se define utilizando el operador <literal>function</literal>,
un nombre, una lista de argumentos (que pueden estar vacíos) separados por comas
(<literal>,</literal>) entre paréntesis, seguidos del cuerpo de
la función entre llaves, como sigue:
</para>
<example>
<title>Declaración de una nueva función llamada <literal>foo</literal></title>
<programlisting role="php">
<![CDATA[
<?php
function foo($arg_1, $arg_2, /* ..., */ $arg_n)
{
echo "Ejemplo de función.\n";
return $retval;
}
?>
]]>
</programlisting>
</example>
<note>
<para>
A partir de PHP 8.0.0, la lista de argumentos puede tener una coma final:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
function foo($arg_1, $arg_2,) { }
?>
]]>
</programlisting>
</informalexample>
</para>
</note>
<simpara>
Todo código PHP válido puede aparecer dentro del cuerpo de una función, incluso otras
funciones y definiciones de
<link linkend="language.oop5.basic.class">clase</link>.
</simpara>
<para>
Los nombres de funciones siguen las mismas reglas que otros identificadores en PHP.
Un nombre de función válido comienza con una letra o un subrayado, seguido
por cualquier número de letras, números o subrayados.
Estas reglas pueden representarse mediante la expresión regular siguiente:
<code>^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>
</para>
&tip.userlandnaming;
<simpara>
Las funciones no necesitan ser definidas antes de ser utilizadas,
<emphasis>SALVO</emphasis> cuando una función es definida
condicionalmente, como se muestra en los dos ejemplos siguientes.
</simpara>
<para>
Cuando una función es definida de manera condicional, como en
los ejemplos siguientes, su definición debe <emphasis>preceder</emphasis>
su utilización.
</para>
<para>
<example>
<title>Funciones condicionales</title>
<programlisting role="php">
<![CDATA[
<?php
$makefoo = true;
/* No es posible llamar a foo() aquí,
ya que esta función no existe.
Pero podemos utilizar bar() */
bar();
if ($makefoo) {
function foo()
{
echo "No existo hasta que el programa pase por aquí.\n";
}
}
/* Ahora podemos llamar a foo()
ya que $makefoo se evalúa como verdadero */
if ($makefoo) foo();
function bar()
{
echo "Existo desde el principio del programa.\n";
}
?>
]]>
</programlisting>
</example>
</para>
<para>
<example>
<title>Funciones dentro de otra función</title>
<programlisting role="php">
<![CDATA[
<?php
function foo()
{
function bar()
{
echo "No existo hasta que foo() sea llamado.\n";
}
}
/* No es posible llamar a bar() aquí
ya que no existe. */
foo();
/* Ahora podemos llamar a bar(),
ya que la utilización de foo() la ha hecho
accesible. */
bar();
?>
]]>
</programlisting>
</example>
</para>
<para>
Todas las funciones y clases en PHP tienen un ámbito global - pueden ser llamadas
fuera de una función si han sido definidas dentro y viceversa.
</para>
<simpara>
PHP no soporta la sobrecarga, la destrucción y la redefinición de
funciones ya declaradas.
</simpara>
<note>
<simpara>
Los nombres de funciones son insensibles a mayúsculas/minúsculas para los caracteres ASCII
<literal>A</literal> a <literal>Z</literal>,
y es generalmente aceptado que las funciones deben
ser llamadas con el nombre utilizado en su declaración,
incluyendo la mayúscula/minúscula.
</simpara>
</note>
<simpara>
Las <link linkend="functions.variable-arg-list">
listas de argumentos de función variables</link> y los
<link linkend="functions.arguments.default">valores por defecto
de argumentos</link> son soportados: ver
las funciones de referencia que son
<function>func_num_args</function>,
<function>func_get_arg</function>, y
<function>func_get_args</function> para más información.
</simpara>
<para>
Es posible llamar a funciones recursivas en PHP.
<example>
<title>Funciones recursivas</title>
<programlisting role="php">
<![CDATA[
<?php
function recursion($a)
{
if ($a < 20) {
echo "$a\n";
recursion($a + 1);
}
}
?>
]]>
</programlisting>
</example>
<note>
<simpara>
Las llamadas de métodos/funciones recursivas con 100-200 niveles de
recursividad pueden llenar la pila y así, terminar el script actual.
Se debe notar que una recursión infinita es considerada un error de
programación.
</simpara>
</note>
</para>
</sect1>
<sect1 xml:id="functions.arguments">
<title>Parámetros y argumentos de función</title>
<simpara>
Los parámetros de la función se declaran en la firma de la función.
Información puede ser pasada a
una función utilizando una lista de argumentos, donde cada
expresión está separada por una coma. Los argumentos serán
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 efectivamente llamada
(evaluación <emphasis>inmediata</emphasis>).
</simpara>
<!-- Note: this paragraph feels like it should be moved to the syntax part? -->
<para>
PHP soporta el paso de argumentos por valor (comportamiento por defecto), <link
linkend="functions.arguments.by-reference">el paso por referencia</link>, y <link
linkend="functions.arguments.default">valores por defecto de argumentos</link>.
Una <link linkend="functions.variable-arg-list">lista de argumentos variable</link>,
así como los <link linkend="functions.named-arguments">Argumentos Nombrados</link>
también son soportados.
</para>
<note>
<para>
A partir de PHP 7.3.0, es posible tener una coma final en la lista de argumentos
para las llamadas de función:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$v = foo(
$arg_1,
$arg_2,
);
?>
]]>
</programlisting>
</informalexample>
</para>
</note>
<para>
A partir de PHP 8.0.0, la lista de argumentos de función puede incluir una
coma final, que será ignorada. Esto es particularmente útil en
los casos donde la lista de argumentos es larga o contiene nombres de variables
largos, haciendo práctico listar los argumentos verticalmente.
</para>
<example>
<title>Lista de parámetros de función con una coma final</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', // Esta coma final no era permitida antes de 8.0.0.
)
{
// ...
}
?>
]]>
</programlisting>
</example>
<sect2 xml:id="functions.arguments.by-reference">
<title>Paso de argumentos por referencia</title>
<simpara>
Por defecto, los argumentos son pasados
a la función por valor (también, cambiar el valor de un argumento en la función no
cambia su valor fuera de la función). Si se desea que las funciones
puedan cambiar los valores de los argumentos, estos argumentos deben ser pasados por referencia.
</simpara>
<para>
Si se desea que un argumento sea siempre pasado
por referencia, se puede añadir un '<literal>&amp;</literal>'
delante del parámetro en la declaración de la función:
</para>
<para>
<example>
<title>Paso de argumentos de función por referencia</title>
<programlisting role="php">
<![CDATA[
<?php
function add_some_extra(&$string)
{
$string .= ', y un poco más.';
}
$str = 'Esto es un string';
add_some_extra($str);
echo $str; // Muestra: 'Esto es un string, y un poco más.'
?>
]]>
</programlisting>
</example>
</para>
<para>
Es incorrecto pasar una expresión constante como argumento a un parámetro
que espera ser pasado por referencia.
</para>
</sect2>
<sect2 xml:id="functions.arguments.default">
<title>Valores por defecto de parámetros</title>
<para>
Una función puede definir valores por defecto para los parámetros utilizando una sintaxis similar
a la de la asignación de una variable. El valor por defecto es utilizado únicamente cuando el argumento del parámetro no es
pasado. Tenga en cuenta que pasar &null; no <emphasis>define</emphasis>
el valor por defecto.
</para>
<para>
<example>
<title>Valor por defecto de argumentos de funciones</title>
<programlisting role="php">
<![CDATA[
<?php
function servir_cafe ($type = "cappuccino")
{
return "Servir un $type.\n";
}
echo servir_cafe();
echo servir_cafe(null);
echo servir_cafe("espresso");
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Servir un cappuccino.
Servir un .
Servir un espresso.
]]>
</screen>
</example>
</para>
<para>
Los valores por defecto de parámetros pueden ser valores escalares,
&array;s, el tipo especial &null;, y a partir de PHP 8.1.0,
objetos utilizando la sintaxis <link linkend="language.oop5.basic.new">new ClassName()</link>.
</para>
<para>
<example>
<title>Uso de tipo no escalar como valor por defecto</title>
<programlisting role="php">
<![CDATA[
<?php
function servir_cafe($types = array("cappuccino"), $coffeeMaker = NULL)
{
$device = is_null($coffeeMaker) ? "las manos" : $coffeeMaker;
return "Preparación de una taza de ".join(", ", $types)." con $device.\n";
}
echo servir_cafe();
echo servir_cafe(array("cappuccino", "lavazza"), "una cafetera");
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Preparación de una taza de cappuccino con las manos.
Preparación de una taza de cappuccino, lavazza con una cafetera.
]]>
</screen>
</example>
</para>
<para>
<example>
<title>Uso de objetos como valores por defecto (a partir de PHP 8.1.0)</title>
<programlisting role="php">
<![CDATA[
<?php
class DefaultCoffeeMaker {
public function brew() {
return 'Hacer café.\n';
}
}
class FancyCoffeeMaker {
public function brew() {
return 'Crear un café bonito solo para usted.\n';
}
}
function makecoffee($coffeeMaker = new DefaultCoffeeMaker)
{
return $coffeeMaker->brew();
}
echo makecoffee();
echo makecoffee(new FancyCoffeeMaker);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Hacer café.
Crear un café bonito solo para usted.
]]>
</screen>
</example>
</para>
<simpara>
El valor por defecto de un argumento debe
ser obligatoriamente una constante, y no puede ser
ni una variable, ni un miembro de clase, ni una llamada de función.
</simpara>
<para>
Tenga en cuenta que todos los parámetros opcionales deben ser especificados después de los
parámetros obligatorios, de lo contrario no pueden ser omitidos en las llamadas.
Considere el siguiente código:
</para>
<para>
<example>
<title>Uso incorrecto de parámetros de función por defecto</title>
<programlisting role="php">
<![CDATA[
<?php
function hacerunyaourt ($container = "bol", $flavour)
{
return "Preparar un $container de yogur a la $flavour.\n";
}
echo hacerunyaourt("framboise"); // "framboise" es $container, no $flavour
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Fatal error: Uncaught ArgumentCountError: Too few arguments
to function hacerunyaourt(), 1 passed in example.php on line 42
]]>
</screen>
</example>
</para>
<para>
Ahora comparemos el ejemplo anterior con el siguiente:
</para>
<para>
<example>
<title>Uso correcto de parámetros de función por defecto</title>
<programlisting role="php">
<![CDATA[
<?php
function hacerunyaourt ($flavour, $container = "bol")
{
return "Preparar un $container de yogur a la $flavour.\n";
}
echo hacerunyaourt ("framboise"); // "framboise" es $flavour
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Preparar un bol de yogur a la framboise.
]]>
</screen>
</example>
</para>
<para>
A partir de PHP 8.0.0, los <link linkend="functions.named-arguments">argumentos nombrados</link>
pueden ser utilizados para pasar por alto varios parámetros opcionales.
</para>
<para>
<example>
<title>Uso correcto de parámetros de función por defecto</title>
<programlisting role="php">
<![CDATA[
<?php
function hacerunyaourt($container = "bol", $flavour = "framboise", $style = "Grec")
{
return "Preparar un $container de yogur $style a la $flavour.\n";
}
echo hacerunyaourt(style: "natural");
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Preparar un bol de yogur natural a la framboise.
]]>
</screen>
</example>
</para>
<para>
A partir de PHP 8.0.0, declarar parámetros obligatorios después de argumentos opcionales es <emphasis>obsoleto</emphasis>.
Este problema puede generalmente resolverse abandonando el valor por defecto, ya que nunca será utilizado.
Una excepción a esta regla concierne a los parámetros de la forma <code>Type $param = null</code>,
donde el &null; por defecto hace el tipo implicitamente nullable.
Este uso está deprecado desde PHP 8.4.0, y un
<link linkend="language.types.declarations.nullable">tipo nullable</link>
explícito debe ser utilizado en su lugar.
<example>
<title>Declaración de parámetros opcionales después de parámetros obligatorios</title>
<programlisting role="php">
<![CDATA[
<?php
function foo($a = [], $b) {} // Valor por defecto no utilizado; desaconsejado a partir de PHP 8.0.0
function foo($a, $b) {} // Funcionalmente equivalente, sin advertencia de deprecación
function bar(A $a = null, $b) {} // A partir de PHP 8.1.0, $a es implicitamente requerido
// (ya que precede a un parámetro requerido),
// pero implicitamente nullable (desaconsejado a partir de PHP 8.4.0),
// ya que el valor por defecto del parámetro es null
function bar(?A $a, $b) {} // Recomendado
?>
]]>
</programlisting>
</example>
</para>
<note>
<simpara>
A partir de PHP 7.1.0, la omisión de un parámetro que no especifica un valor por defecto lanza
un <classname>ArgumentCountError</classname>;
en versiones anteriores, esto generaba una advertencia.
</simpara>
</note>
<note>
<simpara>
Los argumentos pasados por referencia pueden tener
un valor por defecto.
</simpara>
</note>
</sect2>
<sect2 xml:id="functions.variable-arg-list">
<title>Lista de argumentos de número variable</title>
<simpara>
PHP soporta argumentos de número variable en las
funciones definidas por el usuario utilizando el token
<literal>...</literal>.
</simpara>
<para>
La lista de argumentos puede incluir el
token <literal>...</literal> para indicar que esta función acepta
un número variable de argumentos. Los argumentos serán pasados a la variable
proporcionada en forma de un &array;:
<example>
<title>Uso de <literal>...</literal> para acceder a argumentos variables</title>
<programlisting role="php">
<![CDATA[
<?php
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
10
]]>
</screen>
</example>
</para>
<para>
<literal>...</literal> también puede ser utilizado durante las llamadas de
funciones para extraer el &array; o la variable
<classname>Traversable</classname> o el literal en la lista de argumentos:
<example>
<title>Uso de <literal>...</literal> para proporcionar argumentos</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>
Se pueden especificar parámetros clásicos antes de la palabra clave
<literal>...</literal>. En este caso, solo los argumentos finales
que no coincidan con un argumento clásico serán añadidos
al array generado por <literal>...</literal>.
</para>
<para>
También es posible añadir una
<link linkend="language.types.declarations">declaración de tipo</link>
antes del token <literal>...</literal>. Si esto está presente,
entonces todos los argumentos capturados por <literal>...</literal>
deben coincidir con el tipo de parámetro.
<example>
<title>Conversión de argumentos variables</title>
<programlisting role="php">
<![CDATA[
<?php
function total_intervals($unit, DateInterval ...$intervals) {
$time = 0;
foreach ($intervals as $interval) {
$time += $interval->$unit;
}
return $time;
}
$a = new DateInterval('P1D');
$b = new DateInterval('P2D');
echo total_intervals('d', $a, $b).' días';
// Esto fallará, ya que null no es un objeto DateInterval.
echo total_intervals('d', null);
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
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
]]>
</screen>
</example>
</para>
<para>
Finalmente, se pueden pasar argumentos variables
<link linkend="functions.arguments.by-reference">por referencia</link>
prefijando la palabra clave <literal>...</literal> con un comercial
(<literal>&amp;</literal>).
</para>
</sect2>
<sect2 xml:id="functions.named-arguments">
<title>Argumentos Nombrados</title>
<para>
PHP 8.0.0 introduce los argumentos nombrados como extensión a los parámetros
posicionales existentes. Los argumentos nombrados permiten pasar los
argumentos a una función basándose en el nombre del parámetro, en lugar de
la posición del parámetro. Esto documenta automáticamente el significado
del argumento, hace que el orden de los argumentos sea independiente y permite
omitir valores por defecto arbitrariamente.
</para>
<para>
Los argumentos nombrados se pasan prefijando el valor con el nombre del
parámetro seguido de dos puntos. Utilizar palabras clave reservadas como
nombre de parámetro está permitido. El nombre del parámetro debe ser un identificador,
no se permite especificarlo de forma dinámica.
</para>
<example>
<title>Sintaxis de argumentos nombrados</title>
<programlisting role="php">
<![CDATA[
<?php
myFunction(paramName: $value);
array_foobar(array: $value);
// NO soportado.
function_name($variableStoringParamName: $value);
?>
]]>
</programlisting>
</example>
<example>
<title>Argumentos posicionales comparados con argumentos nombrados</title>
<programlisting role="php">
<![CDATA[
<?php
// Utilizando argumentos posicionales:
array_fill(0, 100, 50);
// Utilizando argumentos nombrados:
array_fill(start_index: 0, count: 100, value: 50);
?>
]]>
</programlisting>
</example>
<para>
El orden en el que se pasan los argumentos nombrados no importa.
</para>
<example>
<title>Mismo ejemplo que arriba, pero con un orden de parámetro diferente</title>
<programlisting role="php">
<![CDATA[
<?php
array_fill(value: 50, count: 100, start_index: 0);
?>
]]>
</programlisting>
</example>
<para>
Los argumentos nombrados pueden ser combinados con los argumentos posicionales.
En este caso, los argumentos nombrados deben venir 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.
</para>
<example>
<title>Combinar argumentos nombrados con argumentos posicionales</title>
<programlisting role="php">
<![CDATA[
<?php
htmlspecialchars($string, double_encode: false);
// Igual que
htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', false);
?>
]]>
</programlisting>
</example>
<para>
Pasar el mismo argumento varias veces resulta en una
<classname>Error</classname> excepción.
</para>
<example>
<title>Error lanzado cuando un argumento es pasado varias veces al mismo parámetro nombrado</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>
A partir de PHP 8.1.0, es posible utilizar argumentos nombrados después de descomponer los argumentos.
Un argumento nombrado <emphasis>no debe</emphasis> sobrescribir un argumento ya descompuesto.
</para>
<example>
<title>Utilizar argumentos nombrados después de la descomposición</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)); // Error fatal. El parámetro nombrado $b sobrescribe el argumento anterior.
?>
]]>
</programlisting>
</example>
</sect2>
</sect1>
<sect1 xml:id="functions.returning-values">
<title>Los valores de retorno</title>
<para>
Los valores son devueltos utilizando una
instrucción de retorno opcional. Todos los tipos de variables
pueden ser devueltos, incluyendo arrays y objetos. Esto hace
que la función termine su ejecución inmediatamente y pase
el control a la línea llamante. Ver
<function>return</function>
para más información.
</para>
<note>
<para>
Si <function>return</function>
es omitido, el valor &null; será devuelto.
</para>
</note>
<sect2>
<title>Uso de return</title>
<para>
<example>
<title>Uso de <function>return</function></title>
<programlisting role="php">
<![CDATA[
<?php
function cuadrado($num)
{
return $num * $num;
}
echo cuadrado(4); // Muestra '16'
?>
]]>
</programlisting>
</example>
</para>
<para>
Una función no puede devolver varios valores a la vez, pero
puede obtenerse el mismo resultado devolviendo un array.
</para>
<para>
<example>
<title>Devolver un array de una función</title>
<programlisting role="php">
<![CDATA[
<?php
function pequeño_numero()
{
return [0, 1, 2];
}
// La descomposición de un array recolectará cada miembro del array individualmente
[$zero, $one, $two] = pequeño_numero();
// Anterior a PHP 7.1, la única alternativa equivalente es utilizando la estructura de lenguaje list()
list ($zero, $un, $deux) = pequeño_numero();
?>
]]>
</programlisting>
</example>
</para>
<para>
Para devolver una referencia de una función, utilice
el operador &amp; tanto en la declaración de la función como en
la asignación del valor de retorno.
</para>
<para>
<example>
<title>Devolver una referencia de una función</title>
<programlisting role="php">
<![CDATA[
<?php
function &devolver_referencia()
{
return $uneref;
}
$newref =& devolver_referencia();
?>
]]>
</programlisting>
</example>
</para>
<simpara>
Para más información sobre referencias, véase <link
linkend="language.references">la explicación sobre referencias</link>.
</simpara>
</sect2>
</sect1>
<sect1 xml:id="functions.variable-functions">
<title>Funciones variables</title>
<para>
PHP soporta el concepto de funciones variables.
Esto significa que si el nombre de una variable es seguido de paréntesis,
PHP buscará una función de mismo nombre y intentará ejecutarla.
Esto puede servir, entre otras cosas, para hacer funciones de devolución de llamada, tablas de funciones...
</para>
<para>
Las funciones variables no pueden funcionar con los
elementos de lenguaje como los
<function>echo</function>, <function>print</function>,
<function>unset</function>, <function>isset</function>,
<function>empty</function>, <function>include</function>,
<function>require</function> etc. Se debe utilizar
su propia gestión de funciones para utilizar uno de estos elementos
de lenguaje como funciones variables.
</para>
<para>
<example>
<title>Ejemplo de función variable</title>
<programlisting role="php">
<![CDATA[
<?php
function foo() {
echo "en foo()<br />\n";
}
function bar($arg = '')
{
echo "En bar(); el argumento era '$arg'.<br />\n";
}
// Esto es una función desviada de echo
function echoit($string)
{
echo $string;
}
$func = 'foo';
$func(); // Llama a foo()
$func = 'bar';
$func('test'); // Llama a bar()
$func = 'echoit';
$func('test'); // Llama a echoit()
?>
]]>
</programlisting>
</example>
</para>
<para>
También se pueden llamar los métodos de un objeto utilizando el sistema de
funciones variables.
<example>
<title>Ejemplo de método variable</title>
<programlisting role="php">
<![CDATA[
<?php
class Foo
{
function Variable()
{
$name = 'Bar';
$this->$name(); // Llama al método Bar()
}
function Bar()
{
echo "Es Bar";
}
}
$foo = new Foo();
$funcname = "Variable";
$foo->$funcname(); // Llama a $foo->Variable()
?>
]]>
</programlisting>
</example>
</para>
<para>
Al llamar a métodos estáticos, la llamada de función es mejor que
el operador de propiedad estática:
<example>
<title>Ejemplo de método variable con propiedades estáticas</title>
<programlisting role="php">
<![CDATA[
<?php
class Foo
{
static $variable = 'propiedad estática';
static function Variable()
{
echo 'Método Variable llamado';
}
}
echo Foo::$variable; // Esto muestra 'propiedad estática'. Es necesario tener una $variable en el contexto.
$variable = "Variable";
Foo::$variable(); // Esto llama a $foo->Variable(), leyendo así la $variable desde el contexto.
?>
]]>
</programlisting>
</example>
</para>
<para>
<example>
<title>callables complejo</title>
<programlisting role="php">
<![CDATA[
<?php
class Foo
{
static function bar()
{
echo "bar\n";
}
function baz()
{
echo "baz\n";
}
}
$func = array("Foo", "bar");
$func(); // Muestra "bar"
$func = array(new Foo, "baz");
$func(); // Muestra "baz"
$func = "Foo::bar";
$func(); // Muestra "bar"
]]>
</programlisting>
</example>
</para>
<sect2 role="seealso">
&reftitle.seealso;
<para>
<simplelist>
<member><function>is_callable</function></member>
<member><function>call_user_func</function></member>
<member><function>function_exists</function></member>
<member><link linkend="language.variables.variable">Las variables variables</link></member>
</simplelist>
</para>
</sect2>
</sect1>
<sect1 xml:id="functions.internal">
<title>Funciones internas</title>
<para>
PHP dispone de numerosas funciones y estructuras estándar. También
hay funciones que requieren extensiones específicas de PHP, sin
las cuales se obtendrá el error fatal
<literal>undefined function</literal>. Por ejemplo, para utilizar las
funciones <link linkend="ref.image">de imágenes</link>,
tales como <function>imagecreatetruecolor</function>, se necesitará el
soporte de <productname>GD</productname> en PHP. O bien, para utilizar
<function>mysqli_connect</function>, se necesitará la extensión
<link linkend="book.mysqli">MySQLi</link>. Hay funciones básicas que
están incluidas en todas las versiones de PHP, tales como las funciones de
<link linkend="ref.strings">strings</link> y las funciones de <link linkend="ref.var">variables</link>. Utilice
<function>phpinfo</function> o
<function>get_loaded_extensions</function> para saber qué extensiones están
compiladas con su PHP. Tenga en cuenta también que
numerosas extensiones están activadas por defecto, y que el manual de PHP está
compartimentado por extensión. Véase los capítulos de
<link linkend="configuration">configuración</link>,
<link linkend="install">instalación</link> así como los
detalles particulares de cada extensión, para saber cómo ponerlas en marcha.
</para>
<para>
Leer y comprender el prototipo de una función se describe en el apéndice
<link linkend="about.prototypes">Cómo leer la definición de una
función (prototipo)</link>.
Es importante comprender qué devuelve una función, o si una
función trabaja directamente sobre el valor de los parámetros proporcionados. Por
ejemplo, <function>str_replace</function> devolverá una string modificada,
mientras que <function>usort</function> trabaja directamente sobre la variable
pasada como parámetro. Cada página del manual tiene información específica
sobre cada función, como el número de parámetros, las evoluciones de
especificaciones, los valores devueltos en caso de éxito o fracaso, y la
disponibilidad según las versiones. Conocer bien estas diferencias,
a veces sutiles, es crucial para programar bien en PHP.
</para>
<note>
<simpara>
Si los parámetros dados a una función no son correctos, como pasar un &array; cuando se espera un &string;, el valor devuelto
de la función es indefinido. En este caso, la función devolverá la mayoría de las veces un valor &null; pero esto es solo una convención y
no puede ser considerado como una certeza.
A partir de PHP 8.0.0, normalmente se lanza una excepción <classname>TypeError</classname>
en este caso.
</simpara>
</note>
<note>
<para>
En modo coercitivo, los tipos escalares de las funciones internas son nullables por defecto.
A partir de PHP 8.1.0, pasar &null; a un parámetro de función interna que no está declarado
como nullable está deprecado y emite una advertencia de deprecación en modo coercitivo para alinearse
con el comportamiento de las funciones definidas por el usuario, donde los tipos escalares deben
ser marcados como nullables explícitamente.
</para>
<para>
Por ejemplo, la función <function>strlen</function> espera que el parámetro <literal>$string</literal>
sea de tipo &string; y no &null;.
Por razones históricas, PHP permite pasar &null; para este parámetro en modo coercitivo.
El parámetro es entonces convertido implícitamente a <type>string</type>, resultando en un valor <literal>""</literal>.
Tenga en cuenta que una <classname>TypeError</classname> es emitida en modo estricto.
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
var_dump(strlen(null));
// "Deprecated: Passing null to parameter #1 ($string) of type string is deprecated" a partir de PHP 8.1.0
// int(0)
var_dump(str_contains("foobar", null));
// "Deprecated: Passing null to parameter #2 ($needle) of type string is deprecated" a partir de 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">el índice de funciones</link></member>
<member><function>get_extension_funcs</function></member>
<member><function>dl</function></member>
</simplelist>
</para>
</sect2>
</sect1>
<sect1 xml:id="functions.anonymous">
<title>Funciones anónimas</title>
<simpara>
Las funciones anónimas, también llamadas closures o <literal>closures</literal>
permiten la creación de funciones sin especificar su nombre.
Son particularmente útiles como funciones de devolución de llamada <type>callable</type>,
pero su utilización no se limita a este único uso.
</simpara>
<simpara>
Las funciones anónimas están implementadas utilizando la clase
<link linkend="class.closure"><classname>Closure</classname></link>.
</simpara>
<example>
<title>Ejemplos con funciones anónimas</title>
<programlisting role="php">
<![CDATA[
<?php
echo preg_replace_callback('~-([a-z])~', function ($match) {
return strtoupper($match[1]);
}, 'hola-mundo');
?>
]]>
</programlisting>
</example>
<simpara>
Las funciones anónimas también pueden ser utilizadas como valores de
variables. PHP convertirá automáticamente estas expresiones
en objetos <classname>Closure</classname>. Asignar un closure
a una variable es lo mismo que una asignación clásica,
incluyendo el punto y coma final.
</simpara>
<example>
<title>Asignación de función anónima a una variable</title>
<programlisting role="php">
<![CDATA[
<?php
$saludo = function($name) {
printf("Hola %s\r\n", $name);
};
$saludo('Mundo');
$saludo('PHP');
?>
]]>
</programlisting>
</example>
<simpara>
Las funciones anónimas pueden heredar variables del contexto de su
padre. Estas variables deben entonces ser pasadas en la construcción
de lenguaje <literal>use</literal>.
A partir de PHP 7.1, estas variables no deben incluir &link.superglobals;,
<varname>$this</varname>, o variables con el mismo nombre que un
parámetro. Una declaración de tipo de retorno para la función debe ser colocada
<emphasis>después</emphasis> de la cláusula <literal>use</literal>.
</simpara>
<example>
<title>Herencia de variable desde el contexto padre</title>
<programlisting role="php">
<![CDATA[
<?php
$message = 'hola';
// Sin "use"
$example = function () {
var_dump($message);
};
$example();
// Hereda $message
$example = function () use ($message) {
var_dump($message);
};
$example();
// El valor de la variable heredada es definido cuando la función es
// definida no cuando es llamada
$message = 'mundo';
$example();
// Reinicialización de la variable message
$message = 'hola';
// Herencia por referencia
$example = function () use (&$message) {
var_dump($message);
};
$example();
// El cambio de valor en el contexto padre es reflejado al
// llamar a la función.
$message = 'mundo';
$example();
// Las funciones anónimas también aceptan argumentos clásicos
$example = function ($arg) use ($message) {
var_dump($arg . ' ' . $message);
};
$example("hola");
// Declaración de tipo de retorno viene después de la cláusula use
$example = function () use ($message): string {
return "hola $message";
};
var_dump($example());
?>
]]>
</programlisting>
&example.outputs.similar;
<screen>
<![CDATA[
Notice: Undefined variable: message in /example.php on line 6
NULL
string(5) "hola"
string(5) "hola"
string(5) "hola"
string(5) "mundo"
string(11) "hola mundo"
string(11) "hola mundo"
]]>
</screen>
</example>
<para>
A partir de PHP 8.0.0, la lista de variables heredadas del contexto puede
incluir una coma final, que será ignorada.
</para>
<simpara>
La herencia del contexto padre
<emphasis>no es</emphasis> lo mismo que las variables
del entorno global. Las variables globales existen en el
contexto global, que es el mismo, independientemente de la función que
se esté ejecutando. El contexto padre de una función anónima es la función
en la que la función fue declarada (no necesariamente la que llama). Véase el ejemplo siguiente:
</simpara>
<example>
<title>Funciones anónimas y contexto</title>
<programlisting role="php">
<![CDATA[
<?php
// Un carrito de compra simple, que contiene una lista de productos
// seleccionados y la cantidad deseada de cada producto. Incluye
// un método que calcula el precio total de los elementos en el carrito
// utilizando una función de devolución de llamada anónima.
class Carrito
{
const PRECIO_MANTEQUILLA = 1.00;
const PRECIO_LECHE = 3.00;
const PRECIO_HUEVO = 6.95;
protected $products = array();
public function add($product, $quantity)
{
$this->products[$product] = $quantity;
}
public function getQuantity($product)
{
return isset($this->products[$product]) ? $this->products[$product] :
FALSE;
}
public function getTotal($tax)
{
$total = 0.00;
$callback =
function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRECIO_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
array_walk($this->products, $callback);
return round($total, 2);
}
}
$mi_carrito = new Carrito;
// Añadir elementos al carrito
$mi_carrito->add('mantequilla', 1);
$mi_carrito->add('leche', 3);
$mi_carrito->add('huevo', 6);
// Mostrar el precio con 5.5% de IVA
print $mi_carrito->getTotal(0.055) . "\n";
// El resultado será 54.29
?>
]]>
</programlisting>
</example>
<example>
<title>Vinculación automática de <literal>$this</literal></title>
<programlisting role="php">
<![CDATA[
<?php
class Test
{
public function testing()
{
return function() {
var_dump($this);
};
}
}
$object = new Test;
$function = $object->testing();
$function();
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
object(Test)#1 (0) {
}
]]>
</screen>
</example>
<para>
Cuando se declara en el contexto de una clase, la clase
actual es automáticamente vinculada, haciéndola <literal>$this</literal>
disponible en el contexto de la función. Si este vínculo automático de
la clase actual no es deseado, entonces las
<link linkend="functions.anonymous-functions.static">funciones anónimas
estáticas</link> pueden ser utilizadas en su lugar.
</para>
<sect2 xml:id="functions.anonymous-functions.static">
<title>Las funciones anónimas estáticas</title>
<para>
Las funciones anónimas pueden ser declaradas estáticamente.
Esto permite no vincular automáticamente la clase actual a la función.
Los objetos también pueden no ser vinculados durante la ejecución.
</para>
<para>
<example>
<title>Intento de uso de <literal>$this</literal> en una función anónima estática</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>Intento de vinculación de un objeto a una función anónima estática</title>
<programlisting role="php">
<![CDATA[
<?php
$func = static function() {
// cuerpo de la función
};
$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>
Los closures creados a partir de las <link linkend="language.oop5.magic">métodos
mágicos</link> pueden aceptar argumentos nombrados.
</entry>
</row>
<row>
<entry>7.1.0</entry>
<entry>
Las funciones anónimas no pueden cerrarse sobre &link.superglobals;,
<varname>$this</varname>, o cualquier variable con el mismo nombre que un
parámetro.
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</sect2>
<sect2 role="notes">
&reftitle.notes;
<note>
<simpara>
Es posible utilizar las funciones <function>func_num_args</function>,
<function>func_get_arg</function> y <function>func_get_args</function>
en una función anónima.
</simpara>
</note>
</sect2>
</sect1>
<sect1 xml:id="functions.arrow">
<title>Función Flecha</title>
<simpara>
Las funciones flecha fueron introducidas en PHP 7.4 como sintaxis
más concisa para las
<link linkend="functions.anonymous">funciones anónimas</link>.
</simpara>
<simpara>
Las funciones anónimas como las funciones flecha están implementadas utilizando la clase
<link linkend="class.closure"><classname>Closure</classname></link>.
</simpara>
<simpara>
Las funciones flecha tienen la forma básica
<code>fn (argument_list) =&gt; expr</code>.
</simpara>
<simpara>
Las funciones flecha soportan las mismas características que las
<link linkend="functions.anonymous">funciones anónimas</link>,
excepto que el uso de variables del ámbito padre es automático.
</simpara>
<simpara>
Cuando una variable utilizada en la expresión está definida en el ámbito
padre, será capturada implícitamente por valor.
En el siguiente ejemplo, las funciones <varname>$fn1</varname> y
<varname>$fn2</varname> se comportan de manera idéntica.
</simpara>
<para>
<example>
<title>Las funciones flecha capturan variables por valor automáticamente</title>
<programlisting role="php">
<![CDATA[
<?php
$y = 1;
$fn1 = fn($x) => $x + $y;
// equivalente a usar $y por valor:
$fn2 = function ($x) use ($y) {
return $x + $y;
};
var_export($fn1(3));
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
4
]]>
</screen>
</example>
</para>
<simpara>
Esto también funciona si las funciones flecha están anidadas:
</simpara>
<para>
<example>
<title>Las funciones flecha capturan variables por valor automáticamente, incluso anidadas</title>
<programlisting role="php">
<![CDATA[
<?php
$z = 1;
$fn = fn($x) => fn($y) => $x * $y + $z;
// Muestra 51
var_export($fn(5)(10));
?>
]]>
</programlisting>
</example>
</para>
<simpara>
Similar a las funciones anónimas,
la sintaxis de las funciones flecha permite firmas de función arbitrarias,
esto incluye tipos de parámetros y de retorno, valor por defecto, variable,
así como el paso y retorno por referencia.
Todos los siguientes ejemplos son funciones flecha válidas:
</simpara>
<para>
<example>
<title>Ejemplos de funciones flecha</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>
Las funciones flecha vinculan variables por valor.
Esto es aproximadamente equivalente a hacer un <code>use($x)</code> para
cada variable <varname>$x</varname> utilizada dentro de la función
flecha.
Un vínculo por valor significa que no es posible modificar un
valor del ámbito exterior.
<link linkend="functions.anonymous">Las funciones anónimas</link>
pueden ser utilizadas en su lugar para vínculos por referencia.
</simpara>
<para>
<example>
<title>
Valores del ámbito exterior no pueden ser modificados por funciones flecha
</title>
<programlisting role="php">
<![CDATA[
<?php
$x = 1;
$fn = fn() => $x++; // No tiene efecto
$fn();
var_export($x); // Muestra 1
?>
]]>
</programlisting>
</example>
</para>
<sect2 role="changelog">
&reftitle.changelog;
<para>
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>&Version;</entry>
<entry>&Description;</entry>
</row>
</thead>
<tbody>
<row>
<entry>7.4.0</entry>
<entry>
Las funciones flecha están ahora disponibles.
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</sect2>
<sect2 role="notes">
&reftitle.notes;
<note>
<simpara>
Es posible utilizar <function>func_num_args</function>,
<function>func_get_arg</function>, y <function>func_get_args</function>
desde dentro de una función flecha.
</simpara>
</note>
</sect2>
</sect1>
<sect1 xml:id="functions.first_class_callable_syntax">
<title>Sintaxis callable de primera clase</title>
<para>
La sintaxis de callable de primera clase se introduce a partir de PHP 8.1.0,
como una manera de crear <link linkend="functions.anonymous">funciones anónimas</link>
desde <link linkend="language.types.callable">callables</link>.
Reemplaza la sintaxis de callables existente que utiliza cadenas y arrays.
La ventaja de esta sintaxis es que es accesible al análisis estático
y utiliza el ámbito del punto donde el callable es adquirido.
</para>
<para>
La sintaxis <code>CallableExpr(...)</code> se utiliza para crear un objeto
<classname>Closure</classname> desde el callable.
<code>CallableExpr</code> acepta cualquier expresión que pueda ser directamente
llamada en la gramática de PHP:
<example>
<title>Sintaxis callable de primera clase básica</title>
<programlisting role="php">
<![CDATA[
<?php
class Foo {
public function method() {}
public static function staticmethod() {}
public function __invoke() {}
}
$obj = new Foo();
$classStr = 'Foo';
$methodStr = 'method';
$staticmethodStr = 'staticmethod';
$f1 = strlen(...);
$f2 = $obj(...); // objeto invocable
$f3 = $obj->method(...);
$f4 = $obj->$methodStr(...);
$f5 = Foo::staticmethod(...);
$f6 = $classStr::$staticmethodStr(...);
// callable tradicional usando string, array
$f7 = 'strlen'(...);
$f8 = [$obj, 'method'](...);
$f9 = [Foo::class, 'staticmethod'](...);
?>
]]>
</programlisting>
</example>
</para>
<note>
<para>
Los <code>...</code> forman parte de la sintaxis y no son una omisión.
</para>
</note>
<para>
<code>CallableExpr(...)</code> tiene las mismas semánticas que <methodname>Closure::fromCallable</methodname>.
Es decir, a diferencia de los callables que utilizan cadenas y arrays,
<code>CallableExpr(...)</code> respeta el ámbito del punto donde es creado:
<example>
<title>Comparación de ámbito de <code>CallableExpr(...)</code> y callables tradicionales</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
// Esto es porque la llamada se realiza fuera de Foo y la visibilidad será verificada desde este punto.
class Foo1 {
public function getPrivateMethod() {
// Usa el ámbito donde el callable es adquirido.
return $this->privateMethod(...); // idéntico a Closure::fromCallable([$this, 'privateMethod']);
}
private function privateMethod() {
echo __METHOD__, "\n";
}
}
$foo1 = new Foo1;
$privateMethod = $foo1->getPrivateMethod();
$privateMethod(); // Foo1::privateMethod
?>
]]>
</programlisting>
</example>
</para>
<note>
<para>
La creación de objetos con esta sintaxis (por ejemplo <code>new Foo(...)</code>) no es soportada,
ya que la sintaxis <code>new Foo()</code> no es considerada una llamada.
</para>
</note>
<note>
<para>
La sintaxis de callable de primera clase no puede ser combinada con
el <link linkend="language.oop5.basic.nullsafe">operador nullsafe</link>.
Los dos casos siguientes resultan en un error de compilación:
<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
-->