Sanitize Filenames with Laravel’s String Helper Chain

📖 2 minutes read

When generating filenames from dynamic input—user-provided names, database values, or API responses—a three-step Laravel string helper chain ensures clean, filesystem-safe output.

The pattern combines Str::lower(), Str::slug(), and Str::title() to handle edge cases you might not think of:

use Illuminate\Support\Str;

class FileGenerator
{
    public static function sanitizeFilename(string $name): string
    {
        return Str::title(Str::slug(Str::lower($name), '_'));
    }
}

// Examples
FileGenerator::sanitizeFilename('Q4 Sales Report');
// Returns: 'Q4_Sales_Report'

FileGenerator::sanitizeFilename('User Analytics (2024)');
// Returns: 'User_Analytics_2024'

FileGenerator::sanitizeFilename('Employee List - HR Dept.');
// Returns: 'Employee_List_Hr_Dept'

FileGenerator::sanitizeFilename('Données françaises');
// Returns: 'Donnees_Francaises'

Why this three-step chain works:

  1. Str::lower() normalizes case to avoid filesystem issues on case-sensitive systems (Linux servers are case-sensitive, Windows/Mac are not)
  2. Str::slug() converts to URL-safe format, replacing spaces and special characters with your chosen separator (underscore here)
  3. Str::title() capitalizes words for readable filenames without breaking filesystem compatibility

Real-world usage with timestamps:

class ReportExporter
{
    public function export(string $reportName, array $data): string
    {
        $filename = FileGenerator::sanitizeFilename($reportName) 
                    . '_' . now()->format('Y-m-d_His') 
                    . '.csv';
        
        Storage::put("exports/{$filename}", $this->toCsv($data));
        
        return $filename;
    }
}

// Output: 'Monthly_Revenue_2024-03-05_093045.csv'

Why not just use Str::slug() alone?

Plain Str::slug() would give you 'q4-sales-report' (all lowercase). The Str::title() step makes filenames more readable when users download them. Compare:

  • Without title case: employee_performance_report.csv
  • With title case: Employee_Performance_Report.csv

The second is clearer at a glance in file explorers.

Alternative separators:

You can use hyphens instead of underscores by changing the second parameter to Str::slug():

return Str::title(Str::slug(Str::lower($name), '-'));

This is common for web-facing URLs. Underscores are traditional for downloaded files, but both work fine for filesystems.

Daryle De Silva

VP of Technology

11+ years building and scaling web applications. Writing about what I learn in the trenches.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *