CÓMO USAR KEYBY EN LARAVEL PARA TRANSFORMAR COLECCIONES FÁCILMENTE
keyBy es un método muy útil en las colecciones de Laravel que permiten reorganizar una colección convirtiendo un campo (o el resultado de una función) en la clave del array asociativo.
¿Qué hace exactamente keyBy?
Toma una colección (normalmente con claves numéricas 0, 1, 2...) y la transforma en un array asociativo donde las claves son los valores de una columna específica.
Importante: Si existen claves duplicadas, keyBy se queda solo con el último elemento que tenga esa clave (sobrescribe los anteriores). Si se quieren mantener todos los elementos con la misma clave, se debe usar groupBy en su lugar.
Ejemplos
//Obtener una colección de posts
$posts = Post::with('user')->get();
// Ejemplo del contenido de $posts (antes de keyBy)
[
0 => ['id' => 45, 'title' => 'Mi primer post', 'user_id' => 7, ...],
1 => ['id' => 52, 'title' => 'Laravel es genial', 'user_id' => 12, ...],
2 => ['id' => 45, 'title' => 'Otro post', 'user_id' => 7, ...], // mismo id
]
// Se convierte la colección para que la clave sea el ID del post
$postsById = $posts->keyBy('id');
// Ahora podemos acceder directamente por ID de forma muy rápida:
$post = $postsById[45]; // Devuelve el post con id 45
$post = $postsById[52] ?? null; // Safe access
// También puedes usarlo directamente en una sola línea:
$postsById = Post::all()->keyBy('id');
keyBy con una columna diferente:
// Agrupar por slug (útil para rutas)
$postsBySlug = $posts->keyBy('slug');
$post = $postsBySlug['laravel-es-genial'];
keyBy con funcion callback:
$usersByEmail = $users->keyBy(function ($user) {
return strtolower($user->email);
});
// O más moderno (Laravel 8+):
$usersByEmail = $users->keyBy(fn($user) => strtolower($user->email));
Ejemplo en un controlador:
public function index()
{
$products = Product::all();
// Creamos un "diccionario" para acceso rápido
$productsBySku = $products->keyBy('sku');
return view('products.index', compact('products', 'productsBySku'));
}
Combinación con Pluck:
// Crear un array de [id => name]
$productNames = Product::all()
->keyBy('id')
->pluck('name');
// Resultado: [1 => 'Laptop', 2 => 'Mouse', 3 => 'Teclado']
Ejemplo con relación de Eloquent:
public function showUserPosts($userId)
{
$user = User::findOrFail($userId);
// Obtenemos todos los posts del usuario con la relación inversa
$posts = $user->posts()->with('category')->get();
// Creamos un diccionario de posts por ID (muy útil para vistas o APIs)
$postsById = $posts->keyBy('id');
// También podemos crear un array solo con título y categoría:
$postSummary = $posts->keyBy('id')->map(function ($post) {
return [
'title' => $post->title,
'category' => $post->category?->name ?? 'Sin categoría',
'published' => $post->created_at->format('d/m/Y'),
];
});
return view('users.posts', compact('user', 'postsById', 'postSummary'));
}
Diferencia importante: keyBy vs groupBy
| Método |
Qué hace |
Si hay claves duplicadas |
Uso típico |
| keyBy() |
Convierte el campo en clave del array |
Se queda solo con el último elemento |
Cuando la clave es única (ID, SKU, slug, email, código, etc.) |
| groupBy() |
Agrupa los elementos en sub-colecciones |
Crea un array con todos los elementos |
Cuando puede haber varios elementos por clave (categorías, estados, fechas, etc.) |