fluxter/saas-provider-bundle
fluxter/saas-provider-bundle is a Laravel/PHP package that bundles reusable SaaS provider integration logic, helping you connect provider services and common SaaS workflows into your application with less boilerplate and a cleaner setup.
Before you composer require anything, understand what this is: fluxter/saas-provider-bundle is a Symfony bundle, not a Laravel package. It wires into Symfony's kernel, DI container, and bundle extension system — none of which Laravel has. So the first step for a Laravel developer is not installation, it's concept extraction.
Where to look first (in the repo):
DependencyInjection/ — the *Extension and Configuration classes reveal the config tree and the services the bundle registers. This is the single most informative folder for understanding intent.Resources/config/ — service definitions (YAML/XML) show what gets instantiated and how it's wired.*Provider / tenant / subscription classes — the domain logic you actually care about.Minimal steps to evaluate it for a Laravel app:
git clone https://github.com/Fluxter/symfony-saas-provider-bundle
cat composer.json # note PHP + symfony/* version constraints
grep -r "class .*Extension" src/
There is no composer require path into a Laravel skeleton — it will pull Symfony HTTP Kernel, DependencyInjection, Config, and EventDispatcher and still won't boot. Your "first use case" is therefore: read the config tree, decide whether the tenant/provider model fits your app, and if it does, port the pattern into a Laravel service provider rather than trying to install the bundle.
First use case to target: a multi-tenant SaaS where a Provider (tenant/account) is resolved per request and gates access to plans/subscriptions. That's the shape this bundle models, and it maps cleanly onto Laravel middleware + container bindings + Eloquent global scopes.
Treat the bundle as a reference architecture, and translate Symfony idioms to Laravel ones:
| Symfony bundle concept | Laravel equivalent |
|---|---|
| Bundle class | Package + ServiceProvider |
DependencyInjection/Configuration tree |
config/saas.php |
Service definitions in Resources/config |
Container bindings in register() |
Tagged services (!tagged_iterator) |
$this->app->tag() + tagged() |
| Event subscribers | EventServiceProvider listeners |
| Request listener / kernel event | HTTP middleware |
| Compiler passes | boot() logic or a dedicated registrar |
Pattern 1 — Provider/Tenant registry as a singleton
// app/Providers/SaasServiceProvider.php
public function register(): void
{
$this->app->singleton(TenantManager::class, fn ($app) =>
new TenantManager($app['config']->get('saas.providers', []))
);
}
Pattern 2 — Resolve the tenant in middleware
class ResolveTenant
{
public function __construct(private TenantManager $tenants) {}
public function handle($request, Closure $next)
{
$tenant = $this->tenants->resolveFromHost($request->getHost())
?? abort(404);
app()->instance(CurrentTenant::class, $tenant);
return $next($request);
}
}
Pattern 3 — Scope Eloquent queries automatically
protected static function booted(): void
{
static::addGlobalScope('tenant', function ($q) {
if ($tenant = app(CurrentTenant::class)) {
$q->where('tenant_id', $tenant->id);
}
});
}
Pattern 4 — Subscription/entitlement checks via Gate
Gate::define('feature', fn (User $u, string $feature) =>
app(CurrentTenant::class)->plan()->allows($feature)
);
If you genuinely need the bundle's logic (e.g., a calculation or provider adapter you don't want to rewrite), the pragmatic route is to stand it up inside a small Symfony service and call it over HTTP or a queue — not to graft Symfony's DI into Laravel. If it's MIT (it is), copying the isolated domain class with attribution is usually cleaner.
Config integration tip: mirror the bundle's YAML config tree exactly in config/saas.php and add a php artisan vendor:publish-style stub so future readers can diff against upstream docs.
composer.json for symfony/* and php ranges — a 2022 bundle will likely pin PHP 7.4/8.0 and Symfony 5.x, which is incompatible with current Laravel (10/11/12) on PHP 8.2+. Composer will refuse or force downgrades.SaasProvider:: facade and no Illuminate\Contracts binding. Everything is Symfony-typed (ContainerInterface, EventDispatcherInterface). Expect to shim interfaces if you ever interop.!tagged_iterator (e.g., a list of registered providers) becomes $this->app->tag() in register() and tagged() in consumers — easy to get wrong on first pass.debug:container don't exist here. Use php artisan tinker, dd(app(TenantManager::class)), and Telescope/logging to trace tenant resolution. Log the resolved tenant before the global scope runs or you'll get silent empty result sets.withoutGlobalScope('tenant') escape hatch for admin tooling.%env(...)%) and defaults per node; Laravel's config/*.php doesn't validate shape. Add a small validation step in boot() or a config test so malformed provider definitions fail loudly instead of producing 404s.Extension::load() and compiler passes are where upstream injects behavior. If you're porting, replicate that ordering in register() (bindings) vs boot() (side effects) — mixing them causes "class not found" during resolution.How can I help you explore Laravel packages today?