Executing code for tenants and landlords | laravel-multitenancy | Spatie

 SPATIE

  Laravel Multitenancy
=======================

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Laravel-multitenancy](https://spatie.be/docs/laravel-multitenancy/v3)  Advanced-usage  Executing code for tenants and landlords

 Version   v4   v3   v2   v1

 Other versions for crawler [v4](https://spatie.be/docs/laravel-multitenancy/v4) [v3](https://spatie.be/docs/laravel-multitenancy/v3) [v2](https://spatie.be/docs/laravel-multitenancy/v2) [v1](https://spatie.be/docs/laravel-multitenancy/v1)

- [ Introduction ](https://spatie.be/docs/laravel-multitenancy/v3/introduction)
- [ Support us ](https://spatie.be/docs/laravel-multitenancy/v3/support-us)
- [ Requirements ](https://spatie.be/docs/laravel-multitenancy/v3/requirements)
- [ Questions and issues ](https://spatie.be/docs/laravel-multitenancy/v3/questions-issues)
- [ Changelog ](https://spatie.be/docs/laravel-multitenancy/v3/changelog)
- [ ](https://spatie.be/docs/laravel-multitenancy/v3/installation-setup)

Installation
------------

- [ Base installation ](https://spatie.be/docs/laravel-multitenancy/v3/installation/base-installation)
- [ Using a single database ](https://spatie.be/docs/laravel-multitenancy/v3/installation/using-a-single-database)
- [ Using multiple databases ](https://spatie.be/docs/laravel-multitenancy/v3/installation/using-multiple-databases)
- [ Determining the current tenant ](https://spatie.be/docs/laravel-multitenancy/v3/installation/determining-current-tenant)

Basic usage
-----------

- [ Automatically determining the current tenant ](https://spatie.be/docs/laravel-multitenancy/v3/basic-usage/automatically-determining-the-current-tenant)
- [ Working with the current tenant ](https://spatie.be/docs/laravel-multitenancy/v3/basic-usage/working-with-the-current-tenant)
- [ Making queues tenant aware ](https://spatie.be/docs/laravel-multitenancy/v3/basic-usage/making-queues-tenant-aware)

Advanced usage
--------------

- [ Ensuring a current tenant has been set ](https://spatie.be/docs/laravel-multitenancy/v3/advanced-usage/ensuring-a-current-tenant-has-been-set)
- [ Looping over a collection of tenants ](https://spatie.be/docs/laravel-multitenancy/v3/advanced-usage/looping-over-a-collection-of-tenants)
- [ Making Artisan command tenant aware ](https://spatie.be/docs/laravel-multitenancy/v3/advanced-usage/making-artisan-commands-tenant-aware)
- [ Using a custom tenant model ](https://spatie.be/docs/laravel-multitenancy/v3/advanced-usage/using-a-custom-tenant-model)
- [ Listening for events ](https://spatie.be/docs/laravel-multitenancy/v3/advanced-usage/listening-for-events)
- [ Using tenant specific facades ](https://spatie.be/docs/laravel-multitenancy/v3/advanced-usage/using-tenant-specific-facades)
- [ Executing code for tenants and landlords ](https://spatie.be/docs/laravel-multitenancy/v3/advanced-usage/executing-code-for-tenants-and-landlords)

Using tasks to prepare the environment
--------------------------------------

- [ Overview ](https://spatie.be/docs/laravel-multitenancy/v3/using-tasks-to-prepare-the-environment/overview)
- [ Creating your own task ](https://spatie.be/docs/laravel-multitenancy/v3/using-tasks-to-prepare-the-environment/creating-your-own-task)
- [ Switching databases ](https://spatie.be/docs/laravel-multitenancy/v3/using-tasks-to-prepare-the-environment/switching-databases)
- [ Switching route cache paths ](https://spatie.be/docs/laravel-multitenancy/v3/using-tasks-to-prepare-the-environment/switching-route-cache-paths)
- [ Prefixing cache ](https://spatie.be/docs/laravel-multitenancy/v3/using-tasks-to-prepare-the-environment/prefixing-cache)

      You are viewing the documentation for **an older version** of this package. You can check the version you are using with the following command:

 `                                    composer show spatie/laravel-multitenancy                                                                                                                                                                                                                                    `

Executing code for tenants and landlords
========================================

###  On this page

1. [ Executing tenant code in landlord request ](#content-executing-tenant-code-in-landlord-request)
2. [ Executing landlord code in tenant request ](#content-executing-landlord-code-in-tenant-request)
3. [ Testing with DatabaseTransactions for Tenant ](#content-testing-with-databasetransactions-for-tenant)

The `Tenant` and `Landlord` models provide an `execute` method that allows you to execute code for a specific tenant or landlord.

Executing tenant code in landlord request
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

To execute tenant code in a landlord request, you can use the method `execute` available in the `Tenant` model.

Here is an example where we flush the cache for a tenant using our landlord API:

```
Route::delete('/api/{tenant}/flush-cache', function (Tenant $tenant) {
    $result = $tenant->execute(fn (Tenant $tenant) => cache()->flush());

    return json_encode(["success" => $result]);
});
```

Inside the closure passed to `execute`, the given `$tenant` is set as the current one.

Here's another example, where a job is dispatched from a landlord API route:

```
Route::post('/api/{tenant}/reminder', function (Tenant $tenant) {
    return json_encode([
        'data' => $tenant->execute(fn () => dispatch(ExpirationReminder())),
    ]);
});
```

### Executing a delayed callback in the correct Tenant context

If you need to define a callback that will be executed in the correct Tenant context every time it is called, you can use the Tenant's `callback` method. A notable example for this is the use in the Laravel scheduler where you can loop through all the tenants and schedule callbacks to be executed at the given time:

```
protected function schedule(Schedule $schedule)
{
    Tenant::all()->eachCurrent(function(Tenant $tenant) use ($schedule) {
        $schedule->run($tenant->callback(fn() => cache()->flush()))->daily();
    });
}
```

Executing landlord code in tenant request
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

To execute landlord code, from inside a tenant request, you can use the method `execute` on `Spatie\Multitenancy\Landlord`.

Here is an example where we will first clear the tenant cache, and next, the landlord cache:

```
use  Spatie\Multitenancy\Landlord;

// ...

Tenant::first()->execute(function (Tenant $tenant) {
    // it will clear the tenant cache
    Artisan::call('cache:clear');

    // it will clear the landlord cache
    Landlord::execute(fn () => Artisan::call('cache:clear'));
});
```

Inside the closure passed to `execute`, the landlord is made active by forgetting the current tenant.

Testing with DatabaseTransactions for Tenant
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

When performing testing and using the `DatabaseTransactions` trait, the default setup in Laravel requires changes to ensure that the transactions are performed on the `Tenant` connection. Accordingly, the default `TestCase.php` file may be updated as below:

```
namespace Tests;

use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Support\Facades\Event;
use Spatie\Multitenancy\Concerns\UsesMultitenancyConfig;
use Spatie\Multitenancy\Events\MadeTenantCurrentEvent;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication, DatabaseTransactions, UsesMultitenancyConfig;

    protected function connectionsToTransact()
    {
        return [
            $this->landlordDatabaseConnectionName(),
            $this->tenantDatabaseConnectionName(),
        ];
    }

    protected function setUp(): void
    {
        parent::setUp();

        Event::listen(MadeTenantCurrentEvent::class, function () {
            $this->beginDatabaseTransaction();
        });
    }
}
```

In case a user login is performed using the `Auth` facade in the `setUp` method on a test, the tenant switching will not happen automatically. Accordingly, the `setUp` method above may be updated as below to ensure that the required tenant has been set (using the first `Tenant` as an example below)

```

protected function setUp(): void
{
    parent::setUp();

    Event::listen(MadeTenantCurrentEvent::class, function () {
        $this->beginDatabaseTransaction();
    });

    Tenant::first()->makeCurrent();
}
```
