Lección 21 de 75 12 min de lectura

Parámetros y Argumentos

Los parámetros y argumentos son fundamentales para crear funciones flexibles y reutilizables. Entender cómo funcionan te permite escribir código más limpio y aprovechar al máximo las capacidades de PHP moderno.

Parámetros vs Argumentos

Aunque a menudo se usan indistintamente, hay una diferencia técnica:

  • Parámetros: las variables que defines en la declaración de la función
  • Argumentos: los valores que pasas al llamar a la función
PHP
<?php

declare(strict_types=1);

// $nombre y $edad son PARÁMETROS
function saludar(string $nombre, int $edad): void
{
    echo "Hola, $nombre. Tienes $edad años.\n";
}

// 'Ana' y 25 son ARGUMENTOS
saludar('Ana', 25);

Tipado de parámetros

PHP moderno permite (y recomienda) tipar todos los parámetros. Esto mejora la documentación del código y previene errores:

PHP
<?php

declare(strict_types=1);

// Tipos escalares
function procesar(string $texto, int $numero, float $decimal, bool $activo): void
{
    echo "texto: $texto, numero: $numero, decimal: $decimal\n";
    echo 'activo: ' . ($activo ? 'sí' : 'no') . "\n";
}

procesar('hola', 42, 3.14, true);

// Tipo array
function listarNombres(array $nombres): void
{
    foreach ($nombres as $nombre) {
        echo "- $nombre\n";
    }
}

listarNombres(['Ana', 'Luis', 'Eva']);

// Tipo callable (funciones como parámetros)
function ejecutar(callable $callback, int $valor): int
{
    return $callback($valor);
}

$resultado = ejecutar('abs', -5);  // Usa la función abs() de PHP
echo $resultado; // 5

Tipos nullable

Usa el símbolo ? antes del tipo para indicar que un parámetro puede ser null:

PHP
<?php

declare(strict_types=1);

// El parámetro puede ser string o null
function saludar(?string $nombre): string
{
    if ($nombre === null) {
        return 'Hola, visitante';
    }

    return "Hola, $nombre";
}

echo saludar('Pedro'); // Hola, Pedro
echo saludar(null);    // Hola, visitante

// Nullable con valor por defecto
function configurar(?string $valor = null): void
{
    if ($valor === null) {
        echo "Usando configuración por defecto\n";
        return;
    }

    echo "Configurando: $valor\n";
}

configurar();        // Usando configuración por defecto
configurar(null);    // Usando configuración por defecto
configurar('debug'); // Configurando: debug

Union types (PHP 8+)

Los union types permiten que un parámetro acepte varios tipos diferentes:

PHP
<?php

declare(strict_types=1);

// Acepta string o int
function mostrarId(string|int $id): void
{
    echo "ID: $id\n";
}

mostrarId(123);     // ID: 123
mostrarId('ABC');   // ID: ABC

// Múltiples tipos con null
function procesar(array|string|null $datos): string
{
    if ($datos === null) {
        return 'Sin datos';
    }

    if (is_array($datos)) {
        return implode(', ', $datos);
    }

    return $datos;
}

echo procesar(['a', 'b', 'c']); // a, b, c
echo procesar('texto');          // texto
echo procesar(null);             // Sin datos

Valores por defecto

Los parámetros pueden tener valores por defecto que se usan cuando no se proporciona un argumento:

PHP
<?php

declare(strict_types=1);

// Valor por defecto simple
function saludar(string $nombre = 'mundo'): string
{
    return "Hola, $nombre";
}

echo saludar();       // Hola, mundo
echo saludar('Ana');  // Hola, Ana

// Múltiples valores por defecto
function crearUsuario(
    string $nombre,
    string $email,
    string $rol = 'usuario',
    bool $activo = true,
    int $intentos = 0
): array {
    return [
        'nombre' => $nombre,
        'email' => $email,
        'rol' => $rol,
        'activo' => $activo,
        'intentos' => $intentos,
    ];
}

// Solo los dos primeros son obligatorios
$usuario = crearUsuario('Ana', 'ana@example.com');
$admin = crearUsuario('Admin', 'admin@example.com', 'administrador');

print_r($usuario);
/*
[
    'nombre' => 'Ana',
    'email' => 'ana@example.com',
    'rol' => 'usuario',
    'activo' => true,
    'intentos' => 0,
]
*/
Orden de parámetros

