PHP

PHP

Tutorial PHP: Funciones y llamada de funciones

Domina la declaración y llamada de funciones en PHP. Aprende sobre parámetros, valores de retorno y mejores prácticas. Curso actualizado a 2023.

Aprende PHP GRATIS y certifícate

Declaración y llamada de funciones

En PHP, una función es un bloque de código que realiza una tarea específica y puede ser reutilizado en diferentes partes del programa. Para declarar una función, se utiliza la palabra clave function seguida del nombre de la función y un par de paréntesis que pueden contener parámetros opcionales.

La sintaxis básica para declarar una función es la siguiente:

function nombreDeLaFuncion() {
    // Código a ejecutar
}

Por ejemplo, si deseamos crear una función que salude al usuario, podríamos declararla de la siguiente manera:

function saludar()
{
    echo "¡Hola, bienvenido!\n";
}

Para llamar o invocar a una función, simplemente escribimos su nombre seguido de paréntesis:

saludar(); // Esto imprimirá: ¡Hola, bienvenido!

Las funciones en PHP ayudan a organizar y estructurar el código, facilitando su mantenimiento y mejorando la reusabilidad. Es importante seguir buenas prácticas al nombrar funciones, utilizando nombres descriptivos y siguiendo una convención consistente, como el uso de lowerCamelCase o snake_case.

Cabe destacar que los nombres de las funciones en PHP no distinguen entre mayúsculas y minúsculas, es decir, la función saludar() es equivalente a SALUDAR(). Sin embargo, por motivos de legibilidad y coherencia, es recomendable mantener un estilo uniforme en el código.

Además, en PHP es posible declarar funciones dentro de estructuras de control, lo que permite crear funciones de manera condicional. Por ejemplo:

$usuarioLogueado = true;

if ($usuarioLogueado) {
    function mostrarPanel()
    {
        echo "Bienvenido al panel de usuario.\n";
    }
}


if ($usuarioLogueado) {
    mostrarPanel(); // Imprime: Bienvenido al panel de usuario.
}

En este caso, la función mostrarPanel() solo será declarada si la variable $usuarioLogueado es verdadera. Sin embargo, es importante usar esta característica con precaución para evitar complicaciones en la estructura del código.

Otra característica de PHP es que permite retornar valores desde una función utilizando la palabra clave return. Aunque este aspecto se profundizará en secciones posteriores, es fundamental entender que return finaliza la ejecución de la función y devuelve un valor al llamante.

Finalmente, es posible definir funciones con parámetros para recibir datos de entrada. Aunque este tema se abordará en detalle más adelante, aquí hay un ejemplo sencillo:

function saludarUsuario($nombre)
{
    echo "¡Hola, $nombre!\n";
}	

saludarUsuario("María"); // Imprime: ¡Hola, María!

Esto demuestra cómo las funciones pueden interactuar con el exterior a través de parámetros, aumentando su flexibilidad y utilidad en diferentes contextos.

Parámetros y argumentos (por valor y referencia)

Las funciones en PHP pueden recibir parámetros que permiten pasar datos desde el contexto de llamada hacia la función. Al invocar una función, los argumentos son los valores que se proporcionan a esos parámetros. Por defecto, PHP pasa los argumentos por valor, pero es posible pasarlos por referencia para modificar directamente la variable original.

Paso de parámetros por valor

Cuando se pasa un argumento por valor, la función recibe una copia del valor original. Esto significa que cualquier modificación realizada dentro de la función no afectará a la variable externa. Este es el comportamiento predeterminado en PHP.

function incrementarPorValor($numero)
{
    $numero += 1;
    echo "Valor dentro de la función: $numero\n";
}

$valor = 5;
incrementar($valor);
echo "Fuera de la función: $valor\n";

Salida:

Dentro de la función: 6
Fuera de la función: 5

En este ejemplo, la variable $valor permanece sin cambios fuera de la función porque se pasó por valor, creando una copia independiente.

Paso de parámetros por referencia

Para que una función pueda modificar la variable original, se debe pasar el argumento por referencia. Esto se logra anteponiendo el símbolo & al nombre del parámetro en la declaración de la función.

function incrementarPorReferencia(&$numero)
{
    $numero += 1;
    echo "Valor dentro de la función: $numero\n";
}

$valor = 5;
incrementar($valor);
echo "Fuera de la función: $valor\n";

Salida:

Dentro de la función: 6
Fuera de la función: 6

Ahora, al pasar $valor por referencia, la función modifica directamente el valor de la variable original.

Consideraciones sobre el uso de referencias

El paso de argumentos por referencia puede ser útil cuando se necesita que la función altere el estado de una variable externa. Sin embargo, es importante usar esta técnica con cautela para mantener la claridad y evitar efectos secundarios no deseados.

