9 de octubre de 2023

Cómo importar archivos Excel en Laravel 13: guía completa con Laravel Excel

Foto de Marco Orta Marco Orta | 12 mins de lectura
Compartir
Hoja de cálculo Excel siendo importada hacia una base de datos a través de un proyecto Laravel

Importar archivos Excel y CSV es una de esas tareas que parecen simples hasta que un cliente te pide subir 50 mil filas de productos. Laravel facilita enormemente este flujo gracias al paquete maatwebsite/excel, que sigue siendo el estándar en 2026 (versión 3.1.69, abril 2026). En esta guía actualizada para Laravel 13 vamos a ver instalación, una clase de importación funcional, validación, chunking para volúmenes grandes y cuándo conviene usar la alternativa OpenSpout.

1. Tener Laravel 13 instalado

Si todavía no tienes Laravel listo, revisa la guía dedicada: Cómo instalar Laravel 13. Recuerda que Laravel 13 requiere PHP 8.3 mínimo (8.4 en práctica desde Laravel 13.3).

2. Instalación del paquete maatwebsite/excel

Con Laravel 13 corriendo, instalamos maatwebsite/excel. Este paquete envuelve PhpSpreadsheet y ofrece una API muy ergonómica para importar y exportar archivos Excel, CSV, ODS y más.

composer require maatwebsite/excel

💡 En Laravel 11+ ya no es necesario registrar manualmente el ServiceProvider ni el alias: la auto‑discovery del paquete lo hace por ti. Si estás en una versión muy vieja de Laravel, sí necesitas agregar las entradas en config/app.php, pero en Laravel 12 y 13 el comando anterior es lo único que necesitas.

3. Publicación de la configuración

Con el paquete Maatwebsite/Laravel-Excel ya instalado en tu proyecto Laravel 10, es crucial asegurarse de que la configuración esté adecuadamente establecida para adaptarse a tus necesidades específicas. Este paquete viene con un conjunto de configuraciones predeterminadas que, si bien son útiles para empezar, pueden necesitar ajustes según el proyecto en el que estés trabajando.

Para tener un control completo sobre estas configuraciones y poder personalizarlas, necesitas publicar el archivo de configuración del paquete en tu aplicación. Al hacerlo, Laravel creará una copia del archivo de configuración en tu directorio config, permitiéndote hacer los cambios necesarios sin afectar el paquete original.

Para publicar el archivo de configuración, utiliza el siguiente comando en tu terminal o consola de comandos:

php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider"

Al ejecutar este comando, se creará un nuevo archivo llamado excel.php dentro del directorio config de tu aplicación Laravel. Ahora, si abres este archivo, tendrás acceso a varias opciones de configuración, como formatos de exportación, límites de memoria, y más.

Ejemplo de Código de Config

Excel.php

Es recomendable revisar detenidamente este archivo y familiarizarse con las distintas opciones disponibles. Aunque no es necesario modificar todas las configuraciones de inmediato, es útil saber qué se puede ajustar a medida que avanzas en el proceso de importación de tus archivos Excel.

Con la configuración correctamente publicada y al alcance de tu mano, estás un paso más cerca de aprovechar al máximo las capacidades del paquete Maatwebsite/Laravel-Excel en tu aplicación Laravel 10.

4. Creación del controlador

Una vez que hayas configurado adecuadamente el paquete Maatwebsite/Laravel-Excel, el siguiente paso lógico es crear un controlador que maneje las operaciones relacionadas con la importación de archivos Excel. En el paradigma MVC (Modelo-Vista-Controlador) que Laravel adopta, los controladores son responsables de manejar la lógica de negocio y las interacciones con el usuario. Por lo tanto, tener un controlador dedicado para gestionar las importaciones de Excel mantiene tu código organizado y modular.

Para crear un controlador en Laravel, el framework proporciona un comando Artisan muy útil que automatiza el proceso. En este caso, vamos a crear un controlador llamado ExcelController.

Abre tu terminal o consola de comandos y, estando en la raíz de tu proyecto Laravel, ejecuta el siguiente comando:

php artisan make:controller ExcelController

