Clean, normalize and properly case personal names before validation in Laravel. Handles the mess that comes from web forms, CSV imports and legacy systems, including Italian quirks like NICOLO' stored instead of Nicolò.
Str::title() was built for titles, not for people. It turns D'ANGELO into D'angelo, keeps invisible characters pasted from a spreadsheet, and happily title cases de Rossi into De Rossi even when the user typed it that way on purpose.
Laravel Name Fixer repairs names once, before they reach your database, and leaves alone what it cannot know for sure.
| Input | Output | Fixer |
|---|---|---|
Rossi\u{200B}, Mario\u{00A0}Rossi |
Rossi, Mario Rossi |
StripInvisible |
D’Angelo, Dall`Oglio |
D'Angelo, Dall'Oglio |
NormalizeApostrophe |
Rossi., Rossi, |
Rossi |
StripTrailingPunctuation |
Mario Rossi |
Mario Rossi |
SquishWhitespace |
Maria - Luisa, Maria – Luisa |
Maria-Luisa |
HyphenSpacing |
LUCA D'ANGELO, sant'elia |
Luca D'Angelo, Sant'Elia |
TitleCase |
NICOLO' CANTU' |
Nicolò Cantù |
AccentFromApostrophe (locale: it) |
de Rossi |
de Rossi |
left alone (mixed case) |
Italian surnames are registered exactly as written: De Rossi and de Rossi are both legal, and so are Lo Presti and Lopresti. From DE ROSSI in capitals there is no way to tell which one is right. The package title cases it to De Rossi and, by default, never touches a name that already comes in mixed case. If the exact spelling matters, let users correct the field.
composer require plin-code/laravel-name-fixerOptionally publish the config file:
php artisan vendor:publish --tag="name-fixer-config"use PlinCode\LaravelNameFixer\Facades\NameFixer;
NameFixer::fix(" LUCA D’ANGELO. ");
// "Luca D'Angelo"
// Get a detailed report
$report = NameFixer::diagnose('MARIO ROSSI');
// $report->original → "MARIO ROSSI"
// $report->fixed → "Mario Rossi"
// $report->appliedFixers → ["title_case"]
// $report->wasModified → true
// Batch processing
$reports = NameFixer::fixMany(['MARIO ROSSI', "d'angelo"]);A drop in replacement for Str::title() when the string is a person's name.
use Illuminate\Support\Str;
Str::fixName("luca d'angelo"); // "Luca D'Angelo"
Str::of(' MARIO ROSSI ')->fixName(); // "Mario Rossi"Fix names every time they are written to a model.
use PlinCode\LaravelNameFixer\Casts\FixedName;
class Customer extends Model
{
protected function casts(): array
{
return [
'first_name' => FixedName::class,
'last_name' => FixedName::class,
];
}
}Register the SanitizeNames middleware to fix name fields in incoming requests before they reach validation.
use PlinCode\LaravelNameFixer\Middleware\SanitizeNames;
Route::middleware(SanitizeNames::class)->group(function () {
Route::post('/register', [RegisterController::class, 'store']);
});By default the middleware targets first_name, last_name, surname, nome, cognome, *_first_name and *_last_name. A plain name field is left out on purpose, because it often holds a company or product name. You can change the list in the config file.
ValidName accepts letters (accented ones included) joined by single spaces, apostrophes or hyphens. It rejects digits, emoji, symbols and doubled separators. It only validates: combine it with the middleware or the cast to also fix the value.
use PlinCode\LaravelNameFixer\Rules\ValidName;
public function rules(): array
{
return [
'first_name' => ['required', 'string', 'max:100', new ValidName],
];
}The message is The :attribute field must be a valid name. and can be translated through your JSON language files.
Old management systems and tax code records store names in uppercase ASCII: NICOLO', FORLI', CANTU'. Enable the Italian locale to turn the trailing apostrophe back into an accent.
// Via config (config/name-fixer.php)
'locale' => 'it',
// Or at runtime
NameFixer::locale('it')->fix("NICOLO' CANTU'");
// "Nicolò Cantù"Only a vowel at the end of a word, preceded by at least two letters, is converted. Elisions like D'Angelo and Dell'Acqua and short particles like de' Medici stay as they are.
A trailing E' becomes è (Mosè, Noè, Giosuè). Switch to é with the locale options:
'locale_options' => ['accentedE' => 'é'],The name-fixer:scan command finds badly formatted names already in your database. It only lists the changes unless you pass --fix.
php artisan name-fixer:scan "App\Models\Customer" --column=first_name --column=last_name --locale=it
php artisan name-fixer:scan "App\Models\Customer" --column=first_name --column=last_name --locale=it --fixRows are read in chunks (--chunk=500 by default) and updated with the query builder, so model events, casts and updated_at are not touched. Run it on a backup or a staging copy first.
$reports = NameFixer::fixMany(array_column($rows, 'last_name'));
foreach ($reports as $index => $report) {
$rows[$index]['last_name'] = $report->fixed;
}return [
// Locale preset: 'it' or null
'locale' => null,
// Named arguments for the locale preset
'locale_options' => [],
// Leave mixed case names ("de Rossi") untouched
'lazy' => true,
// Middleware field patterns
'middleware' => [
'fields' => ['first_name', 'last_name', 'surname', 'nome', 'cognome', '*_first_name', '*_last_name'],
],
];Build your own pipeline with any class that implements PlinCode\LaravelNameFixer\Contracts\FixerInterface:
use PlinCode\LaravelNameFixer\Contracts\FixerInterface;
use PlinCode\LaravelNameFixer\Fixers\SquishWhitespace;
use PlinCode\LaravelNameFixer\Fixers\TitleCase;
use PlinCode\LaravelNameFixer\NameFixer;
class StripHonorifics implements FixerInterface
{
public function fix(string $name): string
{
return preg_replace('/^(dott|sig|ing)\.?\s+/iu', '', $name);
}
public function name(): string
{
return 'strip_honorifics';
}
}
$fixer = new NameFixer([
new SquishWhitespace,
new StripHonorifics,
new TitleCase,
]);The fixers and the pipeline do not depend on Laravel:
use PlinCode\LaravelNameFixer\NameFixer;
NameFixer::defaults()->locale('it')->fix("NICOLO' ROSSI");
// "Nicolò Rossi"composer testPlease see CHANGELOG for more information on what has changed recently.
Please review our security policy on how to report security vulnerabilities.
- Daniele Barbaro
- All Contributors
- Inspired by tamtamchik/namecase
The MIT License (MIT). Please see License File for more information.
