Valores de Retorno
El valor de retorno es lo que una función devuelve al código que la llamó. Dominar los tipos de retorno te permite escribir funciones predecibles y aprovechar las verificaciones de tipo de PHP moderno.
La sentencia return
return termina la ejecución de la
función y devuelve un valor al código que la
llamó:
<?php
declare(strict_types=1);
function sumar(int $a, int $b): int
{
return $a + $b; // Devuelve el resultado y termina
}
$resultado = sumar(5, 3);
echo $resultado; // 8
// return termina la función inmediatamente
function verificarEdad(int $edad): string
{
if ($edad < 0) {
return 'Edad inválida'; // Termina aquí si es negativo
}
if ($edad >= 18) {
return 'Mayor de edad'; // Termina aquí si >= 18
}
return 'Menor de edad'; // Caso restante
}
echo verificarEdad(25); // Mayor de edad
echo verificarEdad(-5); // Edad inválida
echo verificarEdad(15); // Menor de edad
Tipo de retorno void
Usa void cuando la función no
devuelve ningún valor. Esto hace explícito que
la función solo ejecuta acciones sin retornar
datos:
<?php
declare(strict_types=1);
function mostrarMensaje(string $mensaje): void
{
echo $mensaje . "\n";
// No hay return, o return sin valor
}
function procesarDatos(array $datos): void
{
foreach ($datos as $dato) {
echo "Procesando: $dato\n";
}
return; // return vacío es válido con void
}
// Esto causaría un error:
// function invalida(): void
// {
// return 'algo'; // Error: función void no puede retornar valor
// }
mostrarMensaje('Hola');
$resultado = mostrarMensaje('Test'); // $resultado será null
Tipos de retorno nullable
Usa ?tipo para indicar que una
función puede retornar el tipo especificado o
null:
<?php
declare(strict_types=1);
// Puede retornar array o null
function buscarUsuario(int $id): ?array
{
$usuarios = [
1 => ['nombre' => 'Ana', 'email' => 'ana@example.com'],
2 => ['nombre' => 'Luis', 'email' => 'luis@example.com'],
];
return $usuarios[$id] ?? null;
}
$usuario = buscarUsuario(1);
if ($usuario !== null) {
echo $usuario['nombre']; // Ana
}
$noExiste = buscarUsuario(99);
if ($noExiste === null) {
echo 'Usuario no encontrado';
}
// Puede retornar string o null
function obtenerConfig(string $clave): ?string
{
$config = [
'app_name' => 'MiApp',
'version' => '1.0.0',
];
return $config[$clave] ?? null;
}
$nombre = obtenerConfig('app_name') ?? 'Aplicación';
echo $nombre; // MiApp
Union types en retorno (PHP 8+)
Los union types permiten que una función retorne uno de varios tipos posibles:
<?php
declare(strict_types=1);
// Retorna int o float dependiendo de la operación
function dividir(int $a, int $b): int|float
{
if ($b === 0) {
return 0;
}
$resultado = $a / $b;
// Retorna int si es división exacta
if ($resultado === floor($resultado)) {
return (int) $resultado;
}
return $resultado;
}
echo dividir(10, 2); // 5 (int)
echo dividir(10, 3); // 3.3333... (float)
// Retorna valor o false (patrón común en PHP)
function buscarEnTexto(string $texto, string $buscar): int|false
{
$posicion = strpos($texto, $buscar);
return $posicion; // int si encuentra, false si no
}
$resultado = buscarEnTexto('Hola mundo', 'mundo');
if ($resultado !== false) {
echo "Encontrado en posición: $resultado"; // 5
}
// Múltiples tipos de retorno
function procesarValor(mixed $valor): string|int|array
{
if (is_array($valor)) {
return $valor;
}
if (is_numeric($valor)) {
return (int) $valor;
}
return (string) $valor;
}
El tipo mixed
mixed (PHP 8+) indica que la
función puede retornar cualquier tipo:
<?php
declare(strict_types=1);
// mixed = cualquier tipo (incluyendo null)
function obtenerValor(string $clave): mixed
{
$datos = [
'nombre' => 'Ana',
'edad' => 25,
'activo' => true,
'tags' => ['php', 'web'],
];
return $datos[$clave] ?? null;
}
$nombre = obtenerValor('nombre'); // string
$edad = obtenerValor('edad'); // int
$tags = obtenerValor('tags'); // array
// Úsalo cuando realmente necesites flexibilidad total
// Prefiere tipos específicos cuando sea posible
Usa mixed solo cuando sea
necesario. Los tipos específicos
proporcionan mejor documentación y
detección de errores.
Retornar múltiples valores
PHP no permite retornar múltiples valores directamente, pero puedes usar arrays y destructuring:
<?php
declare(strict_types=1);
// Opción 1: Array asociativo (más legible)
function calcularEstadisticas(array $numeros): array
{
$cantidad = count($numeros);
$suma = array_sum($numeros);
return [
'min' => min($numeros),
'max' => max($numeros),
'suma' => $suma,
'promedio' => $cantidad > 0 ? $suma / $cantidad : 0,
'cantidad' => $cantidad,
];
}
$stats = calcularEstadisticas([1, 2, 3, 4, 5]);
echo $stats['promedio']; // 3
echo $stats['max']; // 5
// Opción 2: Array indexado con destructuring
function dividirConResto(int $dividendo, int $divisor): array
{
return [
intdiv($dividendo, $divisor),
$dividendo % $divisor,
];
}
[$cociente, $resto] = dividirConResto(17, 5);
echo "17 / 5 = $cociente resto $resto"; // 17 / 5 = 3 resto 2
// Opción 3: Array con claves para destructuring
function obtenerCoordenadas(string $ciudad): array
{
$ubicaciones = [
'Madrid' => ['lat' => 40.4168, 'lon' => -3.7038],
'Barcelona' => ['lat' => 41.3851, 'lon' => 2.1734],
];
return $ubicaciones[$ciudad] ?? ['lat' => 0.0, 'lon' => 0.0];
}
$coords = obtenerCoordenadas('Madrid');
echo "Latitud: {$coords['lat']}"; // Latitud: 40.4168
Early return (retorno temprano)
El patrón "early return" mejora la legibilidad al manejar casos especiales primero:
<?php
declare(strict_types=1);
// ❌ Sin early return (difícil de leer)
function calcularDescuento(float $total, ?string $cupon): float
{
$descuento = 0.0;
if ($total > 0) {
if ($cupon !== null) {
if ($cupon === 'VERANO20') {
$descuento = $total * 0.20;
} elseif ($cupon === 'NUEVO10') {
$descuento = $total * 0.10;
}
}
}
return $descuento;
}
// ✅ Con early return (más claro)
function calcularDescuentoMejor(float $total, ?string $cupon): float
{
if ($total <= 0) {
return 0.0;
}
if ($cupon === null) {
return 0.0;
}
return match ($cupon) {
'VERANO20' => $total * 0.20,
'NUEVO10' => $total * 0.10,
default => 0.0,
};
}
Ejemplo práctico
<?php
declare(strict_types=1);
// Sistema de validación con diferentes tipos de retorno
function validarEmail(string $email): array
{
$errores = [];
if (empty($email)) {
$errores[] = 'El email es obligatorio';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errores[] = 'El formato del email no es válido';
}
return [
'valido' => count($errores) === 0,
'errores' => $errores,
];
}
function validarPassword(string $password): array
{
$errores = [];
if (strlen($password) < 8) {
$errores[] = 'La contraseña debe tener al menos 8 caracteres';
}
if (!preg_match('/[A-Z]/', $password)) {
$errores[] = 'Debe contener al menos una mayúscula';
}
if (!preg_match('/[0-9]/', $password)) {
$errores[] = 'Debe contener al menos un número';
}
return [
'valido' => count($errores) === 0,
'errores' => $errores,
];
}
function registrarUsuario(string $email, string $password, string $nombre): array
{
$errores = [];
// Validar email
$resultadoEmail = validarEmail($email);
if (!$resultadoEmail['valido']) {
$errores = [...$errores, ...$resultadoEmail['errores']];
}
// Validar password
$resultadoPassword = validarPassword($password);
if (!$resultadoPassword['valido']) {
$errores = [...$errores, ...$resultadoPassword['errores']];
}
// Validar nombre
if (strlen($nombre) < 2) {
$errores[] = 'El nombre debe tener al menos 2 caracteres';
}
// Si hay errores, retornar sin crear usuario
if (count($errores) > 0) {
return [
'exito' => false,
'usuario' => null,
'errores' => $errores,
];
}
// Crear usuario (simulado)
$usuario = [
'id' => random_int(1000, 9999),
'email' => $email,
'nombre' => $nombre,
'creado' => date('Y-m-d H:i:s'),
];
return [
'exito' => true,
'usuario' => $usuario,
'errores' => [],
];
}
// Uso
$resultado = registrarUsuario('ana@example.com', 'MiPassword123', 'Ana');
if ($resultado['exito']) {
echo "Usuario creado: {$resultado['usuario']['nombre']}\n";
} else {
echo "Errores:\n";
foreach ($resultado['errores'] as $error) {
echo "- $error\n";
}
}
Ejercicios
Ejercicio 1: Funcion con retorno nullable
Crea una funcion
buscarPorId que reciba un
array de productos y un id (int). Debe
retornar el producto si existe, o
null si no se encuentra.
Cada producto es un array con claves
'id' y 'nombre'.
Ver solucion
<?php
declare(strict_types=1);
function buscarPorId(array $productos, int $id): ?array
{
foreach ($productos as $producto) {
if ($producto['id'] === $id) {
return $producto;
}
}
return null;
}
$productos = [
['id' => 1, 'nombre' => 'Laptop'],
['id' => 2, 'nombre' => 'Mouse'],
['id' => 3, 'nombre' => 'Teclado'],
];
$encontrado = buscarPorId($productos, 2);
print_r($encontrado); // ['id' => 2, 'nombre' => 'Mouse']
$noExiste = buscarPorId($productos, 99);
var_dump($noExiste); // NULL
Ejercicio 2: Retornar multiples valores
Crea una funcion
analizarTexto que reciba un
string y retorne un array asociativo
con: 'longitud' (int), 'palabras' (int)
y 'mayusculas' (bool, true si todo esta
en mayusculas).
Ver solucion
<?php
declare(strict_types=1);
function analizarTexto(string $texto): array
{
return [
'longitud' => strlen($texto),
'palabras' => str_word_count($texto),
'mayusculas' => $texto === strtoupper($texto) && $texto !== '',
];
}
$resultado = analizarTexto('Hola mundo');
print_r($resultado);
// ['longitud' => 10, 'palabras' => 2, 'mayusculas' => false]
$resultado2 = analizarTexto('ALERTA');
print_r($resultado2);
// ['longitud' => 6, 'palabras' => 1, 'mayusculas' => true]
Ejercicio 3: Early return
Crea una funcion
categorizarEdad que reciba
una edad (int) y retorne una categoria:
'nino' (0-12), 'adolescente' (13-17),
'adulto' (18-64), 'senior' (65+). Si la
edad es negativa, retorna 'invalido'.
Usa early return.
Ver solucion
<?php
declare(strict_types=1);
function categorizarEdad(int $edad): string
{
if ($edad < 0) {
return 'invalido';
}
if ($edad <= 12) {
return 'nino';
}
if ($edad <= 17) {
return 'adolescente';
}
if ($edad <= 64) {
return 'adulto';
}
return 'senior';
}
echo categorizarEdad(-5); // invalido
echo categorizarEdad(8); // nino
echo categorizarEdad(15); // adolescente
echo categorizarEdad(30); // adulto
echo categorizarEdad(70); // senior
¿Has encontrado un error o tienes una sugerencia para mejorar esta lección?
Escríbenos¿Te está gustando el curso?
Tenemos cursos premium con proyectos reales y soporte personalizado.
Descubrir cursos premium