Looking to hire Laravel developers? Try LaraJobs

laravel-sanitizer maintained by hadikhanzadeh

Description
Recursive, filter-based input sanitization for Laravel applications, with per-field rules and dot-notation support.
Last update
2026/08/28 15:51 (dev-main)
License
Links
Downloads
9

Comments
comments powered by Disqus

Laravel Sanitizer

Latest Version on Packagist Tests Total Downloads License

Recursive, filter-based input sanitization for Laravel applications — with per-field rules, dot-notation support for nested data, and a FormRequest trait for zero-boilerplate integration.

Why this package

Cleaning request input in Laravel usually ends up as ad-hoc calls to trim() and strip_tags() scattered across controllers, or a single monolithic sanitizer class that's hard to extend. This package instead treats each sanitization step as a small, testable, swappable class — registered through config, resolved through the container, and safe for config:cache.

It's a spiritual successor to the now-unmaintained waavi/sanitizer, rebuilt for PHP 8.4 and Laravel 12/13 with an interface-based filter architecture.

Requirements

  • PHP 8.4+
  • Laravel 12.x or 13.x

Installation

composer require hadikhanzadeh/laravel-sanitizer

The service provider is auto-discovered — no manual registration needed.

Optionally publish the config file to customize registered filters or defaults:

php artisan vendor:publish --tag=sanitizer-config

Basic usage

Resolve the Sanitizer service directly:

use HadiKhanzadeh\LaravelSanitizer\Sanitizer;

$sanitizer = app(Sanitizer::class);

$clean = $sanitizer->clean([
    'name' => '  <b>Hadi</b>  ',
    'bio'  => '<script>alert(1)</script><p>Hello</p>',
]);

// ['name' => 'Hadi', 'bio' => 'Hello']

Or use the facade:

use HadiKhanzadeh\LaravelSanitizer\Facades\Sanitizer;

$clean = Sanitizer::clean($request->all());

Automatic sanitization in FormRequests

Add the SanitizesInput trait to any FormRequest to sanitize its payload automatically before vHadidation runs:

use HadiKhanzadeh\LaravelSanitizer\Concerns\SanitizesInput;
use Illuminate\Foundation\Http\FormRequest;

final class StoreProductRequest extends FormRequest
{
    use SanitizesInput;

    public function rules(): array
    {
        return [
            'name' => ['required', 'string'],
        ];
    }
}

Per-field rules

Override sanitizationRules() to control which filters run on specific fields:

protected function sanitizationRules(): array
{
    return [
        'description' => ['editor'],
        'title' => ['trim', 'strip_tags'],
    ];
}

Nested fields (dot notation)

protected function sanitizationRules(): array
{
    return [
        'address.postal_code' => ['trim'],
    ];
}

Changing the default pipeline

Fields without an explicit rule fall back to config('sanitizer.default_filters') (trim, strip_tags by default). Override per request:

protected function defaultSanitizationFilters(): ?array
{
    return ['trim'];
}

Opting out

protected bool $sanitizeInput = false;

Before/after hooks

protected function beforeSanitization(): void
{
    // runs before the Sanitizer touches the payload
}

protected function afterSanitization(): void
{
    // runs after sanitization, before vHadidation
}

Built-in filters

Name Class Description
trim TrimFilter Trims leading/trailing whitespace.
strip_tags StripTagsFilter Removes all HTML/PHP tags.
stripslashes StripSlashesFilter Removes backslashes. Registered but not in the default pipeline — a legacy filter, opt in per-field only if needed.
editor EditorFilter Sanitizes rich-text HTML via mews/purifier, stripping dangerous attributes (onclick, javascript: URLs) that a plain tag allow-list would miss. Requires composer require mews/purifier and a purifier.editor config preset.

Note: htmlspecialchars is intentionally not included. Escaping is an output-layer concern (Blade, API resources) — encoding on input causes double-encoding when the value is escaped again later.

Adding a custom filter

Implement SanitizationFilter:

namespace App\Sanitization\Filters;

use HadiKhanzadeh\LaravelSanitizer\Contracts\SanitizationFilter;

final readonly class LowercaseFilter implements SanitizationFilter
{
    public function apply(mixed $value): mixed
    {
        return is_string($value) ? mb_strtolower($value) : $value;
    }
}

Register it in config/sanitizer.php:

'filters' => [
    // ...
    'lowercase' => \App\Sanitization\Filters\LowercaseFilter::class,
],

Use it like any other filter name in your rules.

Testing

composer test

License

MIT. See LICENSE.md.