tourze/user-id-bundle
A Symfony bundle for managing user identifiers. It provides services and entity integration to generate, store, and resolve unique user IDs, making it easy to attach consistent identifiers to users across your application. Lightweight, configurable, and simple to wire into existing projects.
tourze/user-id-bundle bumped from 0.1.3 to 1.0.0. The release note is a bare changelog link, so treat this as a major-version boundary with unverified breaking changes until you read the diff yourself. Practically, that means:
composer.json first. Tourze publishes Symfony-oriented packages, and the -bundle suffix is the tell: expect a *Bundle class, a DI extension, and service definitions in YAML/XML rather than a Laravel ServiceProvider. That single fact determines whether this is a five-minute install or a bridging exercise.src/ before the README. For ID-generation packages the README usually documents the happy path; the strategy classes, generator interfaces, and any "worker/node id" config are where the real contract lives.^1.0 and diff 0.1.3...1.0.0 locally (git clone + git diff) if the changelog link is the only artifact — a 0.x → 1.0.0 jump is normally where method signatures, config keys, and return types get renamed.First use case: generating a stable, non-sequential-looking user identifier at registration instead of leaking an autoincrement id in URLs, emails, and API responses. Wire it in behind your existing registration action:
// config/app.php or a small dedicated provider
$this->app->singleton(UserIdGenerator::class, function () {
return new UserIdGenerator(/* config from config/user-id.php */);
});
Then assign at creation time in a creating model hook rather than after the insert, so the value is present on the instance your controller returns.
If the package turns out to depend on symfony/* framework contracts at runtime (not just symfony/polyfill), stop and evaluate before writing integration code — you'll be hand-wiring DI rather than using it idiomatically, and that cost should be weighed against a Laravel-native ULID/snowflake generator.
Container binding as the seam. Bind the generator interface as a singleton and always resolve the interface, never the concrete class. This is the difference between a one-line swap when 1.0.0 changes a constructor argument and a grep across the codebase.
Registration flow — generate before persist.
protected static function booted(): void
{
static::creating(function (User $user) {
$user->public_id ??= app(UserIdGenerator::class)->generate();
});
}
Keep the DB autoincrement as the primary key if you like; the generated ID becomes the external identifier. This avoids a painful migration of foreign keys and is the lowest-risk adoption path.
Two-column migration. Add public_id as a nullable, uniquely-indexed string column, backfill existing rows in chunks, then add the NOT NULL constraint in a separate deploy. Never combine the backfill and the constraint in one migration on a table with real traffic.
Testing seam. Provide a deterministic fake in your test suite that returns predictable values, and bind it in TestCase::setUp(). Assertions against generated IDs are otherwise flaky and unreadable. Add one integration test against the real generator that only asserts shape (length, charset, uniqueness across a batch) — that's the test that catches a 1.0.0 behavior change.
Config surface. Map the package's config (node/worker ID, epoch, prefix, alphabet, depending on the strategy) into config/user-id.php and read it via env() only in that file. If the package assumes multiple app servers, the node/worker identifier is the setting that matters most — it's the one that silently causes collisions when left at its default across a horizontally-scaled deployment.
Integration with queues and jobs. If IDs are generated in queued jobs on multiple workers, verify the worker-ID derivation is actually distinct per process. A generator that reads it from a static config file will collide under a queue autoscaler.
-bundle is a Symfony signal, not a Laravel one. Check whether the package ships a ServiceProvider. If not, don't add it to config/app.php providers and hope — wire it manually and accept that you own the glue. Also check whether Doctrine is a hard dependency; an Eloquent app pulling in doctrine/* transitively is a smell worth noticing early.Carbon::setTestNow() in tests are the three ways this surfaces as duplicate IDs or thrown exceptions. If you use time travel in tests, verify the generator cooperates.final and internally instantiated, you're locked in — note that before you build on top of it.1.0.0, trust the source and open an issue.How can I help you explore Laravel packages today?