If you are familiar with Laravel Livewire, you might come across (especially you working with huge projects), how to manage the Livewire components, to be organise under their own domain.
In my case, I have a project, consider as a big one, need some organisation of each respective domain (can say that I'm using Domain Driven Development - DDD). Livewire one of its component and I don't want to use default Livewire namespace - App\Livewire
. I want to use App\Domain\User\Livewire
, App\Domain\Payroll\Livewire
, etc.
But how do i dynamically register all the Livewire components under the domain?
They keyword is
Livewire::component('name.of.the.component', FQCN)
- Load recursively the domain namespace, and
- Only load classes which is subclass of
Livewire\Component
class.
TLDR
php artisan make:provider LivewireDomainServiceProvider
Add the following code:
<?php
namespace App\Providers;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Arr;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
use Livewire\Component as LivewireComponent;
use Livewire\Livewire;
use Symfony\Component\Finder\Finder;
class LivewireDomainServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
if (class_exists(Livewire::class)) {
$this->load(app_path('Domain'));
}
}
private function load($paths)
{
$paths = array_unique(Arr::wrap($paths));
$paths = array_filter($paths, function ($path) {
return is_dir($path);
});
if (empty($paths)) {
return;
}
$namespace = 'App\Domain\\';
foreach ((new Finder())->in($paths)->files() as $domain) {
$component = $namespace.str_replace(
['/', '.php'],
['\\', ''],
Str::after($domain->getRealPath(), realpath(app_path('Domain')).DIRECTORY_SEPARATOR)
);
if (is_subclass_of($component, LivewireComponent::class)) {
Livewire::component($component::getName(), $component);
}
}
}
}
Then register the service provider in config/app.php
.
Then you are done!
You may want to define your own Livewire domain component by explicitly define in the component class like the following:
public static function getName()
{
return 'domain.user.user-datatable';
}
Main references for the implementation are coming from Jetstream Service Provider and how Artisan command get loaded dynamically in Laravel.
Photo by Dennis Brekke on Unsplash
Top comments (2)
I see there is already a package for this, you could be a new source for a new post.
Laravel Livewire Discover - github.com/joserick/laravel-livewire-discover
interesting post, how can I do to modify and make it work for example: Admin / Http / livewire and Admin / resource / view / livewire
I have the laravel 8 application with App and Admin
Thanks for your help!