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

Core Laravel Package

tenantedlaravel/core

Core package for Tenanted Laravel, a multi-tenancy toolkit for Laravel. Resolve tenants by domain or subdomain, scope Eloquent queries to the active tenant, switch database connections automatically, and keep tenant data isolated—all within a single codebase. Ideal for SaaS apps.

View on GitHub
Deep Wiki
Context7

Getting Started

Sprout is a Laravel package for giving a single user model multiple identities (email, username, phone, social account, etc.) and resolving the right user from any of them at login time. v1.2.0 is a compatibility/maintenance release rather than a feature release, so it is a safe entry point for new installs.

Minimal setup

  1. composer require sprout-laravel/sprout — check the resolved constraint against your app: v1.2.0 adds Laravel 13 support alongside the previously supported versions, so verify composer.json allows the framework version you actually run before upgrading in a locked project.
  2. Publish and review the config + migrations:
    php artisan vendor:publish --tag="sprout-config"
    php artisan vendor:publish --tag="sprout-migrations"
    php artisan migrate
    
  3. Add the package trait/contract to your User model so it can own identities.
  4. Register at least one identity resolver (see below) and confirm it in config/sprout.php.

Where to look first

  • config/sprout.php — the resolver list is the heart of the package; everything else is plumbing around it.
  • The Identity model/contract shipped by the package — this is the shape your registration and profile screens will write to.
  • The resolver contract — the only class you are expected to write yourself.

First use case

Registration writes a User plus one or more identity rows (email at minimum); login resolves the submitted credential through the resolver chain, gets back an identity, and hands you the associated user to authenticate. Start by wiring email login through a single resolver before adding phone/username, so you can isolate failures.

Implementation Patterns

Keep identity creation alongside user creation. Wrap registration in a transaction: create the user, then attach identities. If you let identities be optional at registration you will hit users who cannot log in after a resolver change.

Resolver chain, ordered intentionally. Register resolvers in priority order in config — typically: exact identifier (username/id) → email → phone → external provider. Each resolver should be narrow: it answers "does this input look like my type, and what identity row matches it?" Return null rather than throwing for non-matches so the chain can continue.

// app/Sprout/EmailResolver.php
public function resolve(string $identifier): ?Identity
{
    if (! filter_var($identifier, FILTER_VALIDATE_EMAIL)) {
        return null; // let the next resolver try
    }

    return Identity::query()
        ->where('type', 'email')
        ->where('value', Str::lower($identifier))
        ->first();
}

Login flow. Resolve → guard against null → Auth::login($identity->user). Keep the "resolve" step separate from the "authenticate/session" step; that separation is what makes passwordless, magic-link, and social flows reuse the same resolver chain.

Write paths should normalise, not the resolver. Lowercase emails, E.164 phone numbers, and case-insensitive usernames at write time. Resolvers then do exact matches, which stay index-friendly.

Testing integration. Extend the package's Testbench/PHPUnit base if it ships one, and use RefreshDatabase plus factories for identities. Cover three cases per resolver: matches, plausible-but-missing, and not-my-type (returns null). v1.2.0 bumps PHPUnit/Testbench/Larastan, so re-run your suite after the upgrade — mostly relevant if you subclass package test classes.

Multi-guard apps. If you have admin vs. customer guards, scope resolvers per guard (or add a guard column on identities) rather than relying on a single global chain; otherwise an admin username can resolve a customer identity.

Gotchas and Tips

The deprecation warning for identity resolvers was updated in v1.2.0. Treat this as the headline item of the release: the current resolver mechanism is on a removal path and the warning text has been clarified. If you are starting fresh, keep your resolver implementations behind a thin interface of your own so the eventual swap is a one-file change; if you already have resolvers, budget time to migrate rather than waiting for the removal release. Check the changelog link for the specific replacement direction — this release does not describe it.

No runtime breaking changes advertised. The PHPStan fixes, baseline removal, and CI nightly job are all maintainer-side. Your real risk is transitive: bumping Testbench/PHPUnit/Larastan can conflict with pinned dev dependencies in your app if you extend the package's testing utilities.

Laravel 13 support means wider constraints, not narrower. Packages often broaden illuminate/* ranges while bumping orchestra/testbench. Run composer why-not sprout-laravel/sprout if the install fails after upgrading Laravel, and re-run Larastan after the upgrade since the package's own baseline was removed.

Nightly CI is a signal, not a guarantee. The workflow update means upstream (Laravel/PHPStan) breakage gets caught fast, but tagged releases can still lag. If you track dev-main, pin to a commit in CI.

Beware per-request resolver queries. A resolver that joins on every request will quietly tax your login and any middleware that resolves identities. Restrict resolution to auth endpoints; don't call it from a global middleware or a Blade composer.

Duplicate identities are the classic bug. Enforce a unique index on (type, value) at the database level — application-level checks lose to concurrent registrations.

Debugging. Log which resolver matched (class name + identity id) at debug level. When "login fails for one user only," it is nearly always a normalisation mismatch or a duplicate row created before the unique index existed — query by LOWER(value) to spot it.

Extension points to prefer. Resolver registration via config (not hardcoded in a service provider) and a custom Identity subclass are the two seams that survive releases; avoid extending package internals, which the static-analysis churn in this release shows are not a stability contract.

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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings