Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Directory Cleanup Laravel Package

spatie/laravel-directory-cleanup

Automatically delete old files from specified directories in Laravel. Configure per-path age limits (in minutes) via a published config file, then run cleanup to keep temp, cache, and upload folders tidy. Supports auto service provider registration in Laravel 5.5+.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/laravel-directory-cleanup
    

    Publish the config file:

    php artisan vendor:publish --provider="Spatie\DirectoryCleanup\DirectoryCleanupServiceProvider"
    
  2. Configure Directories: Edit config/directory-cleanup.php to define directories and their retention rules:

    'directories' => [
        'storage/logs' => [
            'max_age_in_days' => 30,
            'dry_run' => false,
        ],
        'storage/framework/cache' => [
            'max_age_in_days' => 7,
            'dry_run' => false,
        ],
    ],
    
  3. First Run: Schedule the cleanup in app/Console/Kernel.php:

    protected function schedule(Schedule $schedule)
    {
        $schedule->command('directory:cleanup')->daily();
    }
    

    Run manually:

    php artisan directory:cleanup
    

First Use Case

Clean up old logs and cache files automatically. Start with dry_run: true to preview deletions before enabling actual cleanup.


Implementation Patterns

Workflows

  1. Directory-Specific Cleanup: Use the package to target specific directories (e.g., logs, uploads, backups) with custom retention policies:

    'directories' => [
        'storage/app/public/uploads' => [
            'max_age_in_days' => 90,
            'only' => ['*.jpg', '*.png'], // Optional: Filter file extensions
        ],
    ],
    
  2. Dynamic Configuration: Override config values per environment (e.g., config/directory-cleanup.php):

    if (app()->environment('production')) {
        $config['directories']['storage/logs']['max_age_in_days'] = 7;
    }
    
  3. Manual Triggers: Call the cleanup programmatically (e.g., in a controller or command):

    use Spatie\DirectoryCleanup\DirectoryCleanup;
    
    DirectoryCleanup::cleanup();
    
  4. Event-Based Cleanup: Hook into Laravel events (e.g., job.failed) to trigger cleanup:

    Event::listen('job.failed', function () {
        DirectoryCleanup::cleanup(['storage/logs']);
    });
    

Integration Tips

  • Logging: Wrap cleanup in a try-catch block and log failures:
    try {
        DirectoryCleanup::cleanup();
    } catch (\Exception $e) {
        Log::error('Directory cleanup failed: ' . $e->getMessage());
    }
    
  • Testing: Use dry_run: true in tests to verify behavior without side effects:
    $this->artisan('directory:cleanup')->expectsOutput('Would delete...');
    
  • Artisan Commands: Extend the base command for custom logic:
    php artisan make:command CustomCleanupCommand
    
    public function handle() {
        DirectoryCleanup::cleanup(['custom/path']);
    }
    

Gotchas and Tips

Pitfalls

  1. Permissions: Ensure the Laravel process has write permissions for target directories. Use chmod or chown if needed:

    chmod -R 755 storage/
    

    Debug: Check logs for Permission denied errors.

  2. Symbolic Links: The package follows symlinks by default. Disable with:

    'follow_symlinks' => false,
    

    Tip: Test with dry_run: true first to avoid unintended deletions.

  3. Concurrent Runs: Avoid running cleanup multiple times simultaneously (e.g., via cron + scheduled task). Use a lock:

    if (!file_exists(storage_path('directory_cleanup.lock'))) {
        file_put_contents(storage_path('directory_cleanup.lock'), 'locked');
        DirectoryCleanup::cleanup();
        unlink(storage_path('directory_cleanup.lock'));
    }
    
  4. Hidden Files: The package skips hidden files (e.g., .env). To include them, override the isHidden() method in a custom cleaner:

    use Spatie\DirectoryCleanup\Cleaners\Cleaner;
    
    class CustomCleaner extends Cleaner {
        public function isHidden(string $path): bool {
            return false;
        }
    }
    

Debugging

  • Dry Runs: Always use dry_run: true during development to preview deletions:
    'dry_run' => env('APP_ENV') !== 'production',
    
  • Verbose Output: Enable debug mode in the config:
    'debug' => true,
    
  • Logging: Check Laravel logs for skipped files or errors:
    tail -f storage/logs/laravel.log | grep "DirectoryCleanup"
    

Extension Points

  1. Custom Cleaners: Extend the base Cleaner class to add logic (e.g., exclude specific files):

    class ExcludeTempCleaner extends Cleaner {
        public function shouldBeDeleted(string $path): bool {
            return parent::shouldBeDeleted($path) && !Str::contains($path, 'temp_');
        }
    }
    

    Register in config/directory-cleanup.php:

    'cleaners' => [
        \App\Cleaners\ExcludeTempCleaner::class,
    ],
    
  2. Pre/Post Hooks: Use Laravel events to run logic before/after cleanup:

    Event::listen('directory.cleanup.starting', function () {
        Log::info('Starting directory cleanup...');
    });
    Event::listen('directory.cleanup.finished', function () {
        Log::info('Directory cleanup completed.');
    });
    
  3. Dynamic Retention: Fetch max_age_in_days from a database or API:

    $config['directories']['storage/logs']['max_age_in_days'] = Setting::get('log_retention_days');
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport