compact() crea un array asociativo a partir de variables del scope actual, usando el nombre de la variable como clave. extract() hace exactamente lo contrario: a partir de un array asociativo, crea variables locales con el nombre de cada clave. Son útiles en plantillas o vistas, pero extract() tiene una reputación bien ganada de ser peligrosa cuando los datos vienen de fuentes no confiables.
compact(): de variables a array
<?php $nombre = 'Ana GarcÃa'; $email = '[email protected]'; $rol = 'editora'; $activa = true; // Sin compact: verboso $usuario = [ 'nombre' => $nombre, 'email' => $email, 'rol' => $rol, 'activa' => $activa, ]; // Con compact: más conciso $usuario = compact('nombre', 'email', 'rol', 'activa'); print_r($usuario); // Array ( [nombre] => Ana GarcÃa [email] => [email protected] [rol] => editora [activa] => 1 ) ?>
Uso habitual en plantillas y controladores
<?php
function renderVista(string $plantilla, array $datos): void
{
extract($datos, EXTR_SKIP); // solo crea variables si no existen ya
include __DIR__ . "/vistas/{$plantilla}.php";
}
// En el controlador
$titulo = 'Lista de productos';
$productos = obtenerProductos();
$paginacion = calcularPagina($_GET['p'] ?? 1, count($productos));
renderVista('productos/lista', compact('titulo', 'productos', 'paginacion'));
?>
extract(): de array a variables
<?php
$config = [
'host' => 'localhost',
'puerto' => 3306,
'database' => 'tienda',
'charset' => 'utf8mb4',
];
extract($config);
// Ahora existen las variables $host, $puerto, $database, $charset
echo $host; // localhost
echo $puerto; // 3306
echo $database; // tienda
?>
Los flags: EXTR_SKIP, EXTR_PREFIX_ALL y EXTR_OVERWRITE
<?php $nombre = 'Variable original'; // ya existe $datos = ['nombre' => 'Del array', 'edad' => 28]; // EXTR_OVERWRITE (por defecto): sobreescribe variables existentes extract($datos, EXTR_OVERWRITE); echo $nombre; // "Del array" ? sobreescribió la original // Resetear $nombre = 'Variable original'; // EXTR_SKIP: no sobreescribe si ya existe extract($datos, EXTR_SKIP); echo $nombre; // "Variable original" ? preservada // EXTR_PREFIX_ALL: añade prefijo a todas las claves extract($datos, EXTR_PREFIX_ALL, 'arr'); echo $arr_nombre; // "Del array" echo $arr_edad; // 28 ?>
Por qué extract() con $_POST es peligroso
<?php
// NUNCA hagas esto
extract($_POST); // ? vulnerabilidad crÃtica
// Si el formulario envÃa ?admin=1 o ?isLoggedIn=true,
// esas variables se crean en el scope actual, pudiendo
// sobreescribir variables de control de acceso:
$esAdmin = false;
extract($_POST); // si POST trae 'esAdmin=1', ahora $esAdmin es '1'
if ($esAdmin) { // BYPASS del control de acceso
// acceso concedido incorrectamente
}
?>
El destructuring como alternativa segura
En PHP 7.1+ el destructuring de arrays es más explÃcito y legible que extract() cuando sabes exactamente qué campos esperas:
<?php $datos = ['nombre' => 'Ana', 'edad' => 28, 'ciudad' => 'Madrid']; // Destructuring: solo extraes lo que declaras explÃcitamente ['nombre' => $nombre, 'edad' => $edad] = $datos; echo $nombre; // Ana echo $edad; // 28 // $ciudad no se extrae, sin riesgo de contaminación del scope ?>
La documentación oficial de compact() y la de extract() detallan todos los flags disponibles y las advertencias de seguridad sobre el uso con datos de entrada del usuario.
