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

Laravel Username Generator Laravel Package

luilliarcec/laravel-username-generator

Laravel Username Generator creates unique, customizable usernames for Laravel apps from names, emails, or custom strings. It handles collisions, supports configurable patterns and validation, and integrates easily with Eloquent models and registration flows.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require <vendor>/<package> and add the HasUsername trait to your authenticatable model (typically App\Models\User). The trait hooks into the Eloquent creating event via a bootHasUsername() method, so no service provider registration is normally required.
  • Look first at: the trait source itself (to see how the value is derived — name, email local-part, random suffix, etc.), any published config file (config/username.php or similar) for length/prefix/column settings, and the migration that adds the username column. Confirm the column is NOT NULL-safe and has a unique index before you rely on it.
  • Verify the migration adds a unique index on username — the generator does not guarantee collision-free output under concurrency; the database constraint is your real safety net.
  • First use case: register a user, let the creating event fire, and confirm a username is populated. Then wire up login: if you authenticate by username, override username() (Fortify) or adjust the credentials() array in your LoginRequest to ['username' => ...].

Implementation Patterns

Standard model setup

class User extends Authenticatable
{
    use HasUsername;
}

Login by username (Fortify)

public function username(): string
{
    return 'username';
}

Route model binding by username

public function getRouteKeyName(): string
{
    return 'username';
}

Factories and seeders — since 6.0.1 the trait always regenerates on creating, a username passed to create() is discarded. For fixtures that need a deterministic handle, set it after the fact:

$user = User::factory()->create();
$user->update(['username' => 'fixture-user']);

For bulk fixtures where you need exact values, bypass events entirely:

DB::table('users')->insert([...]); // no creating event, no generation

Bulk imports — any path that uses insert()/upsert() skips model events, so usernames will be null. Follow the import with a backfill job that iterates models and calls save() (which fires creating only on new models — for existing rows call your generator directly or use update()).

Collision handling — wrap creates in a retry loop that catches Illuminate\Database\QueryException for duplicate-key errors, since the unique index can still reject a generated value.

Testing — assert on the generated column with assertDatabaseHas, and if the generator uses randomness, freeze time or assert a pattern (assertMatchesRegularExpression) rather than an exact string.

Gotchas and Tips

  • 6.0.1 restores "always regenerate". If you adopted 6.0.0, code that relied on a pre-existing username surviving creation (imports, admin-created accounts, factory overrides) is now broken again. Treat 6.0.1 as the corrective release and pin it; do not stay on 6.0.0.
  • Never pass username to create()/updateOrCreate() expecting it to stick. It is overwritten in the creating handler. Explicit values must be applied after the model exists (update(), forceFill()->save(), or saveQuietly()).
  • saveQuietly() / withoutEvents() are the escape hatches when you must control the value during creation — but remember this also suppresses other model events (observers, audit logs).
  • Don't put username in $fillable for user-facing mass assignment. It is generated, and exposing it invites overwrite attempts that silently do nothing.
  • Soft deletes + unique index: a soft-deleted user still occupies its username. Decide whether to suffix on delete or use a partial/composite index; otherwise a recycled handle will throw a QueryException at an unexpected point.
  • Collation/case sensitivity: if your unique index is case-insensitive, normalise (lowercase/trim) before generation, or Alice and alice will collide in confusing ways.
  • Boot method conflicts: bootHasUsername() runs alongside your own booted()/boot() hooks. If you also define a creating listener, ordering is registration order — don't assume your listener sees the final generated value.
  • Debugging: add a temporary listener on User::creating and inspect $model->getDirty(); verify the trait is actually booted (class_uses_recursive) and that your username column exists and isn't silently truncated by length limits (a too-long generated value may be cut off by MySQL non-strict mode and then collide).
  • Extension points: prefer overriding the trait's generator method (or the config values) over copy-pasting the trait. If you need conditional behaviour (e.g. skip generation for SSO users), wrap the trait in your own and guard inside a creating listener registered before the trait's — or simply set the value after creation.
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.
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox