Load Dynamically Livewire Components from Different Namespace

Nasrul Hazim Bin Mohamad - Nov 29 '21 - - Dev Community

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
Enter fullscreen mode Exit fullscreen mode

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);
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

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';
}
Enter fullscreen mode Exit fullscreen mode

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player