Change the storage path in Laravel 5

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company
# Mastering Storage Paths in Laravel 5: Fixing Configuration Hurdles As developers working with legacy frameworks like Laravel 5, we often encounter situations where the core framework structure conflicts with our desired application architecture. One very common desire is to decouple application storage—moving files out of the repository and into a more manageable location specified by configuration. The specific challenge revolves around dynamically setting the storage path using configuration values within the early bootstrap process. Let’s dive into why attempts to use `config()` during the initial loading phase fail in Laravel 5, and how we can achieve this cleanly. ## The Storage Path Evolution in Laravel In older versions of Laravel, managing paths was often handled through specific files like `bootstrap/paths.php`. This provided a simple, static way to define where application assets should reside. However, as applications grow, relying on hardcoded or statically defined paths becomes cumbersome and less flexible. Laravel 5 introduced a more service-oriented approach, utilizing the Service Container to manage dependencies. To achieve dynamic path setting via configuration—for instance, reading from `config('app.storage_path')`—we need to ensure that the configuration system is fully loaded before we attempt to access it in the application bootstrap file (`bootstrap/app.php`). ## Why Direct Configuration Access Fails The initial attempts often lead developers down a rabbit hole of exceptions. When you try to call `config('...')` during the very early boot sequence, the necessary configuration files might not have been fully loaded or registered by the time that specific code runs. This is precisely why you encounter errors like `Uncaught exception 'ReflectionException' with message 'Class config does not exist'`. The subsequent attempts—such as booting later or binding paths directly—show us an incomplete solution: ```php // Attempt 1: Booting late (Did not work for storage paths) $app->booted(function () use ($app) { $app->useStoragePath(config('app.storage_root')); // Fails if config isn't ready yet }); // Attempt 2: Binding the path (Partial success, only fixed views) $app->bind('path.storage', function ($app) { return config('app.storage_root'); }); ``` While binding works for specific components like view caching, it doesn't address the core requirement of setting the default storage location for file operations (like logs or uploaded files). This highlights a fundamental principle in framework design: services and configurations must be resolved in the correct order. ## The Correct Approach: Leveraging Service Providers The robust solution involves hooking into Laravel’s lifecycle correctly, ensuring that configuration resolution happens when it is guaranteed to be available. Instead of trying to access the config directly in `bootstrap/app.php`, we should leverage a dedicated Service Provider that executes later in the boot sequence, once all core services are initialized. We can create a custom Service Provider that resolves the storage path and binds it where needed. This aligns perfectly with the dependency injection philosophy promoted by the Laravel team on the official site: [https://laravelcompany.com](https://laravelcompany.com). Here is how you would implement this cleanly within your application structure: ```php // In app/Providers/StoragePathServiceProvider.php namespace App\Providers; use Illuminate\Support\ServiceProvider; class StoragePathServiceProvider extends ServiceProvider { /** * Register any services. */ public function register(): void { // Bind the