Generating Incremental Usernames

LaravelPosted on

2 min read

When we are working with users or posts, one of the features that we often need is generating usernames or slugs. However handling duplications automatically is not always straightforward. Let’s see how can we use a very simple solution: generating incremental usernames.

Generating Usernames When Persisting a Model

Let’s say we want to generate a username (or a slug) from the user’s name automatically when storing the model into the database. Normally, it’s not that big deal, we can use a simple Eloquent event callback and the Str::slug() helper.

class User extends Authenticatable implements MustVerifyEmail
{
    protected static function booted(): void
    {
        static::creating(static function (self $user): void {
            $user->username = Str::slug($user->name, '.');
        });
    }
}
For slugs, normally we use as a separator, but for usernames it’s more likely a ..

This code works well, and it’s clean and expressive. However what if there are two users with the same name? The usernames should be unique.

Generating Incremental Usernames

With a very simple regex pattern, we can easily track the similar usernames in the database, and add, or increment a numeric suffix to the username. Let’s take a look at the code and update the creating callback in the model.

protected static function booted(): void
{
    static::creating(static function (self $user): void {
        $user->username = static::generateUniqueUsername(
            Str::slug($user->name, '.')
        );
    });
}

protected static function generateUniqueUsername(string $value): string
{
    $username = static::query()
                        ->where('username', 'regexp', preg_quote($value).'[\\d]?$')
                        ->orderByDesc('username')
                        ->take(1)
                        ->value('username');

    $number = (int) filter_var($username, FILTER_SANITIZE_NUMBER_INT);

    return $number === 0 ? $value : $value.++$number;
}
Note, in MySQL we need to use double-backslash: \\.

In the code, we are searching for the “latest” username that matches with the currently generated one, and adds or increments a numeric prefix if needed. So it automatically generates the following pattern: username, username1, username2, username3, and so on.

Closing Thoughts

This is a very simple solution and for simpler applications should work well. However, when you need a more complex solution for slugs or usernames, you might extend this solution or pull in a package.

Need a web developer? Maybe we can help, get in touch!

Looking for web dev job?
You can check them on Jooble.

To see and write comments, you must allow the related (Disqus) cookies. For more information, please visit our privacy policy page.

Similar Posts

More content in Laravel category