How to setup PhpSpreadsheet in Laravel

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company
# How to Setup PhpSpreadsheet in Laravel: Binding Services for Seamless Integration As a senior developer, I often find myself setting up complex packages within a Laravel application. Installing a package via Composer is just the first step; the real challenge lies in integrating that functionality correctly into the framework's architecture. When dealing with heavy libraries like PhpSpreadsheet—which handles complex Excel file manipulation—we don't want to scatter the logic throughout our controllers. Instead, we leverage Laravel’s powerful Service Container to bind these dependencies cleanly. This guide will walk you through the professional method for setting up PhpSpreadsheet so you can easily inject and use it within your Laravel application, following best practices outlined by the Laravel community. ## Why Use a Service Provider? When you install a package via Composer, it provides classes and interfaces. To make these components available globally across your application without manual `new` calls everywhere, we use a **Service Provider**. A Service Provider is essentially a dedicated class where you register bindings (dependencies) into the Laravel Service Container. This adheres to the Dependency Injection principle, making your code more testable, maintainable, and scalable. ## Step 1: Create Your Custom Service Provider First, create a new service provider dedicated to handling file operations or spreadsheet tasks. You can use the Artisan command for this: ```bash php artisan make:provider SpreadsheetServiceProvider ``` This command generates a new file in your `app/Providers` directory. Open this file and define the binding within the `register` method. ## Step 2: Binding PhpSpreadsheet into the Container Inside your newly created `SpreadsheetServiceProvider`, you will tell Laravel how to resolve the `PhpOffice\PhpSpreadsheet\Spreadsheet` class whenever it is requested. Here is the core code for your service provider: ```php // app/Providers/SpreadsheetServiceProvider.php namespace App\Providers; use Illuminate\Support\ServiceProvider; use PhpOffice\PhpSpreadsheet\Spreadsheet; class SpreadsheetServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { // Bind the Spreadsheet class to an interface or directly, depending on your preference. // Binding it makes it available for automatic dependency injection. $this->app->bind(Spreadsheet::class, function ($app) { return new Spreadsheet(); }); } /** * Bootstrap any application services. * * @return void */ public function boot() { // No specific setup needed here unless you have configuration files to load. } } ``` **Developer Insight:** Notice how we use `$this->app->bind(...)`. This is the mechanism that registers our dependency with the container. This approach ensures that any class needing a `Spreadsheet` object can simply request it via its constructor, and Laravel will handle injecting the correctly instantiated object. This level of abstraction is what makes frameworks like Laravel so powerful for building robust applications. ## Step 3: Registering the Service Provider The final step is telling Laravel to load your new provider when the application boots up. Open your main configuration file, `config/app.php`, and add your new provider to the `providers` array: ```php // config/app.php /* |-------------------------------------------------------------------------- | Service Providers |-------------------------------------------------------------------------- | | This array of service providers is loaded by the application. | */ 'providers' => [ // ... other providers App\Providers\SpreadsheetServiceProvider::class, // <-- Add your new provider here ], ``` ## Step 4: Using PhpSpreadsheet in a Controller Now that the dependency is correctly registered in the container, using it in your controller becomes simple and clean. You will inject the class directly via the constructor (or method signature), avoiding manual instantiation and keeping your business logic focused on what matters. ```php // app/Http/Controllers/ExportController.php namespace App\Http\Controllers; use Illuminate\Http\Request; use PhpOffice\PhpSpreadsheet\Spreadsheet; // Import the necessary class class ExportController extends Controller { public function export(Request $request) { // 1. Resolve the dependency from the container (or inject it if bound correctly) $spreadsheet = app(Spreadsheet::class); // 2. Perform your operations on the object $sheet = $spreadsheet->getActiveSheet(); $sheet->setCellValue('A1', 'Report Title'); $sheet->setCellValue('B1', 'Data Point'); // 3. Handle file output (e.g., saving to disk) $writer = \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet); $writer->save('report.xlsx'); return response()->download('report.xlsx'); } } ``` ## Conclusion Setting up external libraries in Laravel is less about manually adding code to `app.php` and more about understanding the Service Container. By utilizing Service Providers, you decouple your application logic from specific library implementations, resulting in cleaner, more maintainable, and highly testable code. Always aim to use dependency injection for complex objects like PhpSpreadsheet to keep your controllers focused on handling HTTP requests rather than managing file operations within their scope. Happy coding!