Экспорт в Excel в Laravel: короткое руководство
Как за полчаса сделать выгрузку данных в файл .xlsx через пакет maatwebsite/excel: установка, экспорт коллекции, форматирование и типичные ошибки при большом объёме.

К концу этого руководства у вас будет кнопка «Скачать Excel», которая отдаёт файл .xlsx с данными из базы. На чистом Laravel 11 с настроенным подключением к БД это занимает 20–30 минут. Мы используем пакет maatwebsite/excel — это обёртка над PhpSpreadsheet, самый распространённый способ делать выгрузки в Laravel.
Разбираем только экспорт коллекции моделей в файл и его скачивание. Импорт из Excel, очереди для гигантских выгрузок и стили ячеек — отдельные темы, здесь их не трогаем.
Что нужно до начала
Проверьте, что всё это уже есть, иначе застрянете на середине:
- PHP 8.2+ — требование актуальной версии пакета (3.1.x). Проверьте:
php -v. - Laravel 10.x или 11.x — работающий проект с настроенным
.envи подключением к базе. - Расширение PHP
ext-zipи одно изext-gd— их требует PhpSpreadsheet для записи.xlsx. Проверить:php -m | grep -i zip. Если строкиzipнет — установите расширение через ваш пакетный менеджер. - Composer в проекте.
- Хотя бы одна модель с данными — для примера возьмём
App\Models\User.
Шаг 1. Установить пакет
В корне проекта выполните:
composer require maatwebsite/excelComposer подтянет сам пакет и PhpSpreadsheet как зависимость. Как понять, что получилось: в composer.json в разделе require появится строка "maatwebsite/excel", а в консоли — Package manifest generated successfully.
ServiceProvider и фасад Excel регистрируются автоматически через package discovery — руками в config/app.php ничего дописывать не нужно.
Шаг 2. Создать класс экспорта
Пакет предлагает свою artisan-команду. Создайте класс для выгрузки пользователей:
php artisan make:export UsersExport --model=UserКак понять, что получилось: появится файл app/Exports/UsersExport.php. Откройте его — внутри будет заготовка с методом collection(), который возвращает всех пользователей:
<?php
namespace App\Exports;
use App\Models\User;
use Maatwebsite\Excel\Concerns\FromCollection;
class UsersExport implements FromCollection
{
public function collection()
{
return User::all();
}
}Как это работает: интерфейс FromCollection говорит пакету «данные бери из коллекции, которую вернёт метод collection()». Каждая модель станет строкой, а её атрибуты — колонками в порядке, в котором они лежат в объекте.
Шаг 3. Добавить заголовки колонок и выбрать поля
По умолчанию в файл уйдут все атрибуты модели, включая password и remember_token. Так делать не нужно. Ограничьте набор полей и добавьте человеческие заголовки — для этого подключите ещё два интерфейса:
<?php
namespace App\Exports;
use App\Models\User;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
class UsersExport implements FromCollection, WithHeadings, WithMapping
{
public function collection()
{
return User::select('id', 'name', 'email', 'created_at')->get();
}
// Заголовки первой строки файла
public function headings(): array
{
return ['ID', 'Имя', 'Email', 'Дата регистрации'];
}
// Как превратить одну модель в строку
public function map($user): array
{
return [
$user->id,
$user->name,
$user->email,
$user->created_at->format('d.m.Y H:i'),
];
}
}WithHeadings добавляет первую строку с названиями колонок, WithMapping даёт контроль над каждой строкой — тут удобно форматировать даты и склеивать поля. Порядок значений в map() должен совпадать с порядком заголовков в headings().
Шаг 4. Отдать файл на скачивание
Добавьте маршрут в routes/web.php:
use App\Exports\UsersExport;
use Maatwebsite\Excel\Facades\Excel;
Route::get('/users/export', function () {
return Excel::download(new UsersExport, 'users.xlsx');
});Как понять, что получилось: откройте /users/export в браузере — начнётся скачивание файла users.xlsx. Откройте его в Excel или LibreOffice: первая строка — ваши заголовки, ниже — данные пользователей с датой в формате дд.мм.гггг.
Второй аргумент Excel::download() — имя файла, которое увидит пользователь. Расширение определяет формат: смените на users.csv — и пакет отдаст CSV без изменений в классе экспорта.
Кнопка в шаблоне
В Blade достаточно обычной ссылки на маршрут:
<a href="{{ url('/users/export') }}" class="btn">Скачать Excel</a>Не открывайте экспорт на публичном маршруте без проверки прав. Файл с email всех пользователей, доступный по прямой ссылке, — это утечка. Оберните маршрут в middleware auth и проверку роли.Если не получилось
Частые ошибки и что с ними делать:
- Class "ZipArchive" not found — не установлено расширение
ext-zip. Поставьте его и перезапустите PHP-процесс (например,php artisan serveзаново). - Target class [maatwebsite...] does not exist или фасад
Excelне находится — сбросьте кеш конфигурации:php artisan config:clearиcomposer dump-autoload. - Скачивается файл, но при открытии Excel ругается на повреждение — почти всегда виноват лишний вывод до отдачи файла: пробел перед
<?php,echoилиdd()в коде, случайный BOM в файле. Проверьте, что передreturn Excel::download()ничего не печатается. - Даты выводятся как число вроде 45000 — это сериализованная дата Excel. Форматируйте значение строкой в
map(), как в шаге 3, или подключите интерфейс форматирования колонок. - Allowed memory size exhausted — коллекция целиком загрузилась в память. Про это ниже.
Что делать при большом объёме
Метод collection() тянет все строки в память разом. На нескольких тысячах записей это нормально, на сотнях тысяч — Allowed memory size exhausted. Первое, что стоит сделать — заменить FromCollection на FromQuery: пакет сам разобьёт выборку на части (chunking) и не будет держать всё в памяти.
| Интерфейс | Когда использовать | Цена |
|---|---|---|
FromCollection | До нескольких тысяч строк | Просто, но грузит всё в память |
FromQuery | Десятки и сотни тысяч строк | Экономит память за счёт чанков |
Экспорт в очереди (ShouldQueue) | Выгрузки, которые не должны блокировать запрос | Нужен настроенный воркер очереди |
Точный синтаксис FromQuery и постановки экспорта в очередь смотрите в разделах Exports официальной документации пакета — там показаны актуальные для версии 3.1.x интерфейсы.
Что дальше
Базовая выгрузка готова. Дальше по мере надобности: закройте маршрут авторизацией, если ещё не сделали; для больших таблиц переходите на FromQuery; если выгрузка тяжёлая — вынесите её в очередь и отдавайте пользователю ссылку на готовый файл. Стили ячеек, ширину колонок и заморозку шапки добавляют отдельными интерфейсами — это следующий шаг, когда базовый экспорт заработает.
Магистр Excel и Google Sheets: ВПР, СУММЕСЛИМН, макросы VBA и скрипты Apps Script.
Спросить за 20 ₽Источники: Laravel Excel — официальная документация, PhpSpreadsheet — документация
Частые вопросы
Пакет требует более новую версию PHP, чем у меня. Что делать?
Скачивается пустой файл или только с заголовками. Почему?
Можно ли отдать файл сразу с несколькими листами?
Нужен ли настроенный storage, чтобы отдать файл через download?
Excel открывает CSV кракозябрами с кириллицей. Как исправить?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.