Problem
Laravel Livewire has no direct support for multitenancy applications, in which custom route namespaces are registered for a tenant.
The PR #2662 (feat: make Livewire default routes configurable and publishable) addresses this issue, but has not been merged to main
.
When you apply PR #2662 to your local or CI/CD environment, it will be overwritten with the next composer update
.
Solution
First, add the livewire/livewire
package to the dont-discover
section of your composer.json
. This prevents the automatic package discovery of Livewire\LivewireServiceProvider
:
{
"require": {
"livewire/livewire": "^2.10.4",
},
"extra": {
"laravel": {
"dont-discover": [
"livewire/livewire"
]
}
}
Create a new class App\Providers\CustomLivewireServiceProvider
. That one overwrites the default route registratation:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Route as RouteFacade;
use Livewire\Controllers\FilePreviewHandler;
use Livewire\Controllers\FileUploadHandler;
use Livewire\Controllers\HttpConnectionHandler;
use Livewire\Controllers\LivewireJavaScriptAssets;
use Livewire\LivewireServiceProvider;
/**
* This custom service provider overwrites the default LivewireServiceProvider.
* It is required so that the routes are registered inside a tenant's namespace.
*
* <ul>
* <li>Add <em>livewire/livewire</em> to the <em>dont-discover</em> section inside your <em>compoers.json</em></li>
* <li>Call CustomLivewireServiceProvider::registerLivewireRoutes() in your <em>routes/web.php</em></li>
* </ul>
*/
class CustomLivewireServiceProvider extends LivewireServiceProvider
{
/**
* Register the default Livewire routes.
*
* @return void
*/
public static function registerLivewireRoutes()
{
RouteFacade::post('/livewire/message/{name}', HttpConnectionHandler::class)
->name('livewire.message')
->middleware(config('livewire.middleware_group', ''));
RouteFacade::post('/livewire/upload-file', [FileUploadHandler::class, 'handle'])
->name('livewire.upload-file')
->middleware(config('livewire.middleware_group', ''));
RouteFacade::get('/livewire/preview-file/{filename}', [FilePreviewHandler::class, 'handle'])
->name('livewire.preview-file')
->middleware(config('livewire.middleware_group', ''));
}
protected function registerRoutes()
{
// we are okay with the fact, that the JavaScript files gets registered in the default namespace
RouteFacade::get('/livewire/livewire.js', [LivewireJavaScriptAssets::class, 'source']);
RouteFacade::get('/livewire/livewire.js.map', [LivewireJavaScriptAssets::class, 'maps']);
}
}
Add the newly created CustomLivewireServiceProvider
to the providers
section of your config/app.php
:
<?php
return [
/*
|--------------------------------------------------------------------------
| Application Name
|--------------------------------------------------------------------------
|
| This value is the name of your application. This value is used when the
| framework needs to place the application's name in a notification or
| any other location as required by the application or its packages.
|
*/
'name' => env('APP_NAME', 'app'),
// ...
'providers' => [
// ...
\App\Providers\CustomLivewireServiceProvider::class,
// ...
],
// ...
];
In the last step, you have to register the routes manually in your routes/web.php
. You have to call the registration inside your multitenant-specific route group definition:
Route::domain('{subdomain}.' . config('app.domain'))
->name('subdomain.')
->middleware(['tenant.subdomain'])
->group(function () {
// ...
// register custom livewire routes
\App\Providers\CustomLivewireServiceProvider::registerLivewireRoutes();
// accept temporary uploads for media library
// @see https://spatie.be/docs/laravel-medialibrary/v10/handling-uploads-with-media-library-pro/installation
Route::mediaLibrary();
});