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

User Id Email Bundle Laravel Package

tourze/user-id-email-bundle

A lightweight Symfony bundle from Tourze that connects user IDs with email addresses, making it easy to store, look up, and resolve user identifiers across your application. Simple service integration and minimal configuration for Doctrine-backed projects.

View on GitHub
Deep Wiki
Context7

Getting Started

tourze/user-id-email-bundle 0.0.1 is a scaffold release: the only published artifact is a compare link, so there are no documented features, BC promises, or migration notes. Read the source before installing — treat the repository as the spec.

What it appears to be: a tiny Symfony bundle supplying a Doctrine entity plus repository that stores a userId → email mapping. It is not a user/auth system; it is a lookup table for correlating an opaque user identifier (SSO subject, legacy ID, external IdP ID) with an email address.

Minimal steps in a Symfony app:

  1. composer require tourze/user-id-email-bundle:0.0.1 — pin the exact version, the API has no stability guarantee at 0.0.x.
  2. Register the bundle in config/bundles.php (Tourze\UserIdEmailBundle\UserIdEmailBundle::class => ['all' => true]).
  3. Confirm the Doctrine mapping path is picked up (check the bundle's DependencyInjection/ extension or AbstractBundle::loadExtension for the mapping directory).
  4. Generate a migration for the table; never rely on doctrine:schema:update for a first install you intend to keep.
  5. Look at src/Entity/UserIdEmail.php and src/Repository/UserIdEmailRepository.php first — they define the entire usable surface.

First use case: you have a user record keyed by an opaque ID (OIDC sub, a UUID from another service, a legacy integer) but downstream systems — notification queues, audit logs, exports — need an email address. Instead of joining across services, you persist the pair here and read it by ID.

Laravel note: despite the assessment brief, this is a Symfony bundle. Laravel's package discovery will not register it and there are no publishable config or migration stubs. In Laravel you either (a) skip the bundle and copy the entity into an Eloquent model, or (b) install it and write a thin service provider that binds the repository and registers a Schema::create migration mirroring the Doctrine mapping. Option (a) is usually cheaper for a two-column table.

Implementation Patterns

Upsert on user lifecycle events. This table is a projection, not a source of truth. Wire it to the event that already knows both values:

  • Symfony: a Doctrine postPersist/postUpdate listener on your User entity, or an event subscriber on your domain's UserCreated/UserEmailChanged events.
  • Laravel: a model observer on saved/created.

The write is always the same shape — look up by userId, update the email if the row exists, insert otherwise. Do not blind-insert; you will accumulate duplicate rows that silently shadow each other on read.

Read with a single-row helper, then guard. The repository is a ServiceEntityRepository, so autowiring works once the bundle is registered. Wrap findOneBy(['userId' => $id]) in a small domain service returning ?string so callers never touch the entity — that boundary is what lets you swap in caching or a different store later.

Batch resolution to avoid N+1. For lists (dashboards, exports, admin tables) fetch once and hydrate:

$rows = $repo->createQueryBuilder('e')
    ->where('e.userId IN (:ids)')
    ->setParameter('ids', $ids)
    ->getQuery()
    ->getResult();
$map = array_column($rows, 'email', 'userId');

Backfill as an idempotent command. Write a console command that pages through your existing users in chunks of ~500 and calls the same upsert path. Because it is idempotent you can re-run it after any incident or after fixing a normalisation bug.

Testing. SQLite in-memory with the bundle's mapping loaded, plus one test asserting that upserting the same userId twice leaves exactly one row and updates the email.

Gotchas and Tips

  • Symfony bundle in a Laravel codebase. No auto-discovery, no vendor:publish, no migrations shipped. Any install in Laravel is a manual bridge; budget for a service provider and a migration rather than expecting it to "just work".
  • 0.0.1 with an empty changelog. The changelog entry is a link to the commit range and nothing else — there is no signal about what changed or what might break. Pin 0.0.1 exactly, diff the source when bumping, and keep a local note of the entity fields you depend on.
  • Uniqueness is your job. A userId → email table is only correct with a unique index on userId. Check whether the entity declares one; if not, add it in your own migration. Under concurrency the read-then-write upsert can race — catch the unique-violation and retry as an update.
  • Email changes need a decision up front. A single row per userId means the previous address is gone. If you need an audit trail (email change history is a compliance concern in most systems), log changes yourself or model the row as append-only with a current flag.
  • Normalise before persisting. Trim and lowercase consistently. Collation differences (MySQL utf8mb4_0900_ai_ci vs. Postgres) make "same" emails compare unequal across environments and produce duplicate rows that look identical to a human.
  • Never treat it as an auth source. No passwords, no tokens, no verification state — only an address. Pair it with your own verification flow; do not send mail to a row you never confirmed.
  • Debugging mapping failures. The most common 0.0.x error is Class ... is not a valid entity or mapped super class, which almost always means the bundle is not registered in config/bundles.php or the extension is not loading the mapping directory. Verify registration before touching the entity annotations.
  • Extension point. Subclass the repository to add a second-level cache or a batch lookup, but check Resources/config/services.yaml for an existing service alias first — redeclaring the repository without overriding that alias gives you a silently unused class.
  • Production schema. The bundle's mapping is the source of truth for column definitions, not for indexes or data. If you need extra columns (timestamps, source system, verification flag), extend the entity via Doctrine inheritance only if you are comfortable upgrading across an unstable 0.0.x line — copying the entity into your own namespace is safer at this stage.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo