Installation:
composer require mews/purifier
First Use Case: Sanitize user input (e.g., form submissions, comments):
use Mews\Purifier\Facades\Purifier;
$cleanHtml = Purifier::clean($userInput);
div, a, p, etc.) and CSS (e.g., font, color).Where to Look First:
php artisan vendor:publish --provider="Mews\Purifier\PurifierServiceProvider".Purifier::clean($html, $configKey) for dynamic sanitization.CleanHtml, CleanHtmlInput, or CleanHtmlOutput in Eloquent models (Laravel 7+).Request Sanitization:
public function handle($request, Closure $next) {
$request->merge([
'content' => Purifier::clean($request->content, 'default')
]);
return $next($request);
}
Dynamic Configs:
titles, youtube) or pass custom arrays:
// Allow IDs in headings
Purifier::clean($html, ['Attr.EnableID' => true]);
// Custom URI filtering (e.g., allow only YouTube/Vimeo iframes)
Purifier::clean($html, 'youtube');
Eloquent Integration:
save()/get():
protected $casts = [
'description' => CleanHtmlInput::class, // Sanitize on input
'formatted_content' => CleanHtmlOutput::class, // Sanitize on output
];
URI Filtering:
Purifier::clean($html, 'default', function ($config) {
$config->getDefinition('URI')->addHost($config, 'trusted-domain.com');
});
Blade Directives: Create a custom directive for templated sanitization:
Blade::directive('clean', function ($html) {
return "<?php echo Purifier::clean($html, 'default'); ?>";
});
Usage:
{!! clean($userHtml) !!}
API Responses: Sanitize before JSON serialization:
return response()->json([
'content' => Purifier::clean($request->content)
]);
Testing: Mock the facade for unit tests:
$this->app->instance('Purifier', Mockery::mock('Mews\Purifier\Facades\Purifier'));
Performance:
cachePath in config to avoid recompiling definitions on every request.memory_get_usage().Config Overrides:
array_merge to extend defaults:
$config = array_merge(config('purifier.settings.default'), ['Attr.EnableID' => true]);
Purifier::clean($html, $config);
XSS Edge Cases:
HTML.Allowed, malicious scripts can slip through via onerror or style attributes. Use HTML.SafeObject or HTML.Safe sparingly.$config->getDefinition('URI')->addFilter(new HTMLPurifier_URIFilter_DataURI());
Eloquent Casts:
CleanHtml runs on both get/set. Use CleanHtmlInput/Output separately to avoid redundant passes.Validation Errors: HTMLPurifier throws HTMLPurifier_Exception for malformed input. Catch and log:
try {
Purifier::clean($html);
} catch (HTMLPurifier_Exception $e) {
Log::error('Purifier error: ' . $e->getMessage());
return back()->withInput();
}
Config Validation: Use HTMLPurifier_Config::validate() to check configs before runtime:
$config = HTMLPurifier_Config::create($settings);
$config->validate();
Custom Definitions:
details/summary for HTML5):
$config->define('custom_definition', [
'elements' => [
['details', 'Block', 'Flow', 'Common'],
['summary', 'Inline', 'Flow', 'Common'],
],
]);
Filter Chains:
$html = strip_comments($html);
$html = Purifier::clean($html);
Event Hooks:
purifier.clean events to log sanitized content:
Purifier::clean($html)->then(function ($cleaned) {
Log::debug('Sanitized HTML:', ['content' => $cleaned]);
});
Profile Configs: Use HTMLPurifier_Config::getHTMLDefinition() to inspect active rules:
$definition = Purifier::getConfig('default')->getHTMLDefinition();
dd($definition->getElement('a')->getAttributes());
Fallbacks: Provide fallback HTML for invalid input:
$cleaned = Purifier::clean($html, 'default');
$cleaned = $cleaned ?: '<p>No valid content provided.</p>';
Laravel 11+: Leverage app('purifier') for container binding:
$this->app->bind('purifier', function () {
return Purifier::getConfig('strict');
});
How can I help you explore Laravel packages today?