mirror of
https://github.com/php/doc-es.git
synced 2026-03-23 23:12:09 +01:00
1778 lines
48 KiB
XML
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>&</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>&</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 & 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) => 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">
|
|
<;
|
|
$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
|
|
-->
|