pdfloresjdav/multi-user-bundle
A Symfony bundle for managing multiple users in your application, with tools for user accounts, authentication, roles, and profile handling. It helps organize shared-user setups and simplifies common multi-user workflows so you can integrate user management faster.
Read this first: it is a Symfony bundle, not a Laravel package. pdfloresjdav/multi-user-bundle is a fork of PUGX/MultiUserBundle, built to extend FOSUserBundle inside a Symfony kernel. It depends on symfony/framework-bundle, friendsofsymfony/user-bundle, and Doctrine. There is no service provider, no facade, no config/multi-user.php. Attempting composer require pdfloresjdav/multi-user-bundle in a Laravel project will either fail dependency resolution or drag in FOSUserBundle, which expects a Symfony container and will not boot under Laravel's kernel.
So the honest "getting started" depends on which side you are on:
DependencyInjection/ and Resources/config/, and reimplement the discriminator pattern yourself (see the next section). Do not try to shoehorn it in.composer.json first to confirm the Symfony/FOSUserBundle version constraints, then the bundle's DependencyInjection/Configuration.php for the pugx_multi_user config tree, then upstream PUGX/MultiUserBundle docs — this fork ships no meaningful README, so upstream is your only documentation.First use case (the bundle's reason to exist): multiple user types sharing one authentication entry point. A Buyer and a Seller both authenticate through the same login form, but resolve to different entities with different fields, and route to different dashboards. That is the whole feature.
Minimal Symfony wiring, for context: require FOSUserBundle + this bundle, declare pugx_multi_user with your per-type user classes, have each entity extend the configured base user, and register the UserDiscriminator service that picks the entity based on a submitted field. Nothing here maps onto Laravel's Auth facade.
Since the package itself is not usable from Laravel, the real deliverable is the pattern it encodes — which is genuinely worth copying.
Pattern 1 — Discriminator column on a single users table (simplest, recommended for most Laravel apps).
users table gains user_type (enum/string) plus a nullable union of type-specific columns, or — cleaner — type-specific data lives in separate profile tables.UserProvider (extend EloquentUserProvider) reads user_type from the credential payload and scopes the query: ->where('user_type', $type).LoginController with per-type FormRequest validation, or separate guards (buyer, seller) declared in config/auth.php — this is the Laravel-native analogue of the bundle's multiple user managers.Auth::guard('seller')->attempt(...) rather than one giant conditional.Pattern 2 — Polymorphic profile (single table inheritance in spirit).
users holds credentials + user_type; buyer_profiles / seller_profiles hold role data via a profile() morphTo.UserTypeResolver service keyed off user_type, injecting a ProfileRepository per type — mirrors the bundle's UserManager per class.Route::get('/seller/{seller}', ...) with an explicit Seller binding, or a global scope filtering by type.Pattern 3 — Doctrine-style inheritance, if you insist on Symfony.
User as MappedSuperclass, Buyer/Seller as @InheritanceType("JOINED") entities.pugx_multi_user.users.<name>.entity per class and let UserDiscriminator resolve the class from the registration form.Integration tips for Laravel:
users.auth:sanctum works fine; issue tokens from the discriminated user, and stamp the guard/type into the token's abilities so you can authorize per type.user_type before any seeders, and backfill existing rows in the same migration.Package-level red flags (why this fork specifically is a liability):
ServiceProvider, no config publishing, no facade, no Auth integration. Any "Laravel usage" article claiming otherwise is mistaken.PUGX/MultiUserBundle, which itself is thinly documented and effectively unmaintained.If you are actually running it in a Symfony app:
pugx_multi_user config, bin/console cache:clear — the discriminator mapping is compiled into the container, and stale caches produce "service not found" errors that look like code bugs.JOINED inheritance with doctrine:schema:update produces dangling foreign keys; use migrations, not schema diffing, in any real environment.UserDiscriminator trusts a form field to pick the entity class. Validate that discriminator server-side against a whitelist — never pass it through from the request unvalidated, or you enable privilege confusion._security_<firewall> context can leak across firewalls if you share one firewall. Use separate firewalls per type or a single firewall with one provider that discriminates.Laravel equivalents of the pitfalls:
Buyer hitting /seller/dashboard with a valid session is already logged in. Guard scope is the enforcement point, middleware is the UX layer.Auth::guard() returns the same instance per request; if you switch guards mid-request (e.g., admin impersonation), call Auth::forgetGuards() or re-resolve.user_type is a PHP enum, cast it in the model — otherwise ->where('user_type', 'seller') comparisons can silently miss due to backed-value mismatches.php artisan route:list --columns=method,uri,middleware is the fastest way to confirm which guard a route is actually behind; Auth::guard('seller')->check() in Tinker separates "wrong guard" from "wrong credentials."UserManager is the right abstraction. In Laravel, bind an interface UserTypeManager in a service provider and resolve the concrete implementation by type — it keeps registration, password reset, and profile editing from turning into switch statements.Bottom line: you cannot leverage this package from Laravel. Leverage the pattern it encodes (discriminator + per-type manager), and skip the dependency entirely.
How can I help you explore Laravel packages today?