Laravel Multitenancy
Multi-tenancy is the ability to provide your service to multiple users (tenants) from a single hosted instance of the application. This is contrasted with deploying the application separately for each user.
composer require stancl/tenancy
Then run
php artisan tenancy:install
This will create config/tenancy.php, routes/tenant.php, app/Providers/TenancyServiceProvider.php and some new migration tables
Then add
// config/app.php
App\Providers\TenancyServiceProvider::class,If there’s already a migration update the user migration
Schema::create('users', function (Blueprint $table) {
		...
    $table->string('domain')->unique();
		...
});
Then run
php artisan migrate:fresh
Make a Tenant model
php artisan make:model Tenant
namespace App;
use Stancl\Tenancy\Database\Models\Tenant as BaseTenant;
use Stancl\Tenancy\Contracts\TenantWithDatabase;
use Stancl\Tenancy\Database\Concerns\HasDatabase;
use Stancl\Tenancy\Database\Concerns\HasDomains;
class Tenant extends BaseTenant implements TenantWithDatabase
{
    use HasDatabase, HasDomains;
}Then update
// config/tenancy.php
'tenant_model' => \App\Models\Tenant::class,
Update the RouteServiceProvider
// RouteServiceProvider
protected function mapWebRoutes()
{
    foreach ($this->centralDomains() as $domain) {
        Route::middleware('web')
            ->domain($domain)
            ->namespace($this->namespace)
            ->group(base_path('routes/web.php'));
    }
}
protected function mapApiRoutes()
{
    foreach ($this->centralDomains() as $domain) {
        Route::prefix('api')
            ->domain($domain)
            ->middleware('api')
            ->namespace($this->namespace)
            ->group(base_path('routes/api.php'));
    }
}
protected function centralDomains(): array
{
    return config('tenancy.central_domains', []);
}
Then update in boot() of RouteServiceProvider
// comment $this->routes(function () {}); add this instead
$this->routes(function () {
    $this->mapApiRoutes();
    $this->mapWebRoutes();
});
Add to .env
// localhost or domain tenant.test
APP_CENTRAL_DOMAIN=localhost 
We will create tenants after the user registers or you can use Tinker.
$user = User::create(['name' => 'madindo','email' => 'madindo@gmail.com', 'password' => bcrypt('madindo123'), 'domain' => 'madindo']);// App\\Models\\User
public static function booted() {
    static::created(function($user) {
        $user_tenant = Tenant::create(['id' => $user->domain]);
        $user_tenant->domains()->create(['domain' => $user->domain . '.' . env('APP_CENTRAL_DOMAIN')]);
    });
}
For local development, you may use *.localhost domains (like foo.localhost) for tenants. On many operating systems, these work the same way as localhost.
Try to access {user_domain}.tenant.test / {user_domain}.localhost
This is the start of multi-tenancy, there’s a lot more to develop for our custom app.
php artisan make:migration create_settings_table --path=database/migrations/tenant
Schema::create('settings', function (Blueprint $table) {
    $table->string('key')->primary();
    $table->text('value')->nullable();
    $table->timestamps();
});
php artisan tenants:migrate
This will create a new folder in migration called tenant with migrations specifically for tenants.
Let’s make the model
php artisan make:model Tenant/Setting
namespace App\\Models\\Tenant;
use Illuminate\\Database\\Eloquent\\Factories\\HasFactory;
use Illuminate\\Database\\Eloquent\\Model;
class Setting extends Model
{
    use HasFactory;
    protected $keyType = 'string';
    protected $primaryKey = 'id';
}
[Update 14/09/2024]
Redirect when accessing the wrong subdomain
Find TenantServiceProvider.php find method boot() add this
// Handling tenant identification failure
InitializeTenancyByDomain::$onFail = function ($exception, $request, $next) {
	return redirect(env('APP_URL'));
};