Es recomendable utilizar parámetros por referencia en situaciones específicas, como:

  • Funciones que modifican objetos grandes: Evita la duplicación innecesaria de datos, mejorando el rendimiento.
  • Algoritmos que requieren modificar múltiples valores: Permite retornar múltiples resultados modificando los argumentos.

Combinación de parámetros por valor y referencia

Una función puede tener una combinación de parámetros que se pasan por valor y por referencia. Cada parámetro se define de manera independiente en la declaración.

function procesarDatos($dato1, &$dato2)
{
    $dato1 *= 2;
    $dato2 *= 3;
    echo "Dato 1 dentro de la función: $dato1\n";
    echo "Dato 2 dentro de la función: $dato2\n";
}

$a = 4;
$b = 5;
procesarDatos($a, $b);
echo "Dato1 fuera de la función: $a\n";
echo "Dato2 fuera de la función: $b\n";

Salida:

Dato1 dentro de la función: 8
Dato2 dentro de la función: 15
Dato1 fuera de la función: 4
Dato2 fuera de la función: 15

En este caso, $dato1 se pasa por valor y no afecta a $a fuera de la función, mientras que $dato2 se pasa por referencia y modifica a $b.

Parámetros por referencia en funciones anónimas y closures

En PHP, las funciones anónimas y los closures también pueden utilizar parámetros por referencia. Se sigue la misma sintaxis que en las funciones normales.

$duplicar = function(&$numero) {
    $numero *= 2;
};

$valor = 7;
$duplicar($valor);
echo "Valor duplicado: $valor\n";

Salida:

Valor duplicado: 14

Pasar parámetros por referencia en funciones anónimas es especialmente útil en procedimientos que requieren modificar variables en un contexto más amplio.

Mejores prácticas y novedades recientes

Con las mejoras introducidas en las versiones más recientes de PHP, es importante seguir buenas prácticas al usar parámetros por referencia:

  • Claridad del código: Evitar el abuso de referencias puede mejorar la legibilidad y mantenimiento del código.
  • Documentación adecuada: Indicar en los comentarios o documentación cuándo una función modifica sus argumentos.
  • Uso de tipos: Combinado con el tipado estricto, se puede especificar el tipo de datos esperado, mejorando la robustez.

Ejemplo práctico integrando referencias

A continuación, un ejemplo que muestra una función que intercambia los valores de dos variables utilizando parámetros por referencia:

function intercambiar(&$x, &$y)
{
    $temp = $x;
    $x = $y;
    $y = $temp;
}

$a = 10;
$b = 20;
intercambiar($a, $b);
echo "a: $a, b: $b\n";

Salida:

a: 20, b: 10

La función intercambiar() modifica directamente los valores de $a y $b al recibirlos por referencia.

Valores de retorno

En PHP, las funciones pueden devolver valores utilizando la palabra clave return. Esta permite que una función envíe un resultado al contexto desde el cual fue llamada, lo que es fundamental para la reutilización de código y la construcción de aplicaciones modulares.

La sintaxis básica para retornar un valor es:

function obtenerMensaje()
{
    return "¡Bienvenido a PHP!";
}

Al invocar la función, podemos capturar el valor retornado:

$mensaje = obtenerMensaje();
echo $mensaje; // Imprime: ¡Bienvenido a PHP!

Devolución de diferentes tipos de datos

Las funciones en PHP pueden retornar cualquier tipo de dato, como enteros, cadenas de texto, booleanos, arrays, objetos e incluso funciones anónimas.

Retornando tipos escalares

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

$resultado = multiplicar(4, 5);
echo $resultado; // Imprime: 20

En este ejemplo, la función multiplicar() devuelve un entero producto de los parámetros proporcionados.

Retornando arrays

function obtenerDatosUsuario()
{
    return ['nombre' => 'Ana', 'email' => 'ana@example.com'];
}

$datos = obtenerDatosUsuario();
echo $datos['email']; // Imprime: ana@example.com

Aquí, la función devuelve un array asociativo que contiene información del usuario.

Retornando objetos

function crearObjetoUsuario($nombre)
{
    $usuario = new stdClass();
    $usuario->nombre = $nombre;
    return $usuario;
}

$usuario = crearObjetoUsuario('Luis');
echo $usuario->nombre; // Imprime: Luis

La función crearObjetoUsuario() devuelve un objeto con una propiedad asignada.

Efecto de return en el flujo de ejecución

La instrucción return no solo devuelve un valor, sino que también detiene la ejecución de la función. Cualquier código después de return no será ejecutado.

function comprobarNumero($numero)
{
    if ($numero > 0) {
        return "El número es positivo";
    }

    if ($numero < 0) {
        return "El número es negativo";
    }

    return "El número es cero";
}

echo comprobarNumero(-3); // Imprime: El número es negativo

En este ejemplo, la función devuelve un mensaje dependiendo del valor del número y finaliza su ejecución en cada caso.

Funciones sin valor de retorno

Una función no está obligada a devolver un valor. Si no se especifica return, o se utiliza sin un valor, la función devolverá NULL por defecto.

function saludar($nombre) {
    echo "Hola, $nombre";
    // No hay return explícito
}

$saludo = saludar('Carlos'); // Imprime: Hola, Carlos
var_dump($saludo); // Imprime: NULL

La variable $saludo contendrá NULL porque la función saludar() no devuelve ningún valor explícito.

Retorno por referencia

Además de pasar parámetros por referencia, es posible retornar referencias desde una función. Esto se logra colocando un & antes del nombre de la función en su declaración. De esta forma, la función devuelve una referencia a una variable en lugar de su valor.

$contador = 10;

function &obtenerContador()
{
    global $contador;
    return $contador;
}

$contadorReferencia = &obtenerContador();
$contadorReferencia++;
echo $contador; // Imprime: 11

En este caso, $contadorReferencia es una referencia a $contador, por lo que al incrementarla, también se incrementa $contador.

Retorno de funciones anónimas (closures)

Una función puede retornar una función anónima, lo que es útil para crear comportamientos dinámicos.

function generarMultiplicador($factor)
{
    return function ($numero) use ($factor) {
        return $numero * $factor;
    };
}

$duplicar = generarMultiplicador(2);
echo $duplicar(5); // Imprime: 10

La función generarMultiplicador() devuelve un closure que multiplica un número por el factor proporcionado.

Emulación de múltiples valores de retorno

PHP no permite retornar múltiples valores directamente, pero se puede emular este comportamiento retornando un array o un objeto que contenga varios elementos.

Usando arrays

function calcular($a, $b) {
    $suma = $a + $b;
    $producto = $a * $b;
    return [$suma, $producto];
}

list($suma, $producto) = calcular(3, 4);
echo "Suma: $suma, Producto: $producto"; // Imprime: Suma: 7, Producto: 12

Usando objetos

function obtenerCoordenadas()
{
    return (object) ['x' => 10, 'y' => 20];
}

$coordenadas = obtenerCoordenadas();
echo "X: {$coordenadas->x}, Y: {$coordenadas->y}"; // Imprime: X: 10, Y: 20

Al retornar objetos, se pueden manejar resultados más complejos de manera estructurada.

Declaración de tipos de retorno

A partir de PHP 7, se puede declarar el tipo de retorno de una función, lo que permite especificar el tipo de dato esperado.

function obtenerTotal(array $precios): float
{
    return array_sum($precios);
}

$total = obtenerTotal([10.5, 20.75, 15.30]);
echo $total; // Imprime: 46.55

La función obtenerTotal() declara que retornará un float, asegurando que el valor devuelto cumpla con el tipo especificado.

Tipado estricto

Para hacer cumplir estrictamente los tipos de retorno, se puede activar el tipado estricto al inicio del archivo.

declare(strict_types=1);

function dividir(int $dividendo, int $divisor): float {
    return $dividendo / $divisor;
}

$resultado = dividir(10, 3);
echo $resultado; // Imprime: 3.3333333333333

Con strict_types=1, PHP no realizará conversiones automáticas de tipos, lo que mejora la robustez del código.

Buenas prácticas al retornar valores

  • Consistencia en los tipos: Es importante que las funciones retornen el mismo tipo de datos en todas las rutas de ejecución para evitar comportamientos inesperados.
  • Documentación clara: Detallar en los comentarios qué valores y tipos retorna la función facilita el mantenimiento y comprensión del código.
  • Gestión de errores: En lugar de retornar NULL o false ante errores, es recomendable utilizar excepciones para manejar situaciones excepcionales.

Uso de void como tipo de retorno

Desde PHP 7.1, se puede especificar que una función no debe retornar ningún valor utilizando el tipo de retorno void.

function registrarEvento(string $mensaje): void
{
    // Código para registrar el evento
    echo "Evento: $mensaje";
}

registrarEvento("Usuario autenticado");
// Imprime: Evento: Usuario autenticado

Si la función intenta retornar un valor cuando se ha declarado void, PHP generará un error.

Ejemplo práctico: función con tipos de retorno y excepciones

function dividirNumeros(float $numerador, float $denominador): float
{
    if ($denominador === 0.0) {
        throw new Exception('El denominador no puede ser cero');
    }
    return $numerador / $denominador;
}

try {
    $resultado = dividirNumeros(10.0, 0.0);
    echo $resultado;
} catch (Exception $e) {
    echo 'Error: ' . $e->getMessage(); // Imprime: Error: El denominador no puede ser cero
}

En este ejemplo, la función dividirNumeros() declara un retorno de tipo float y utiliza una excepción para manejar el caso de división por cero.

Funciones variables

En PHP, las funciones variables permiten llamar a una función utilizando el valor de una variable como su nombre. Esto significa que si tienes una variable que contiene el nombre de una función, puedes invocar esa función a través de dicha variable. Esta característica aporta flexibilidad al código y es especialmente útil en ciertos patrones de diseño y algoritmos dinámicos.

Por ejemplo, si definimos las siguientes funciones:

function saludo()
{
    echo "¡Hola, bienvenido!";
}

function despedida()
{
    echo "Adiós, hasta pronto.";
}

Podemos utilizar una variable para almacenar el nombre de la función y luego invocarla:

$funcion = 'saludo';
$funcion(); // Imprime: ¡Hola, bienvenido!

En este caso, la variable $funcion contiene la cadena 'saludo', y al usar $funcion() estamos llamando a la función saludo(). Las funciones variables también funcionan con funciones que aceptan parámetros:

function saludarUsuario($nombre) {
    echo "¡Hola, $nombre!";
}

$funcion = 'saludarUsuario';
$funcion('María'); // Imprime: ¡Hola, María!

Es importante destacar que las funciones variables pueden utilizarse con métodos de clases y objetos. Si tenemos una clase con métodos definidos, podemos llamar a sus métodos de forma variable:

class Mensaje
{
    public function bienvenida()
    {
        echo "Bienvenido al sitio.";
    }

    public function despedida()
    {
        echo "Gracias por visitarnos.";
    }
}

$objeto = new Mensaje();
$metodo = 'bienvenida';
$objeto->$metodo(); // Imprime: Bienvenido al sitio.

En este ejemplo, usamos $objeto->$metodo() para invocar el método bienvenida() de la instancia $objeto. La variable $metodo contiene el nombre del método que queremos ejecutar, proporcionando una mayor dinamismo en la llamada de métodos.

Además, es posible utilizar funciones variables con métodos estáticos de clases, empleando la sintaxis :: y almacenando el nombre del método en una variable:

class Utilidades
{
    public static function sumar($a, $b)
    {
        return $a + $b;
    }
}

$metodoEstatico = 'sumar';
$resultado = Utilidades::$metodoEstatico(5, 3); // Llama a Utilidades::sumar(5, 3)
echo "El resultado es: $resultado"; // Imprime: El resultado es: 8

Las funciones variables también pueden manejarse en el contexto de arrays y bucles, lo que permite iterar y llamar a múltiples funciones de manera eficiente:

function incrementar($valor)
{
    return $valor + 1;
}

function duplicar($valor)
{
    return $valor * 2;
}

$funciones = ['incrementar', 'duplicar'];
$numero = 5;

foreach ($funciones as $funcion) {
    $numero = $funcion($numero);
}

echo "El resultado final es: $numero"; // Imprime: El resultado final es: 12

Aquí, el número 5 se incrementa y luego se duplica, aplicando secuencialmente las funciones almacenadas en el array $funciones.

Es fundamental ser cauteloso al utilizar funciones variables para evitar errores y mantener la claridad del código. Si intentamos llamar a una función que no existe, PHP generará un error fatal. Por ello, es recomendable verificar que la función existe antes de invocarla, usando la función function_exists():

$funcion = 'procesarDatos';

if (function_exists($funcion)) {
    $funcion($datos);
} else {
    echo "La función $funcion no existe.";
}

En cuanto a la seguridad, es esencial no permitir que usuarios malintencionados puedan influir en el nombre de las funciones a llamar. Si el nombre de la función proviene de una entrada del usuario, debemos validar o sanitizar el valor antes de utilizarlo:

$funcionSolicitada = "accion";
$funcionesPermitidas = ['iniciar', 'detener'];

if (in_array($funcionSolicitada, $funcionesPermitidas)) {
    $funcionSolicitada();
} else {
    echo "Acción no permitida.";
}

En este ejemplo, solo se permiten las funciones listadas en $funcionesPermitidas, reduciendo el riesgo de ejecución de código no deseado.

Las funciones variables pueden combinarse con variables variables, donde tanto la variable que almacena el nombre de la función como la función misma son variables:

$funcion1 = 'mostrarMensaje';
$mostrarMensaje = function() {
    echo "Este es un mensaje dinámico.";
};

$$funcion1(); // Equivalente a $mostrarMensaje()

Aunque esta técnica es poderosa, su uso puede complicar el seguimiento del flujo del programa, por lo que se debe utilizar con moderación y siempre priorizando la legibilidad del código.

Es posible utilizar funciones variables en combinación con callables, que son referencias a funciones que pueden ser llamadas. Las funciones variables son una forma de callables, pero existen otras, como las funciones anónimas y los métodos de objetos. Las funciones como array_map() y array_filter() aceptan callables como argumentos:

function cuadrado($n)
{
    return $n * $n;
}

$numeros = [1, 2, 3, 4];
$resultados = array_map('cuadrado', $numeros);

print_r($resultados); // Imprime: Array ( [0] => 1 [1] => 4 [2] => 9 [3] => 16 )

En este caso, pasamos el nombre de la función cuadrado como un callable a array_map(), y PHP la llama para cada elemento del array.

Asimismo, al usar funciones variables, es importante entender que no funcionan con ciertas construcciones del lenguaje, como las estructuras de control y determinados operadores. No podemos, por ejemplo, utilizar una función variable para llamar a if, echo o unset, ya que no son funciones, sino construcciones del lenguaje.

En resumen, las funciones variables en PHP permiten una programación más dinámica y flexible al permitir que los programas decidan en tiempo de ejecución qué función ejecutar. Sin embargo, su uso debe equilibrarse con consideraciones de seguridad y mantenibilidad, asegurando que el código sea claro y manejable para otros desarrolladores.

Funciones anónimas y closures

Las funciones anónimas, también conocidas como closures en PHP, son funciones sin nombre que se pueden asignar a variables o pasar como argumentos a otras funciones. Introducidas en PHP 5.3 y mejoradas en versiones posteriores, permiten escribir código más flexible y conciso, facilitando la programación funcional y la manipulación de datos.

Declaración de funciones anónimas

La sintaxis básica de una función anónima es la siguiente:

$variableFuncion = function($parametros) {
    // Código de la función
};

Por ejemplo, para crear una función anónima que sume dos números:

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

$resultado = $suma(3, 4);
echo "El resultado es: $resultado"; // Imprime: El resultado es: 7

En este caso, la función anónima se asigna a la variable $suma, que puede utilizarse como si fuera una función convencional.

Uso de funciones anónimas como argumentos

Las funciones anónimas son especialmente útiles cuando se pasan como argumentos a otras funciones, como en el caso de funciones de orden superior o callbacks.

Por ejemplo, utilizando array_map() para aplicar una función a cada elemento de un array:

$numeros = [1, 2, 3, 4, 5];

$cuadrados = array_map(function ($n) {
    return $n * $n;
}, $numeros);

print_r($cuadrados);
// Imprime: Array ( [0] => 1 [1] => 4 [2] => 9 [3] => 16 [4] => 25 )

El uso de una función anónima permite definir el comportamiento en línea, sin necesidad de crear una función nombrada aparte.

Closures y el uso de use

Las closures en PHP pueden capturar variables del ámbito exterior utilizando la palabra clave use. Esto permite acceder a variables definidas fuera del cuerpo de la función anónima.

Por ejemplo:

$factor = 3;

$multiplicar = function ($numero) use ($factor) {
    return $numero * $factor;
};

echo $multiplicar(5); // Imprime: 15

En este caso, la función anónima utiliza la variable $factor del ámbito exterior gracias a use ($factor). Es importante destacar que las variables capturadas se pasan por valor por defecto.

Captura por referencia

Si se necesita que la función anónima modifique una variable del ámbito exterior, se puede capturar por referencia anteponiendo & a la variable en use.

$contador = 0;

$incrementar = function () use (&$contador) {
    $contador++;
};

$incrementar();
$incrementar();

echo "El contador es: $contador"; // Imprime: El contador es: 2

Al capturar $contador por referencia, los cambios realizados dentro de la función anónima afectan directamente a la variable externa.

Tipado de parámetros y retornos en funciones anónimas

Al igual que en las funciones nombradas, es posible especificar tipos para los parámetros y el valor de retorno en las funciones anónimas. Esto mejora la consistencia y la fiabilidad del código.

$suma = function (int $a, int $b): int {
    return $a + $b;
};

echo $suma(10, 20); // Imprime: 30

Si el tipado estricto está activado mediante declare(strict_types=1);, PHP respetará los tipos definidos y lanzará errores si no se cumplen.

Asignación a propiedades de objetos

Las funciones anónimas pueden asignarse a propiedades de objetos, incluyendo el objeto especial $this dentro de su ámbito si es necesario.

class Saludador
{
    public $mensaje;

    public function __construct($nombre)
    {
        $this->mensaje = function () use ($nombre) {
            echo "Hola, $nombre\n";
        };
    }
}

$saludador = new Saludador('Luis');
($saludador->mensaje)(); // Imprime: Hola, Luis

En este ejemplo, la función anónima accede a la variable $nombre del constructor mediante use, y se asigna a la propiedad $mensaje.

Closures dentro de objetos y ámbito static

Es posible vincular una closure a un objeto específico utilizando el método bindTo(), o al ámbito estático de una clase con Closure::bind().

class Contador
{
    private $cuenta = 0;

    public function obtenerIncrementador()
    {
        return function () {
            $this->cuenta++;
            echo "Cuenta actual: $this->cuenta";
        };
    }
}

$contador = new Contador();
$incrementar = $contador->obtenerIncrementador();
$incrementar(); // Imprime: Cuenta actual: 1