Los parámetros con valores por defecto deben ir después de los obligatorios. function foo(string $a = '', string $b) es incorrecto.

Paso por valor vs por referencia

Por defecto, PHP pasa argumentos por valor: la función recibe una copia del valor original. Para modificar la variable original, usa paso por referencia con &:

PHP
<?php

declare(strict_types=1);

// Paso por valor (por defecto)
function duplicarValor(int $numero): void
{
    $numero = $numero * 2;
    echo "Dentro: $numero\n";
}

$x = 5;
duplicarValor($x);
echo "Fuera: $x\n";
// Dentro: 10
// Fuera: 5 (no cambió)

// Paso por referencia (con &)
function duplicarReferencia(int &$numero): void
{
    $numero = $numero * 2;
    echo "Dentro: $numero\n";
}

$y = 5;
duplicarReferencia($y);
echo "Fuera: $y\n";
// Dentro: 10
// Fuera: 10 (sí cambió)
PHP
<?php

declare(strict_types=1);

// Uso práctico: modificar un array en el sitio
function agregarElemento(array &$lista, string $elemento): void
{
    $lista[] = $elemento;
}

$frutas = ['manzana', 'pera'];
agregarElemento($frutas, 'naranja');
print_r($frutas); // ['manzana', 'pera', 'naranja']

// Intercambiar dos valores
function intercambiar(int &$a, int &$b): void
{
    $temp = $a;
    $a = $b;
    $b = $temp;
}

$x = 10;
$y = 20;
intercambiar($x, $y);
echo "x=$x, y=$y"; // x=20, y=10
Mejor práctica

Prefiere retornar valores en lugar de modificar por referencia. El código es más claro: $lista = agregarElemento($lista, $item) es más explícito que modificar silenciosamente.

Parámetros variádicos

El operador ... (splat) permite recibir un número variable de argumentos:

PHP
<?php

declare(strict_types=1);

// Función que acepta cualquier número de argumentos
function sumar(int ...$numeros): int
{
    return array_sum($numeros);
}

echo sumar(1, 2);           // 3
echo sumar(1, 2, 3, 4, 5);  // 15
echo sumar();               // 0

// Combinar parámetros fijos con variádicos
function log(string $nivel, string ...$mensajes): void
{
    foreach ($mensajes as $mensaje) {
        echo "[$nivel] $mensaje\n";
    }
}

log('INFO', 'Iniciando aplicación');
log('ERROR', 'Fallo en conexión', 'Reintentando...', 'Éxito');
// [INFO] Iniciando aplicación
// [ERROR] Fallo en conexión
// [ERROR] Reintentando...
// [ERROR] Éxito

// Tipado del parámetro variádico
function concatenar(string $separador, string ...$partes): string
{
    return implode($separador, $partes);
}

echo concatenar('-', 'a', 'b', 'c'); // a-b-c

Desempaquetar argumentos

El operador ... también sirve para desempaquetar un array como argumentos individuales:

PHP
<?php

declare(strict_types=1);

function sumarTres(int $a, int $b, int $c): int
{
    return $a + $b + $c;
}

$numeros = [1, 2, 3];

// Desempaquetar array como argumentos
echo sumarTres(...$numeros); // 6

// Equivalente a:
echo sumarTres($numeros[0], $numeros[1], $numeros[2]);

// Con arrays asociativos (PHP 8+)
function crearPersona(string $nombre, int $edad): array
{
    return ['nombre' => $nombre, 'edad' => $edad];
}

$datos = ['nombre' => 'Ana', 'edad' => 30];
$persona = crearPersona(...$datos);
print_r($persona); // ['nombre' => 'Ana', 'edad' => 30]

// Combinar arrays al desempaquetar
function sumarTodos(int ...$nums): int
{
    return array_sum($nums);
}

$grupo1 = [1, 2, 3];
$grupo2 = [4, 5];

echo sumarTodos(...$grupo1, ...$grupo2); // 15

Ejemplo práctico

PHP
<?php

declare(strict_types=1);

// Sistema de logger flexible

function formatearMensaje(
    string $mensaje,
    string $nivel = 'INFO',
    ?string $contexto = null
): string {
    $timestamp = date('Y-m-d H:i:s');
    $salida = "[$timestamp] [$nivel] $mensaje";

    if ($contexto !== null) {
        $salida .= " | Contexto: $contexto";
    }

    return $salida;
}

