Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Full Name Parser Laravel Package

adci/full-name-parser

A PHP package for parsing full names into first, middle, last, prefix, and suffix components. It handles common name formats, titles, and suffixes, making it easy to split user-provided names for storage, search, or display in Laravel and other PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Install with Composer (no Laravel auto-discovery, no config file, no service provider):

composer require adci/full-name-parser

The entire public surface is two classes: ADCI\FullNameParser\Parser and the Name value object it returns. Instantiate the parser once and call parse():

use ADCI\FullNameParser\Parser;

$parser = new Parser();
$name = $parser->parse('Dr. Juan de la Cruz Jr.');

$name->getSalutation(); // "Dr."
$name->getFirstName();  // "Juan"
$name->getMiddleName(); // "de la"
$name->getLastName();   // "Cruz"
$name->getSuffix();     // "Jr."

Look first at src/Parser.php (the splitting heuristics) and the returned Name object's getters — that is the complete API you will build against. Then skim the package's test fixtures: they document exactly which name shapes the parser handles (compound surnames, quoted nicknames, suffixes), which is more useful than the README when deciding whether to trust it for your data.

First realistic use case: a CRM/contacts table with a single full_name column, where you need sortable last_name and personalized greetings (first_name). Parse on write, keep the raw string, and store the parts alongside it.

Register it as a singleton so you don't rebuild the parser per row:

// AppServiceProvider::register()
$this->app->singleton(\ADCI\FullNameParser\Parser::class, fn () => new \ADCI\FullNameParser\Parser());

Implementation Patterns

Wrap it in your own service, never call it from controllers/models directly. The package has no interface and no injection points; a thin NameParser wrapper lets you swap it later and gives you one place for normalisation and fallback logic.

final class ParsedName
{
    public function __construct(
        public readonly ?string $salutation,
        public readonly ?string $first,
        public readonly ?string $middle,
        public readonly ?string $last,
        public readonly ?string $suffix,
    ) {}
}

final class NameParser
{
    public function __construct(private \ADCI\FullNameParser\Parser $parser) {}

    public function parse(string $full): ParsedName
    {
        $n = $this->parser->parse(trim($full));

        return new ParsedName(
            $n->getSalutation() ?: null,
            $n->getFirstName() ?: null,
            $n->getMiddleName() ?: null,
            $n->getLastName() ?: null,
            $n->getSuffix() ?: null,
        );
    }
}

Parse at the boundary, persist normalised. Do the parsing in a form request, an import job, or a model observer — not on every read. Persist full_name (source of truth) plus first_name, middle_name, last_name, salutation, suffix. That way re-parsing later (e.g. after a parser upgrade) is a backfill job, not a data loss event.

Use it as a triage signal, not a verdict. A good pattern for imports is to flag rows where the parser produced something suspicious:

$parsed = $this->nameParser->parse($row['name']);
$needsReview = $parsed->last === null || $parsed->first === null;

Batch imports: chunk the source (->chunkById(500, ...)), reuse the same singleton parser, and collect failures rather than aborting the whole import on one weird name.

Sorting and search: once last_name is populated, index it. For display, keep a formatted_name() accessor that prefers the original full_name and falls back to recombining the parts — the parser can "correct" a name into something the user never typed (e.g. moving "de la" into the middle name), so don't silently replace what they entered.

Testing: use a PHPUnit data provider with the real-world names you care about (your actual customer base, not just John Smith). This is the cheapest way to discover the package's failure modes before production does.

Gotchas and Tips

  • Names are not deterministic. Any parser that splits on whitespace and a salutation/suffix dictionary will get some names wrong. Treat the output as a best guess and always retain the original string.
  • Nulls, not empty strings. Getters return null when a part is absent; : string type hints and strlen() calls will blow up. Coalesce (?: null) at the boundary as shown above.
  • Mononyms and single tokens. parse('Cher') will put the token in one field and leave the rest null — decide what "last name" means for your UI before this becomes a bug report.
  • Compound surnames and particles. "de la Cruz", "van der Berg", "bin Salman", "Al-Rashid" are the classic weak spot. Check the fixtures for the specific languages you serve; if your user base is heavily non-Anglo, budget a review queue.
  • "Last, First" input. A comma usually flips the order in people's heads, but don't assume the parser handles it — normalise input yourself (detect the comma and swap) before calling parse().
  • Suffixes vs. last names. III, Jr., Ph.D. and a surname like "Young" are indistinguishable without a dictionary; verify getSuffix() before trusting the split.
  • Salutations and nicknames. Titles like "Dr.", "Prof.", "Capt." and quoted nicknames ("Bob") are recognised by dictionary — anything outside it (e.g. "Rev. Dr.", emoji, honorifics in other languages) will leak into the first-name field.
  • Encoding. Ensure input is UTF-8 and trimmed. Accented and non-Latin names may round-trip fine but case-folding and mb_* handling is on you, not the package.
  • Reuse the parser. Constructing Parser per row in a 100k-row import is wasted work; bind it as a singleton.
  • Maintenance risk. Last release was November 2019. Pin the version in composer.json, add your own tests around the behaviour you depend on, and verify it on your PHP version (8.x) before committing — the algorithm is simple enough to vendor or fork if a PHP upgrade ever breaks it.
  • Extending behaviour. There is no config or extension point for custom salutation/suffix lists; the practical approach is pre-processing (strip known titles yourself), post-processing (fix known-surname patterns), or subclassing Parser if the internals allow it. Keep the wrapper in place so either is a one-file change.
  • Debugging. When a name parses unexpectedly, dump the whole Name object rather than individual getters — it shows you which dictionary rule fired and makes the failure obvious.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle