Closed nickfls closed 5 months ago
The Undefined array key 0
comes from:
$route->parameterNames()[0]
the route itself has no route parameters — you have only applied middleware. You could try changing the route to /{tenant}/livewire/update
or something along those lines.
Would it be fair to say that InitializeTenancyByPath
is not entirely compatible with livewire and one need to search for an alternative?
Path identification is in general more difficult to get working with various third-party packages than e.g. domain identification because of this exact issue: the need for package routes to contain the {tenant}
parameter, which isn't always something you can set.
In the case of Livewire, you can set it so I think you should be able to make this work.
But to use Livewire in both the central app and the tenant app you'd need a bit more logic to dynamically change the update route (so that it does have the parameter in the tenant app and doesn't have it in the central app).
Something like this might work:
class LivewireBootstrapper implements TenancyBootstrapper
{
public function bootstrap(Tenant $tenant)
{
Livewire::setUpdateRoute(function ($handle) {
return Route::post('/{tenant}/livewire/update', $handle)->middleware([
'web',
InitializeTenancyByPath::class
]);
});
}
public function revert()
{
Livewire::setUpdateRoute(function ($handle) {
return Route::post('/livewire/update', $handle)->middleware(['web']);
});
}
}
@stancl I appreciate your time.
i think the Bootstrappers are called when the tenancy is initialized - that may be ok for the initial run (it isn't - for whatever reason the update route ONLY sets when defined in routes
or within AppServiceProvider::boot()
), but routes are loaded before that moment and since tenancy is not defined yet, we are at the same spot.
livewire 3 docs say they will respect and keep the prefix on reload; however, i cannot fathom the spot where i need to run the Livewire::updateRoute(...)
Right that makes sense. We're adding the identification middleware to these routes so setting them inside bootstrappers (that run after identification) won't work. I remembered we had another solution for path identification, I'll find it and mention it here.
Any luck so far, @stancl?
Ah sorry, meant to post here but didn't get to it.
Essentially, the setup we use in v4 is more dependent on some features added in v4, but can be replicated with a bit of work:
'universal'
and InitializeTenancyByPath::class
MWs added/{tenant}
path prefix and tenant.
name prefix)tenant.
routes when in tenant contextThis will lead LW creating a path to either the central route or the tenant route based on the current context on the initial render, and then subsequent requests will respect that URL.
I'm currently facing the exact same problem. I tried doing something like this:
Livewire::setUpdateRoute(function ($handle) {
$tenantIdentifier = request()->segment(1);
return Route::post("/{tenant}/livewire/update", $handle)
->middleware(
[
'web',
'universal',
InitializeTenancyByPath::class,
])
->defaults('tenant', $tenantIdentifier)
->name('livewire.update');
});
Unfortunately it didn't work due to a Missing required parameter
error. If anyone was able to make this work using v3 I would really appreciate it.
@abikali @stancl @nickfls Im facing this problem and this is what i did:
First i added the livewire update route to the TenancyServiceProvider
Livewire::setUpdateRoute(function ($handle) {
//\Livewire\Mechanisms\HandleRequests\HandleRequests::class
return Route::post('/livewire/update', $handle)
->middleware(
'web',
'universal',
\Stancl\Tenancy\Middleware\InitializeTenancyByPath::class, // or whatever tenancy middleware you use
);
});
$this->makeTenancyMiddlewareHighestPriority();
Then i had to modify (or maybe create a new MW) InitializeTenancyByPath
public function handle(Request $request, Closure $next)
{
/** @var Route $route */
/**
* We need to check if the request is a livewire request
* because livewire requests are missing 'tenant' value in parameterNames array
* and we need it to initialize the tenant
**/
if(Livewire::isLivewireRequest()) {
$tenant = explode("/", $request->server('HTTP_REFERER'))[3];
$tenant = YourTenantModel::find($tenant);
\tenancy()->initialize($tenant);
return $next($request);
}
$route = $request->route();
// Only initialize tenancy if tenant is the first parameter
// We don't want to initialize tenancy if the tenant is
// simply injected into some route controller action.
if ($route->parameterNames()[0] === PathTenantResolver::$tenantParameterName) {
return $this->initializeTenancy(
$request, $next, $route
);
} else {
throw new RouteIsMissingTenantParameterException;
}
return $next($request);
And thats all, livewire its working on central and tenant routes.
Bug description
Laravel throws
Undefined array key 0
received when using InitializeTenancyByPath with livewire within tenant context.Steps to reproduce
LivewireServiceProvider::boot()
tenant.localhost.test/{tenant}/
Expected behavior
Undefined array key 0 in Middleware/InitializeTenancyByPath.php:40
Stack trace
Laravel version
11.4.0
stancl/tenancy version
3.8.2