function formatearDatos(array $datos): string
{
    $partes = [];
    foreach ($datos as $clave => $valor) {
        if (is_array($valor)) {
            $valor = implode(',', $valor);
        }
        $partes[] = "$clave=$valor";
    }
    return implode(', ', $partes);
}

function registrarLog(string $nivel, string $mensaje, array $datos = []): void
{
    $contexto = null;

    if (count($datos) > 0) {
        $contexto = formatearDatos($datos);
    }

    echo formatearMensaje($mensaje, $nivel, $contexto) . "\n";
}

// Uso del logger
registrarLog('INFO', 'Aplicación iniciada');
// [2024-01-15 10:30:00] [INFO] Aplicación iniciada

registrarLog('DEBUG', 'Usuario autenticado', ['user_id' => 123, 'ip' => '192.168.1.1']);
// [2024-01-15 10:30:00] [DEBUG] Usuario autenticado | Contexto: user_id=123, ip=192.168.1.1

registrarLog('ERROR', 'Conexión fallida', ['servidor' => 'mysql', 'puerto' => 3306]);
// [2024-01-15 10:30:00] [ERROR] Conexión fallida | Contexto: servidor=mysql, puerto=3306

// Función que aplica valores por defecto a un array de configuración
function aplicarDefaults(array $config, array $defaults): array
{
    foreach ($defaults as $clave => $valor) {
        if (!array_key_exists($clave, $config)) {
            $config[$clave] = $valor;
        }
    }
    return $config;
}

$miConfig = ['debug' => true];
$defaults = ['debug' => false, 'cache' => true, 'timeout' => 30];

$configFinal = aplicarDefaults($miConfig, $defaults);
print_r($configFinal);
// ['debug' => true, 'cache' => true, 'timeout' => 30]

Ejercicios

Ejercicio 1: Funcion con parametros opcionales

Crea una funcion formatearNombre que reciba un nombre (obligatorio), un apellido (opcional, por defecto cadena vacia) y un titulo (opcional, por defecto null). Debe retornar el nombre completo formateado. Si hay titulo, incluirlo al principio.

Ver solucion
PHP
<?php
declare(strict_types=1);

function formatearNombre(
    string $nombre,
    string $apellido = '',
    ?string $titulo = null
): string {
    $nombreCompleto = trim("$nombre $apellido");

    if ($titulo !== null) {
        return "$titulo $nombreCompleto";
    }

    return $nombreCompleto;
}

echo formatearNombre('Ana');                    // Ana
echo formatearNombre('Ana', 'Garcia');          // Ana Garcia
echo formatearNombre('Ana', 'Garcia', 'Dra.');  // Dra. Ana Garcia

Ejercicio 2: Funcion variadica

Crea una funcion calcularPromedio que acepte cualquier cantidad de numeros (int o float) usando parametros variadicos y retorne su promedio. Si no se pasan numeros, debe retornar 0.

Ver solucion
PHP
<?php
declare(strict_types=1);

function calcularPromedio(int|float ...$numeros): float
{
    if (count($numeros) === 0) {
        return 0.0;
    }

    return array_sum($numeros) / count($numeros);
}

echo calcularPromedio(10, 20, 30); // 20.0
echo calcularPromedio(5, 10);      // 7.5
echo calcularPromedio(100);        // 100.0
echo calcularPromedio();           // 0.0

Ejercicio 3: Paso por referencia

Crea una funcion agregarPrefijo que reciba un array de strings por referencia y un prefijo. La funcion debe modificar cada elemento del array agregando el prefijo al principio. No debe retornar nada (void).

Ver solucion
PHP
<?php
declare(strict_types=1);

function agregarPrefijo(array &$elementos, string $prefijo): void
{
    foreach ($elementos as $key => $valor) {
        $elementos[$key] = $prefijo . $valor;
    }
}

$archivos = ['documento.pdf', 'imagen.jpg', 'video.mp4'];
agregarPrefijo($archivos, 'uploads/');

print_r($archivos);
// ['uploads/documento.pdf', 'uploads/imagen.jpg', 'uploads/video.mp4']

¿Te está gustando el curso?

Tenemos cursos premium con proyectos reales y soporte personalizado.

Descubrir cursos premium