La función anónima tiene acceso a $this y puede interactuar con las propiedades privadas del objeto.

Uso de funciones anónimas en programación funcional

Las funciones anónimas son fundamentales en la programación funcional, permitiendo la creación de funciones de orden superior y facilitando operaciones con colecciones de datos.

Por ejemplo, filtrar un array utilizando array_filter():

$numeros = [1, 2, 3, 4, 5, 6];

$pares = array_filter($numeros, function ($n) {
    return $n % 2 === 0;
});

print_r($pares);
// Imprime: Array ( [1] => 2 [3] => 4 [5] => 6 )

Aquí, la función anónima define el criterio de filtrado, seleccionando los números pares del array.

Funciones anónimas recursivas

Para crear una función anónima recursiva, es necesario asignarla a una variable y referenciarse a sí misma dentro de su definición.

$factorial = function ($n) use (&$factorial) {
    return ($n <= 1) ? 1 : $n * $factorial($n - 1);
};

echo $factorial(5); // Imprime: 120

En este ejemplo, la función anónima calcula el factorial de un número utilizando recursión y capturando por referencia a sí misma con use (&$factorial).

Novedades y mejoras recientes

En versiones recientes de PHP, se han introducido mejoras en las funciones anónimas y closures:

  • Arrow functions: Sintaxis más corta para funciones anónimas simples, introducida en PHP 7.4.
$incrementar = fn($x) => $x + 1;

echo $incrementar(5); // Imprime: 6

Las arrow functions heredan automáticamente las variables del ámbito exterior sin necesidad de use.

  • Funciones anónimas estáticas: Es posible declarar una función anónima como static para evitar acceso al ámbito $this.
$sumar = static function ($a, $b) {
    return $a + $b;
};

Esto mejora el rendimiento y previene acceso no intencional a propiedades de objetos.

Buenas prácticas con funciones anónimas y closures

Legibilidad: Utilizar funciones anónimas cuando mejoren la claridad del código, evitando abusar de ellas en contextos donde una función nombrada sería más apropiada.

Captura de variables: Ser consciente del ámbito de las variables y cómo se capturan en las closures, especialmente al pasar por valor o por referencia.

Seguridad: Evitar exponer datos sensibles a través de closures y ser cuidadoso al acceder a propiedades privadas.

Ejemplo avanzado: Ordenamiento personalizado

Las funciones anónimas pueden utilizarse para definir comportamientos personalizados, como ordenar un array de objetos.

$personas = [
    ['nombre' => 'Ana', 'edad' => 30],
    ['nombre' => 'Luis', 'edad' => 25],
    ['nombre' => 'Carlos', 'edad' => 35],
];

usort($personas, function ($a, $b) {
    return $a['edad'] <=> $b['edad'];
});

print_r($personas);
/* Imprime:
Array
(
    [0] => Array ( [nombre] => Luis   [edad] => 25 )
    [1] => Array ( [nombre] => Ana    [edad] => 30 )
    [2] => Array ( [nombre] => Carlos [edad] => 35 )
)
*/

En este ejemplo, la función anónima define el criterio de comparación para ordenar el array de personas por edad.

Tipado estricto en funciones

El tipado estricto en funciones de PHP permite especificar de forma rigurosa los tipos de datos que las funciones aceptan como parámetros y los tipos que retornan. Esta característica mejora la robustez y fiabilidad del código, asegurando que las funciones reciban y devuelvan los tipos esperados.

Para activar el tipado estricto, se utiliza la declaración declare(strict_types=1); al inicio del archivo PHP:

<?php
declare(strict_types=1);

// Código PHP con tipado estricto

Con strict_types activado, PHP exige que los tipos de los argumentos y los valores de retorno coincidan exactamente con los especificados en las funciones, sin realizar conversiones automáticas o coerción de tipos.

Declaración de tipos en parámetros

En PHP, se pueden especificar tipos para los parámetros de las funciones, lo que se conoce como type hinting. Esto se hace indicando el tipo antes del nombre del parámetro:

function sumar(int $a, int $b)
{
    return $a + $b;
}

En este ejemplo, la función sumar() requiere que ambos parámetros sean de tipo int, es decir, enteros.

Con el tipado estricto activado, si se intenta llamar a la función con argumentos de un tipo distinto, se generará un TypeError:

echo sumar(5, 3);      // Funciona correctamente, imprime: 8
echo sumar(5.5, 3.2);  // Genera TypeError

El segundo llamado provoca un error porque los parámetros son de tipo float, no de tipo int.

Declaración de tipos de retorno

Además de los parámetros, es posible especificar el tipo de retorno de una función, colocando : tipo después de los paréntesis y antes de las llaves de la función:

function obtenerMensaje(): string
{
    return "Bienvenido a PHP";
}

La función obtenerMensaje() declara que retornará un valor de tipo string. Si el valor retornado no coincide con el tipo especificado, se generará un TypeError con el tipado estricto activado.

Tipos escalares y compuestos

PHP permite utilizar tanto tipos escalares como compuestos en el tipado de funciones. Los tipos escalares incluyen:

  • int
  • float
  • string
  • bool

Los tipos compuestos incluyen:

  • array
  • object
  • callable
  • iterable

Por ejemplo:

function procesarDatos(array $datos): bool
{
    if (sizeof($datos) > 0)
        return true;
    else
        return false;
}

echo var_export(procesarDatos([])), "\n";

En este caso, la función procesarDatos() requiere un parámetro de tipo array y devuelve un valor de tipo bool.

Tipos de clase e interfaces

Es posible especificar como tipo una clase o interfaz, lo que obliga a que el argumento sea una instancia de la clase especificada o que implemente la interfaz correspondiente.

class Usuario
{
    private $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function getName(): string
    {
        return $this->name;
    }
}

function enviarNotificacion(Usuario $usuario)
{
    echo "Notificación enviada a: ", $usuario->getName(), "\n";
}

enviarNotificacion(new Usuario("Pepe"));

Aquí, la función enviarNotificacion() espera un objeto de la clase Usuario.

Tipos nullables

Desde PHP 7.1, se pueden utilizar tipos nullables anteponiendo un signo de interrogación ? al tipo. Esto indica que el parámetro o el valor de retorno puede ser del tipo especificado o null.

function obtenerEdad(?int $id): ?int
{
    if ($id === null) {
        return null;
    }
    // Obtener la edad del usuario con el ID dado
    return 30;
}

En este ejemplo, el parámetro $id puede ser int o null, y la función puede retornar un int o null.

Strict typing vs. weak typing

Sin el tipado estricto, PHP realiza conversiones automáticas de tipos, lo que se denomina tipado débil. Por ejemplo:

function multiplicar(int $a, int $b)
{
    return $a * $b;
}

echo multiplicar(5.5, 2.3); // Sin strict_types, imprime: 10

Aunque los argumentos son float, PHP los convierte a int y realiza la multiplicación. Con el tipado estricto activado, este código generaría un TypeError.

Excepciones TypeError

Cuando se viola una declaración de tipo con el tipado estricto activado, PHP lanza una excepción de tipo TypeError. Es posible capturar esta excepción utilizando un bloque try-catch para manejar el error de manera controlada.

declare(strict_types=1);

function dividir(int $dividendo, int $divisor): float
{
    return $dividendo / $divisor;
}

try {
    echo dividir(10, 0);
} catch (DivisionByZeroError $e) {
    echo "No se puede dividir entre cero\n";
} catch (TypeError $e) {
    echo "Error de tipo: " . $e->getMessage(), "\n";
}

En este ejemplo, si se proporcionan tipos incorrectos, el TypeError es capturado y se puede informar al usuario adecuadamente.

Beneficios del tipado estricto

El uso del tipado estricto en funciones aporta múltiples ventajas:

  • Detección temprana de errores: Los errores de tipo se detectan en tiempo de ejecución, facilitando la depuración.
  • Código más predecible: Al conocer los tipos de datos, se reduce la incertidumbre sobre el comportamiento de las funciones.
  • Mejor mantenimiento: Facilita la comprensión del código por parte de otros desarrolladores y mejora la legibilidad.

Tipos union y mixed

Desde PHP 8.0, se introdujeron los tipos union, que permiten especificar que un parámetro o retorno puede ser de múltiples tipos:

function analizar($dato): int|float
{
    if (is_int($dato)) {
        return $dato * 2;
    } elseif (is_float($dato)) {
        return $dato * 1.5;
    }
    throw new InvalidArgumentException("Tipo de dato no soportado");
}

try {
    echo analizar("a");
} catch (InvalidArgumentException $e) {
    echo $e->getMessage(), "\n";
}

La función analizar() puede retornar un int o un float según el tipo de dato procesado.

El tipo especial mixed indica que se acepta cualquier tipo de dato:

function procesar(mixed $entrada): void
{
    echo "Tipo de dato procesado, el tipo es: ", gettype($entrada), "\n";
}

procesar(65);

Consideraciones al usar tipado estricto

  • Coherencia: Es recomendable utilizar el tipado estricto de forma consistente en todo el proyecto.
  • Compatibilidad: Al implementar tipado estricto, se debe verificar que las funciones y métodos heredados o sobreescritos cumplan con las mismas declaraciones de tipos.
  • Documentación: Aunque el tipado estricto mejora la autodocumentación del código, es importante mantener documentación clara y actualizada.

Ejemplo práctico

A continuación, un ejemplo que implementa una función con tipado estricto para calcular el área de un rectángulo:

declare(strict_types=1);

function calcularArea(float $ancho, float $alto): float
{
    return $ancho * $alto;
}

echo "El área es: " . calcularArea(5.2, 3.8); // Imprime: El área es: 19.76

Si se intenta llamar a calcularArea() con argumentos de tipo incorrecto, como cadenas de texto, se generará un TypeError:

echo calcularArea('5', '3'); // Genera TypeError

Notas sobre versiones de PHP

Es importante tener en cuenta que el tipado estricto y algunas de las características mencionadas están disponibles a partir de PHP 7 y versiones posteriores. Al desarrollar aplicaciones, es fundamental verificar la versión de PHP en el entorno de ejecución.

Tipos estáticos y dinámicos

Aunque PHP es un lenguaje de tipado dinámico, el uso de tipado estricto introduce elementos de tipado estático, combinando lo mejor de ambos enfoques. Esto permite escribir código más seguro sin sacrificar la flexibilidad característica de PHP.

Para seguir leyendo hazte Plus

¿Ya eres Plus? Accede a la app

20 % DE DESCUENTO

Plan mensual

19.00 /mes

15.20 € /mes

Precio normal mensual: 19 €
58 % DE DESCUENTO

Plan anual

10.00 /mes

8.00 € /mes

Ahorras 132 € al año
Precio normal anual: 120 €
Aprende PHP GRATIS online

Todas las lecciones de PHP

Accede a todas las lecciones de PHP y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Php

PHP

Introducción Y Entorno

Instalación Y Primer Programa De Php

PHP

Introducción Y Entorno

Tipos De Datos, Variables Y Constantes

PHP

Sintaxis

Operadores Y Expresiones

PHP

Sintaxis

Estructuras De Control

PHP

Sintaxis

Funciones Y Llamada De Funciones

PHP

Sintaxis

Cadenas De Texto Y Manipulación

PHP

Sintaxis

Manejo De Números

PHP

Sintaxis

Manejo De Fechas Y Tiempo

PHP

Sintaxis

Manejo De Arrays

PHP

Sintaxis

Introducción A La Poo En Php

PHP

Programación Orientada A Objetos

Clases Y Objetos

PHP

Programación Orientada A Objetos

Constructores Y Destructores

PHP

Programación Orientada A Objetos

Herencia

PHP

Programación Orientada A Objetos

Encapsulación

PHP

Programación Orientada A Objetos

Polimorfismo

PHP

Programación Orientada A Objetos

Interfaces

PHP

Programación Orientada A Objetos

Traits

PHP

Programación Orientada A Objetos

Namespaces

PHP

Programación Orientada A Objetos

Autoloading De Clases

PHP

Programación Orientada A Objetos

Manejo De Errores Y Excepciones

PHP

Programación Orientada A Objetos

Manejo De Archivos

PHP

Programación Orientada A Objetos

Patrones De Diseño

PHP

Programación Orientada A Objetos

Introducción A Los Formularios En Php

PHP

Formularios

Procesamiento De Datos De Formularios

PHP

Formularios

Manejo De Archivos En Formularios

PHP

Formularios

Redirecciones Y Retroalimentación Al Usuario

PHP

Formularios

Formularios Dinámicos Y Separación De Lógica

PHP

Formularios

Introducción A La Persistencia En Php

PHP

Persistencia

Conexión A Bases De Datos

PHP

Persistencia

Consultas Y Operaciones Crud

PHP

Persistencia

Gestión De Transacciones

PHP

Persistencia

Manejo De Errores Y Excepciones En Base De Datos

PHP

Persistencia

Patrones De Acceso A Datos

PHP

Persistencia

Concepto De Sesiones En Php

PHP

Sesiones Y Cookies

Configuración De Sesiones

PHP

Sesiones Y Cookies

Cookies

PHP

Sesiones Y Cookies

Manejo Avanzado De Sesiones Y Cookies

PHP

Sesiones Y Cookies

Principales Vulnerabilidades En Php

PHP

Seguridad

Seguridad En Formularios Y Entrada De Datos

PHP

Seguridad

Protección Frente A Inyección Sql

PHP

Seguridad

Gestión De Contraseñas Y Cifrado

PHP

Seguridad

Seguridad En Sesiones Y Cookies

PHP

Seguridad

Configuraciones De Php Para Seguridad

PHP

Seguridad

Introducción Al Testing En Php

PHP

Testing

Phpunit

PHP

Testing

Cobertura De Código En Testing

PHP

Testing

Test Doubles (Mocks, Stubs, Fakes, Spies)

PHP

Testing

Pruebas De Integración Y Funcionales

PHP

Testing

Accede GRATIS a PHP y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Entender la declaración básica de funciones en PHP.
  • Definir funciones con y sin parámetros.
  • Diferenciar entre paso de parámetros por valor y por referencia.
  • Conocer el uso de return para retornar valores.
  • Implementar funciones variables y anónimas.