Este comando generará un nuevo archivo ExcelController.php dentro del directorio app/Http/Controllers. Al abrir este archivo, encontrarás una clase vacía preparada para que empieces a añadir tus métodos y lógica relacionada con la importación de Excel.

ExcelController

ExcelController.php

Es importante mencionar que, aunque en este punto el controlador está vacío, pronto lo llenaremos con los métodos necesarios para manejar la carga de archivos, la validación y, por supuesto, la importación de datos desde los archivos Excel hacia tu base de datos.

Con el controlador en su lugar, has establecido un punto centralizado desde el cual gestionar todas las operaciones relacionadas con Excel en tu aplicación Laravel. En las próximas secciones, detallaremos cómo integrar la funcionalidad de importación y cómo interactuar con el paquete Maatwebsite/Laravel-Excel desde este controlador.

5. Creando la clase de importación

La verdadera magia del paquete Maatwebsite/Laravel-Excel radica en su capacidad para permitirte definir clases de importación personalizadas. Estas clases actúan como intermediarias entre el archivo Excel y tu base de datos, dictando cómo se deben interpretar y almacenar los datos. Al separar esta lógica en su propia clase, mantienes una estructura limpia y modular, lo que facilita la escalabilidad y el mantenimiento a largo plazo.

Para crear una clase de importación, primero debes determinar qué tipo de datos deseas importar. Por ejemplo, si estás trabajando en una aplicación que gestiona usuarios y deseas importar una lista de ellos desde un archivo Excel, podrías crear una clase UsersImport.

Para generar esta clase de importación, utiliza el comando Artisan proporcionado por Laravel. Asegúrate de estar en la raíz de tu proyecto y ejecuta:

php artisan make:import UsersImport --model=User

Con el argumento --model=User, le estás indicando a Laravel que esta clase de importación estará asociada con el modelo User. Esto es especialmente útil, ya que la clase generada ya contendrá una estructura básica que mapea las filas del archivo Excel a instancias del modelo User.

El comando anterior creará un nuevo archivo UsersImport.php en el directorio app/Imports. Al abrir este archivo, encontrarás una estructura básica que puedes personalizar según tus necesidades.

La creación de esta clase es esencial, ya que aquí es donde definirás cómo se deben interpretar los datos del archivo Excel y cómo se deben mapear a tu base de datos. Es el núcleo de la funcionalidad de importación y será el lugar donde pasarás la mayor parte del tiempo configurando y ajustando la lógica de importación.

Con la clase de importación en su lugar, estás listo para avanzar y profundizar en la personalización de cómo se importarán los datos.

6. Configurando la clase de importación

Con tu clase UsersImport creada, es hora de configurarla para dictar exactamente cómo se deben manejar los datos del archivo Excel. Esta configuración es fundamental, ya que determinará cómo se interpretarán las filas y columnas del Excel y cómo se mapearán a tu modelo User.

Definición del comportamiento de importación

El paquete Maatwebsite/Laravel-Excel proporciona varias interfaces (o “Concerns”) que puedes implementar para definir el comportamiento de tu clase de importación. Una de las más comunes es ToModel, que te permite mapear cada fila del archivo Excel a una instancia de un modelo Eloquent.

Abre el archivo UsersImport.php y modifica la clase para que implemente la interfaz ToModel:

use Maatwebsite\Excel\Concerns\ToModel;

class UsersImport implements ToModel
{
    ...
}

Mapeo de filas a modelos

Dentro de la clase, debes definir el método model, que determinará cómo se mapea cada fila del archivo Excel a una instancia del modelo:

use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Maatwebsite\Excel\Concerns\ToModel;

class UsersImport implements ToModel
{
    public function model(array $row)
    {
        return new User([
            'name'     => $row[0],
            'email'    => $row[1],
            'password' => Hash::make($row[2]),
        ]);
    }
}

En el ejemplo anterior, cada fila del archivo Excel se mapea a un nuevo modelo User, donde la primera columna se utiliza como el nombre, la segunda como el correo electrónico y la tercera como la contraseña (que se cifra utilizando Hash::make).

Personalización adicional

Es posible que necesites realizar ajustes adicionales dependiendo de la estructura de tu archivo Excel y tus requisitos específicos. Por ejemplo, podrías querer agregar validación, omitir filas o incluso manejar eventos durante el proceso de importación. Maatwebsite/Laravel-Excel ofrece una amplia gama de interfaces y métodos que te permiten personalizar completamente el proceso de importación.

Con tu clase de importación ahora configurada, has establecido una clara instrucción sobre cómo se deben manejar los datos importados. Este nivel de detalle y personalización es lo que hace que el paquete Maatwebsite/Laravel-Excel sea tan poderoso y flexible.

7. Importando los datos

Con la estructura y configuración ya en su lugar, es momento de llevar a cabo la acción principal: importar los datos del archivo Excel a tu base de datos. Para esto, utilizarás el controlador ExcelController que creaste anteriormente y la clase de importación UsersImport que acabas de configurar.

Método de importación en el controlador

Dentro de tu ExcelController, necesitas definir un método que se encargue de la importación. Este método deberá recibir el archivo Excel a través de una solicitud HTTP, procesarlo utilizando la clase UsersImport y, finalmente, almacenar los datos en la base de datos.

Abre el archivo ExcelController.php y añade el siguiente método:

use App\Imports\UsersImport;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;

public function import(Request $request) 
{
    // Validar que se ha subido un archivo
    $request->validate([
        'file' => 'required|mimes:xlsx,csv'
    ]);

    // Importar el archivo utilizando la clase UsersImport
    Excel::import(new UsersImport, $request->file('file'));

    // Redirigir con un mensaje de éxito
    return redirect('/')->with('success', 'Datos importados con éxito!');
}

En este método:

  • Primero, validas que se haya subido un archivo y que sea de tipo xlsx o csv.
  • Luego, utilizas el facade Excel para importar los datos del archivo utilizando la clase UsersImport.
  • Finalmente, rediriges al usuario a la página de inicio con un mensaje de éxito.

Integración con el frontend

Para que los usuarios puedan subir archivos Excel, necesitarás un formulario en tu frontend que permita seleccionar y enviar el archivo. Asegúrate de que este formulario esté dirigido a la ruta que maneja el método de importación en ExcelController.

Por ejemplo:

<form action="{{ route('import') }}" method="POST" enctype="multipart/form-data">
    @csrf
    <input type="file" name="file" required>
    <button type="submit">Importar</button>
</form>

Este formulario simple permite a los usuarios seleccionar un archivo Excel y enviarlo para su importación.

8. Frontend y rutas

Con la lógica de importación en su lugar, es esencial asegurarse de que los usuarios tengan una interfaz fácil de usar para subir archivos Excel y que tu aplicación pueda procesar adecuadamente estas solicitudes. Esto implica configurar el frontend y definir rutas claras en Laravel.

Creación de la vista

Primero, necesitas una vista donde los usuarios puedan seleccionar y subir archivos. Si bien anteriormente proporcioné un ejemplo básico de un formulario, es posible que desees hacerlo más estético y funcional.

En el directorio resources/views, crea un nuevo archivo, por ejemplo, import.blade.php. Dentro de este archivo, puedes diseñar una página sencilla con el formulario:

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>Importar Usuarios desde Excel</h1>
    <form action="{{ route('import') }}" method="POST" enctype="multipart/form-data">
        @csrf
        <div class="form-group">
            <label for="file">Selecciona un archivo Excel</label>
            <input type="file" name="file" class="form-control" required>
        </div>
        <button type="submit" class="btn btn-primary">Importar</button>
    </form>
</div>
@endsection

Este diseño básico proporciona un título y un campo de entrada para el archivo, todo dentro de una estructura típica de Laravel Blade.

Definición de rutas

Para que la aplicación pueda responder a las solicitudes de los usuarios, necesitas definir rutas en Laravel que apunten a las acciones adecuadas en tu controlador.

Abre el archivo routes/web.php y añade las siguientes rutas:

use App\Http\Controllers\ExcelController;

// Ruta para mostrar el formulario
Route::get('/import', [ExcelController::class, 'showImportForm'])->name('import.form');

// Ruta para procesar la importación
Route::post('/import', [ExcelController::class, 'import'])->name('import');

Aquí, la primera ruta muestra el formulario de importación, mientras que la segunda ruta maneja la solicitud POST del formulario y lleva a cabo la importación.

Método adicional en el controlador

Dado que hemos añadido una ruta para mostrar el formulario, necesitamos un método correspondiente en ExcelController:

public function showImportForm()
{
    return view('import');
}

Este método simplemente devuelve la vista que contiene el formulario de importación.

9. Importaciones grandes: chunking y validación

Cuando el archivo Excel pasa de las 5–10 mil filas, cargar todo en memoria se convierte en un problema. maatwebsite/excel te ofrece dos herramientas clave: chunking y batch inserts.

Modifica UsersImport para implementar las interfaces WithChunkReading, WithBatchInserts, WithValidation y WithHeadingRow:

namespace App\Imports;

use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithValidation;

class UsersImport implements ToModel, WithChunkReading, WithBatchInserts, WithValidation, WithHeadingRow
{
    public function model(array $row)
    {
        return new User([
            'name'     => $row['name'],
            'email'    => $row['email'],
            'password' => Hash::make($row['password']),
        ]);
    }

    public function chunkSize(): int   { return 500; }
    public function batchSize(): int   { return 500; }

    public function rules(): array
    {
        return [
            'name'     => ['required', 'string', 'max:255'],
            'email'    => ['required', 'email', 'unique:users,email'],
            'password' => ['required', 'min:8'],
        ];
    }
}

Lo que cambia:

  • WithHeadingRow te permite acceder por nombre de columna ($row['email']) en lugar de por índice numérico. Mucho más mantenible.
  • WithChunkReading lee el archivo en bloques de 500 filas, evitando agotar memoria.
  • WithBatchInserts ejecuta INSERT por lotes en lugar de uno por fila.
  • WithValidation valida cada fila con las mismas reglas que usas en tus FormRequest.

Para archivos muy grandes, puedes además encolar la importación:

use Maatwebsite\Excel\Facades\Excel;

Excel::queueImport(new UsersImport, $request->file('file'));

La importación se procesará en background con tu sistema de colas (Redis, database, SQS). Esto es prácticamente obligatorio para archivos de más de 50 mil filas.

10. Alternativa: OpenSpout para volúmenes muy grandes

maatwebsite/excel se apoya en PhpSpreadsheet, que es muy completo pero consume bastante memoria. Si solo necesitas leer/escribir CSV o XLSX simples a velocidad máxima, OpenSpout (fork mantenido del antiguo Spout de Box) es notablemente más rápido y consume menos RAM, a cambio de menos funciones de formato.

composer require openspout/openspout
use OpenSpout\Reader\XLSX\Reader;

$reader = new Reader();
$reader->open(storage_path('app/usuarios.xlsx'));

foreach ($reader->getSheetIterator() as $sheet) {
    foreach ($sheet->getRowIterator() as $row) {
        $cells = $row->getCells();
        User::create([
            'name'     => $cells[0]->getValue(),
            'email'    => $cells[1]->getValue(),
            'password' => Hash::make($cells[2]->getValue()),
        ]);
    }
}

$reader->close();

Regla práctica:

  • Hasta ~50 k filas o si necesitas validaciones complejas, estilos y múltiples hojas → maatwebsite/excel.
  • Más de 50 k filas o pipelines de datos donde solo importa la velocidad → OpenSpout.

Conclusión

Importar archivos Excel en Laravel 13 es una tarea que el paquete maatwebsite/excel resuelve con elegancia, y para archivos pequeños o medianos sigue siendo la mejor opción en 2026. Cuando entres en territorio de decenas de miles de filas, no olvides activar chunking + batch inserts y considerar encolar la importación. Y si llegas al punto de procesar millones de filas, dale una oportunidad a OpenSpout.

Si estás construyendo un panel de administración con importaciones masivas, también te puede interesar Cómo optimizar el rendimiento de tu proyecto Laravel para sacarle todo el jugo a Octane y FrankenPHP.

¿Te funcionó la guía? Compártela en tus redes. ¡Saludos!

Compartir

Buscar

Etiquetas