From 4937a74ed5c44ecefc90bd8a52a458a894c9831c Mon Sep 17 00:00:00 2001 From: lukinovec Date: Fri, 3 Apr 2026 13:07:40 +0200 Subject: [PATCH] BroadcastingConfigBootstrapper and TenancyBroadcastManager: comments --- .../BroadcastingConfigBootstrapper.php | 25 +++++++++++++------ src/Overrides/TenancyBroadcastManager.php | 23 +++++++++++++---- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/Bootstrappers/BroadcastingConfigBootstrapper.php b/src/Bootstrappers/BroadcastingConfigBootstrapper.php index 277db58f..b0df125b 100644 --- a/src/Bootstrappers/BroadcastingConfigBootstrapper.php +++ b/src/Bootstrappers/BroadcastingConfigBootstrapper.php @@ -14,6 +14,12 @@ use Stancl\Tenancy\Contracts\TenancyBootstrapper; use Stancl\Tenancy\Contracts\Tenant; use Stancl\Tenancy\Overrides\TenancyBroadcastManager; +/** + * Maps tenant properties to broadcasting config and overrides + * the BroadcastManager binding with TenancyBroadcastManager in tenant context. + * + * @see TenancyBroadcastManager + */ class BroadcastingConfigBootstrapper implements TenancyBootstrapper { /** @@ -66,13 +72,15 @@ class BroadcastingConfigBootstrapper implements TenancyBootstrapper $this->setConfig($tenant); - // Make BroadcastManager resolve to TenancyBroadcastManager which always re-resolves the used broadcasters (so that - // the broadcasting credentials are always up-to-date at the point of broadcasting) and gives the channels of - // the broadcaster from the central context to the newly resolved broadcasters in tenant context. + // Make BroadcastManager resolve to TenancyBroadcastManager which always re-resolves the used broadcasters so that + // the credentials used by broadcasters are always up-to-date with the config when retrieving the broadcasters using + // the manager and gives the channels of the broadcaster from central context to the newly resolved broadcasters in tenant context. $this->app->extend(BroadcastManager::class, function (BroadcastManager $broadcastManager) { $originalCustomCreators = invade($broadcastManager)->customCreators; $tenantBroadcastManager = new TenancyBroadcastManager($this->app); + // TenancyBroadcastManager inherits the custom driver creators registered in the central context so that + // custom drivers work in tenant context without having to re-register the creators manually. foreach ($originalCustomCreators as $driver => $closure) { $tenantBroadcastManager->extend($driver, $closure); } @@ -81,16 +89,17 @@ class BroadcastingConfigBootstrapper implements TenancyBootstrapper }); // Swap currently bound Broadcaster instance for one that's resolved through the tenant broadcast manager. - // Note that changing tenant's credentials in tenant context doesn't update them in the bound Broadcaster instance. - // If you need to e.g. send a notification in response to updating tenant's broadcasting credentials in tenant context, - // it's recommended to use the broadcast() helper which always uses fresh broadcasters with the current credentials. + // Note that updating broadcasting config (credentials) in tenant context doesn't update the credentials + // used by the bound Broadcaster instance. If you need to e.g. send a notification in response to + // updating tenant's broadcasting credentials in tenant context, it's recommended to + // reinitialize tenancy after updating the credentials. $this->app->extend(Broadcaster::class, function (Broadcaster $broadcaster) { return $this->app->make(BroadcastManager::class)->connection(); }); // Clear the resolved Broadcast facade's Illuminate\Contracts\Broadcasting\Factory instance - // so that it gets re-resolved as the tenant broadcast manager when used (e.g. the - // Broadcast::auth() call in BroadcastController::authenticate). + // so that it gets re-resolved as TenancyBroadcastManager instead of the central BroadcastManager + // when used e.g. in the Broadcast::auth() call in BroadcastController::authenticate (/broadcasting/auth). Broadcast::clearResolvedInstance(BroadcastingFactory::class); } diff --git a/src/Overrides/TenancyBroadcastManager.php b/src/Overrides/TenancyBroadcastManager.php index 3364bec4..bc74e539 100644 --- a/src/Overrides/TenancyBroadcastManager.php +++ b/src/Overrides/TenancyBroadcastManager.php @@ -8,13 +8,26 @@ use Illuminate\Broadcasting\Broadcasters\Broadcaster; use Illuminate\Broadcasting\BroadcastManager; use Illuminate\Contracts\Broadcasting\Broadcaster as BroadcasterContract; +/** + * BroadcastManager override that always re-resolves the broadcasters in static::$tenantBroadcasters + * when attempting to retrieve them and passes the channels of the original (central) broadcaster + * to the broadcasters newly resolved in tenant context. + * + * Affects calls that use app(BroadcastManager::class)->get(). + * + * @see Stancl\Tenancy\Bootstrappers\BroadcastingConfigBootstrapper + */ class TenancyBroadcastManager extends BroadcastManager { /** * Names of broadcasters that * - should always be recreated using $this->resolve(), even when they're cached and available - * in $this->drivers (so that e.g. when you update broadcasting credentials in the tenant context, - * the updated credentials will be used for broadcasting in the same context) + * in $this->drivers so that when you update broadcasting config in the tenant context, + * the updated config/credentials will be used for broadcasting in the same context. + * Note that in cases like this, only direct config changes are reflected immediately. + * For the broadcasters to reflect tenant property changes made in tenant context, + * you still have to reinitialize tenancy after updating the tenant properties intended + * for broadcasting config mapping, since the properties are only mapped to config on BroadcastingConfigBootstrapper::bootstrap(). * - should inherit the original broadcaster's channels (= the channels registered in * the central context, e.g. in routes/channels.php, before this manager overrides the bound BroadcastManager). */ @@ -46,9 +59,9 @@ class TenancyBroadcastManager extends BroadcastManager } // The newly resolved broadcasters don't automatically receive the channels registered - // in central context (e.g. in routes/channels.php), so the channels have to be obtained from the - // broadcaster used in central context and manually passed to the new broadcasters - // (attempting to broadcast using a broadcaster with no channels results in a 403 error). + // in central context (e.g. Broadcast::channel() in routes/channels.php), so the channels + // have to be obtained from the original (central) broadcaster and manually passed to the new broadcasters + // (broadcasting using a broadcaster with no channels results in a 403 error on Broadcast::auth()). protected function passChannelsFromOriginalBroadcaster(Broadcaster $originalBroadcaster, Broadcaster $newBroadcaster): void { // invade() because channels can't be retrieved through any of the broadcaster's public methods