Экспорт в Excel в Laravel: пошаговая инструкция
За полчаса вы соберёте кнопку, по которой Laravel отдаёт готовый .xlsx с данными из базы. Разбираем установку пакета, класс экспорта, заголовки столбцов и типичные ошибки при скачивании файла.

В конце этой инструкции у вас будет рабочая ссылка вида /users/export, по которой браузер скачивает файл users.xlsx с данными из таблицы. На всё уйдёт 20–30 минут, если проект на Laravel уже поднят. Работаем с пакетом Laravel Excel (maatwebsite/excel) версии 3.1 на Laravel 11 и PHP 8.2.
Пакет Laravel Excel — обёртка над библиотекой PhpSpreadsheet. Он берёт коллекцию или запрос Eloquent и превращает в файл, а вам остаётся описать, какие поля и в каком порядке попадут в таблицу.
Что нужно иметь до начала
- Laravel 11 с настроенным подключением к базе и хотя бы одной моделью (в примере —
Userс данными); - PHP 8.2 или новее;
- установленное расширение PHP
ext-gdи одно из:ext-zipлибоext-xmlwriter— PhpSpreadsheet требует их для сборки .xlsx. Проверить:php -m | grep -E 'zip|gd|xml'; - Composer, доступ к терминалу в корне проекта.
Если расширений нет, установка пакета пройдёт, но при попытке скачать файл вы получите ошибку о недоступном ZIP-архиваторе. Поэтому проверьте php -m заранее.
Шаг 1. Устанавливаем пакет
В корне проекта:
composer require maatwebsite/excelComposer подтянет и сам пакет, и PhpSpreadsheet как зависимость. Начиная с версии 3.1 сервис-провайдер и фасад Excel регистрируются автоматически через package discovery — вручную ничего в config/app.php прописывать не нужно.
Проверка: выполните composer show maatwebsite/excel. В выводе должна быть строка versions : * 3.1.x. Если Composer ругается на конфликт версий PHP — сверьте требования пакета в его документации, для старого PHP нужна другая мажорная версия.
Шаг 2. Создаём класс экспорта
Пакет работает через отдельные классы — по одному на каждый тип выгрузки. Сгенерируйте заготовку artisan-командой:
php artisan make:export UsersExport --model=UserПоявится файл app/Exports/UsersExport.php. По умолчанию он реализует интерфейс FromCollection и выгружает всю модель как есть. Это редко то, что нужно: попадут все поля, включая пароли и служебные. Опишем выгрузку явно.
<?php
namespace App\Exports;
use App\Models\User;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
class UsersExport implements FromQuery, WithHeadings, WithMapping
{
// Заголовки столбцов первой строкой
public function headings(): array
{
return ['ID', 'Имя', 'Email', 'Дата регистрации'];
}
// Запрос вместо готовой коллекции: пакет читает данные порциями
public function query()
{
return User::query()->orderBy('id');
}
// Что и в каком порядке кладём в каждую строку
public function map($user): array
{
return [
$user->id,
$user->name,
$user->email,
$user->created_at->format('d.m.Y'),
];
}
}Три интерфейса делают три вещи. FromQuery отдаёт данные не одной коллекцией, а запросом — это важно для больших таблиц, о чём ниже. WithHeadings добавляет строку заголовков. WithMapping позволяет форматировать каждую ячейку и не тащить в файл лишние поля.
Шаг 3. Роут и метод контроллера
Экспорт запускается фасадом Excel::download(). Первый аргумент — экземпляр класса экспорта, второй — имя файла для скачивания. Расширение определяет формат: .xlsx — современный Excel, .csv — CSV.
<?php
// routes/web.php
use App\Exports\UsersExport;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\Route;
Route::get('/users/export', function () {
return Excel::download(new UsersExport, 'users.xlsx');
});Для реального проекта логику лучше держать в контроллере и закрыть роут middleware auth — выгрузка пользователей не должна быть доступна кому угодно по прямой ссылке.
Проверка: откройте /users/export в браузере. Должно начаться скачивание файла users.xlsx. Откройте его в Excel или LibreOffice — в первой строке заголовки, дальше данные.
Шаг 4. Кнопка на странице
Ссылку достаточно повесить обычной <a>, метод GET подходит для скачивания:
<a href="{{ route('users.export') }}" class="btn">
Скачать Excel
</a>Чтобы route() работал, дайте роуту имя: ->name('users.export') в файле маршрутов.
Главная ошибка новичка — не проверить объём. На тысяче строк любой подход отработает мгновенно. На двухстах тысячах строкFromCollectionположит память, аFromQueryс чтением порциями — нет. Выбор интерфейса решается до того, как таблица выросла.
Если не получилось
- Class "ZipArchive" not found при скачивании — не установлено расширение
ext-zip. Поставьте его для своей версии PHP и перезапустите php-fpm или сервер. - Скачивается файл с HTML внутри вместо таблицы — в ответ попал отладочный вывод или пробел перед
<?php. Проверьте, что перед открывающим тегом в задействованных файлах нет пустых строк иdd()/echo. - Call to undefined method map() или столбцы идут вперемешку — вы забыли
use ... WithMappingлибо не подключили интерфейс вimplements. Оба нужны вместе: интерфейс объявляет, метод реализует. - Allowed memory size exhausted — большая таблица тянется через
FromCollection. Переключитесь наFromQuery(как в примере) — пакет будет читать записи чанками, а не загонять всё в память разом. - В датах или числах каша — Excel сам интерпретирует форматы. Приводите значения к строке в
map()явно, как сformat('d.m.Y')выше, либо задавайте формат ячеек через отдельный интерфейс форматирования.
Форматы и когда какой брать
| Расширение файла | Формат | Когда |
|---|---|---|
| .xlsx | Excel 2007+ | Нужны несколько листов, стили, формулы |
| .csv | CSV | Импорт в другую систему, минимум веса |
| .xls | Excel 97–2003 | Только если получатель на старом ПО |
Расширение в имени файла и определяет writer — отдельно формат указывать не обязательно. Для больших выгрузок .csv заметно легче: нет XML-обвязки.
Что дальше
Работающую кнопку стоит закрыть авторизацией и подумать о нагрузке. Если выгрузка тяжёлая, пакет умеет отдавать её в очередь через ShouldQueue — тогда файл собирается в фоне, а пользователь не ждёт с зависшей вкладкой. Импорт из Excel обратно в базу — отдельная тема, здесь мы её не трогали; для неё в пакете есть команда make:import и свой набор интерфейсов. За точным списком интерфейсов (стили, ширина колонок, несколько листов) идите в раздел Exporting официальной документации Laravel Excel — там перечислены все concerns для версии 3.1.
Дефектный акт по фото: Осмотр по фотографиям: классификация дефектов, ссылки на нормы, требования к устранению. Готовый акт в Word.
Спросить за 80 ₽Источники: Laravel Excel — официальная документация (Exports), maatwebsite/excel на GitHub
Частые вопросы
У меня другая версия Laravel Excel — 3.0 или старее. Код сработает?
Файл скачивается, но открывается как повреждённый. Что не так?
Как выгрузить не всю таблицу, а результат фильтра или поиска?
На большой таблице падает с Allowed memory size exhausted. Как быть?
Можно ли отдать несколько листов в одном файле?
Обязательно ли ставить расширения PHP, или пакет обойдётся сам?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.