1. Install the package
composer require vcian/laravel-word-refiner
The service provider is auto-discovered on Laravel 8+, so there is no manual registration step. Confirm the package appears under vendor/vcian/laravel-word-refiner and check its composer.json for the supported Laravel/PHP matrix before committing, since the last tagged release is from April 2023.
2. Publish the configuration
php artisan vendor:publish --provider="Vcian\LaravelWordRefiner\WordRefinerServiceProvider"
This drops a config file (typically config/word-refiner.php) containing the dictionary of words the package should match and/or the replacement character used when refining a string. Open it first — it is the single most important file to understand.
3. First use case: sanitizing user-generated text
The canonical scenario is taking a raw string (a comment, review, chat message, product Q&A) and returning a refined version with the configured words masked or replaced:
use Vcian\LaravelWordRefiner\Facades\WordRefiner;
$clean = WordRefiner::refine('This is a really stupid product');
// "This is a really ****** product"
Where to look first, in order:
README.md — confirm the exact facade alias and method names (refine, find, etc.); naming has changed between minor versions.config/word-refiner.php — the word list and mask character.src/ — the package is small; read the main service class top to bottom. You will likely understand the entire package in under ten minutes.tests/ — useful as executable documentation for edge cases the author cared about.Wrap it in your own service. Given the package's size and age, do not call the facade directly from 30 controllers. Create a thin ContentSanitizer service that delegates to WordRefiner and exposes the methods your app actually needs. When the package stalls or you outgrow it, you swap one class instead of grepping the codebase.
namespace App\Services;
use Vcian\LaravelWordRefiner\Facades\WordRefiner;
class ContentSanitizer
{
public function clean(string $text): string
{
return WordRefiner::refine($text);
}
public function isClean(string $text): bool
{
return $this->clean($text) === $text;
} // or however the package exposes detection, per the README
}
Custom validation rule. Refining on display is not enough — you usually want to reject or flag submissions at the edge:
class CleanContent implements ValidationRule
{
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (! app(ContentSanitizer::class)->isClean((string) $value)) {
$fail('Please remove inappropriate language.');
}
}
}
Attach this inside a FormRequest alongside your other rules so the check lives with the rest of the validation contract.
Middleware for request-level refinement. If you would rather sanitize than reject, a middleware that walks $request->all() and refines string fields (recursively for nested arrays) keeps controllers clean. Guard it carefully: skip file uploads, JSON payloads you do not own, and anything in $request->route().
Model-level hook. For model writes that bypass HTTP (console commands, imports, queued jobs), a saving observer on the relevant models is more reliable than middleware:
public function saving(Comment $comment): void
{
$comment->body = app(ContentSanitizer::class)->clean($comment->body);
}
Keep the original in a separate column (body_raw) if moderation, appeals, or audit trails matter.
Bulk backfill. For existing rows, write a one-off artisan command that chunks by ID and updates in batches. Run it inside a transaction per chunk and never in a single query — a 500k-row update through PHP will time out.
Blade / API output. For legacy data you did not sanitize on write, apply the refiner in an accessor or API Resource so the raw value is never rendered. Do not refine in Blade directly; it hides the behavior from anyone reading the controller.
Testing. Add a small test dataset of known-good and known-bad strings and assert both directions (clean passes, dirty is refined). This becomes your regression suite when you upgrade Laravel or the package.
strtolower assumptions break on Turkish İ and similar.php artisan config:cache must be re-run. A stale cached config means your new words silently do nothing.refine() in a loop over large text bodies.composer why-not vcian/laravel-word-refiner and re-run your regression tests. If support lags, replacing the package with a 50-line service over your own word list is a realistic option — the abstraction layer recommended above makes that swap cheap.How can I help you explore Laravel packages today?