Skip to content

Commit

Permalink
Merge pull request #544 from spatie/refactoring-interface
Browse files Browse the repository at this point in the history
Contract IsTenant replace Tenant uses
  • Loading branch information
freekmurze committed Jul 24, 2024
2 parents 593df73 + 5ac00aa commit 8a22870
Show file tree
Hide file tree
Showing 51 changed files with 377 additions and 324 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
matrix:
os: [ubuntu-latest]
php: [8.2]
laravel: ['10.*', '11.*']
laravel: ['11.*']
dependency-version: [prefer-lowest, prefer-stable]


Expand Down
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
],
"require": {
"php": "^8.2",
"illuminate/support": "^10.0|^11.0",
"illuminate/support": "^11.0",
"spatie/laravel-package-tools": "^1.9"
},
"require-dev": {
"laravel/legacy-factories": "^1.0.4",
"laravel/octane": "^2.3",
"laravel/octane": "^2.5",
"laravel/serializable-closure": "^1.1",
"mockery/mockery": "^1.4",
"orchestra/testbench": "^8.0|^9.0",
"orchestra/testbench": "^9.0",
"pestphp/pest": "^2.34",
"spatie/valuestore": "^1.2"
},
Expand Down
27 changes: 7 additions & 20 deletions config/multitenancy.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
<?php

use Illuminate\Broadcasting\BroadcastEvent;
use Illuminate\Events\CallQueuedListener;
use Illuminate\Mail\SendQueuedMailable;
use Illuminate\Notifications\SendQueuedNotifications;
use Illuminate\Queue\CallQueuedClosure;
use Spatie\Multitenancy\Actions\ForgetCurrentTenantAction;
use Spatie\Multitenancy\Actions\MakeQueueTenantAwareAction;
use Spatie\Multitenancy\Actions\MakeTenantCurrentAction;
Expand Down Expand Up @@ -42,7 +37,8 @@
/*
* This class is the model used for storing configuration on tenants.
*
* It must be or extend `Spatie\Multitenancy\Models\Tenant::class`
* It must extend `Spatie\Multitenancy\Models\Tenant::class` or
* implement `Spatie\Multitenancy\Contracts\IsTenant::class` interface
*/
'tenant_model' => Tenant::class,

Expand All @@ -65,6 +61,11 @@
*/
'landlord_database_connection_name' => null,

/*
* This key will be used to associate the current tenant in the context
*/
'current_tenant_context_key' => 'tenantId',

/*
* This key will be used to bind the current tenant in the container.
*/
Expand All @@ -87,20 +88,6 @@
'migrate_tenant' => MigrateTenantAction::class,
],

/*
* You can customize the way in which the package resolves the queueable to a job.
*
* For example, using the package laravel-actions (by Loris Leiva), you can
* resolve JobDecorator to getAction() like so: JobDecorator::class => 'getAction'
*/
'queueable_to_job' => [
SendQueuedMailable::class => 'mailable',
SendQueuedNotifications::class => 'notification',
CallQueuedClosure::class => 'closure',
CallQueuedListener::class => 'class',
BroadcastEvent::class => 'event',
],

/*
* Jobs tenant aware even if these don't implement the TenantAware interface.
*/
Expand Down
30 changes: 29 additions & 1 deletion docs/advanced-usage/using-a-custom-tenant-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ title: Using a custom tenant model
weight: 6
---

If you want to change or add behaviour on the `Tenant` model you can use your custom model. Make sure that your custom model extends the `Spatie\Multitenancy\Models\Tenant` model provided by the package.
If you want to change or add behaviour on the `Tenant` model you can use your custom model. There are two ways of doing this by extending the `Tenant` model provided by the package, or by prepping a model of your own.

## Option 1: extending the `Tenant` model provided by the package


Make sure that your custom model extends the `Spatie\Multitenancy\Models\Tenant` model provided by the package.

You should specify the class name of your model in the `tenant_model` key of the `multitenancy` config file.

Expand All @@ -16,6 +21,29 @@ You should specify the class name of your model in the `tenant_model` key of the
'tenant_model' => \App\Models\CustomTenantModel::class,
```

## Option 2: using a model of your own

You don't have to extend our `Tenant` model. For example if you use Laravel Jetstream, then you probably want to use `Team` model provided by that package as your tenant model.

To accomplish that, you can implement the `IsTenant` interface and use trait `ImplementsTenant` to fulfill that intervace.

Here's an example:

```php
namespace App\Models;

use Laravel\Jetstream\Team as JetstreamTeam;
use Spatie\Multitenancy\Contracts\IsTenant;
use Spatie\Multitenancy\Models\Concerns\ImplementsTenant;

class Team extends JetstreamTeam implements IsTenant
{
use HasFactory;
use UsesLandlordConnection;
use ImplementsTenant;
}
```

## Performing actions when a tenant gets created

You can leverage Eloquent's lifecycle callbacks to execute extra logic when a tenant gets created, updated, deleted, ...
Expand Down
8 changes: 4 additions & 4 deletions docs/advanced-usage/using-tenant-specific-facades.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ namespace App\Tenancy\SwitchTasks;

use Illuminate\Support\Facades\Facade;
use Illuminate\Support\Str;
use Spatie\Multitenancy\Models\Tenant;
use Spatie\Multitenancy\Contracts\IsTenant;
use Spatie\Multitenancy\Tasks\SwitchTenantTask;

class ClearFacadeInstancesTask implements SwitchTenantTask
{
public function makeCurrent(Tenant $tenant): void
public function makeCurrent(IsTenant $tenant): void
{
// tenant is already current
}
Expand All @@ -43,12 +43,12 @@ namespace App\Tenancy\SwitchTasks;

use Illuminate\Support\Facades\Facade;
use Illuminate\Support\Str;
use Spatie\Multitenancy\Models\Tenant;
use Spatie\Multitenancy\Contracts\IsTenant;
use Spatie\Multitenancy\Tasks\SwitchTenantTask;

class ClearFacadeInstancesTask implements SwitchTenantTask
{
public function makeCurrent(Tenant $tenant): void
public function makeCurrent(IsTenant $tenant): void
{
// tenant is already current
}
Expand Down
11 changes: 4 additions & 7 deletions docs/basic-usage/automatically-determining-the-current-tenant.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ app('currentTenant') // will return the current tenant or `null`
You can create a tenant finder of your own. A valid tenant finder is any class that extends `Spatie\Multitenancy\TenantFinder\TenantFinder`. You must implement this abstract method:

```php
abstract public function findForRequest(Request $request): ?Tenant;
abstract public function findForRequest(Request $request): ?IsTenant;
```

Here's how the default `DomainTenantFinder` is implemented. The `getTenantModel` returns an instance of the class specified in the `tenant_model` key of the `multitenancy` config file.
Expand All @@ -37,18 +37,15 @@ Here's how the default `DomainTenantFinder` is implemented. The `getTenantModel`
namespace Spatie\Multitenancy\TenantFinder;

use Illuminate\Http\Request;
use Spatie\Multitenancy\Models\Concerns\UsesTenantModel;
use Spatie\Multitenancy\Models\Tenant;
use Spatie\Multitenancy\Contracts\IsTenant;

class DomainTenantFinder extends TenantFinder
{
use UsesTenantModel;

public function findForRequest(Request $request):?Tenant
public function findForRequest(Request $request): ?IsTenant
{
$host = $request->getHost();

return $this->getTenantModel()::whereDomain($host)->first();
return app(IsTenant::class)::whereDomain($host)->first();
}
}
```
20 changes: 16 additions & 4 deletions docs/basic-usage/working-with-the-current-tenant.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ title: Working with the current tenant
weight: 3
---

There are several methods available to get, set and clear the current tenant.
There are several methods available to get, set and clear the current tenant. All methods are available using the Tenant model directly, or through the Laravel Service Container `app(IsTenant::class)`.

### Finding the current tenant

You can find the current tenant like this:

```php
Spatie\Multitenancy\Models\Tenant::current(); // returns the current tenant, or if no tenant is current, `null`
// Model
Tenant::current(); // returns the current tenant, or if no tenant is current, `null`

// Service Container
app(IsTenant::class)::current(); // returns the current tenant, or if no tenant is current, `null`
```

A current tenant will also be bound in the container using the `currentTenant` key.
Expand All @@ -24,7 +28,11 @@ app('currentTenant'); // returns the current tenant, or if no tenant is current,
You can check if there is tenant set as the current one:

```php
Tenant::checkCurrent() // returns `true` or `false`
// Model
Tenant::checkCurrent(); // returns `true` or `false`

// Service Container
app(IsTenant::class)::checkCurrent(); // returns `true` or `false`
```

### Manually setting the current tenant
Expand All @@ -42,9 +50,13 @@ When a tenant is made the current one, the package will run the `makeCurrent` me
You can forget the current tenant:

```php
// Model
Tenant::forgetCurrent();

Tenant::current() // return null;

// Service Container
app(IsTenant::class)::forgetCurrent();
app(IsTenant::class)::current(); // return null
```

If there was no tenant current when calling `forgetCurrent`, the function will do nothing.
24 changes: 8 additions & 16 deletions docs/installation/base-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ weight: 1
This package can be installed via composer:

```bash
composer require "spatie/laravel-multitenancy:^3.0"
composer require "spatie/laravel-multitenancy:^4.0"
```

### Publishing the config file
Expand Down Expand Up @@ -64,7 +64,8 @@ return [
/*
* This class is the model used for storing configuration on tenants.
*
* It must be or extend `Spatie\Multitenancy\Models\Tenant::class`
* It must extend `Spatie\Multitenancy\Models\Tenant::class` or
* implement `Spatie\Multitenancy\Contracts\IsTenant::class` interface
*/
'tenant_model' => Tenant::class,

Expand All @@ -87,6 +88,11 @@ return [
*/
'landlord_database_connection_name' => null,

/*
* This key will be used to associate the current tenant in the context
*/
'current_tenant_context_key' => 'tenantId',

/*
* This key will be used to bind the current tenant in the container.
*/
Expand All @@ -109,20 +115,6 @@ return [
'migrate_tenant' => MigrateTenantAction::class,
],

/*
* You can customize the way in which the package resolves the queueable to a job.
*
* For example, using the package laravel-actions (by Loris Leiva), you can
* resolve JobDecorator to getAction() like so: JobDecorator::class => 'getAction'
*/
'queueable_to_job' => [
SendQueuedMailable::class => 'mailable',
SendQueuedNotifications::class => 'notification',
CallQueuedClosure::class => 'closure',
CallQueuedListener::class => 'class',
BroadcastEvent::class => 'event',
],

/*
* Jobs tenant aware even if these don't implement the TenantAware interface.
*/
Expand Down
4 changes: 2 additions & 2 deletions docs/requirements.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Requirements
weight: 3
weight: 4
---

This package requires **PHP 8.0+** and **Laravel 8.0+**.
This package requires **PHP 8.2+** and **Laravel 11.0+**.
2 changes: 1 addition & 1 deletion docs/support-us.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Support us
weight: 2
weight: 3
---

We invest a lot of resources into creating our [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).
Expand Down
39 changes: 39 additions & 0 deletions docs/upgrade-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
title: Upgrade guide
weight: 2
---

In the `4.x` version, we have introduced the contract concept to the Tenant so that any model could implement the interface.

The first step to reach our goal is upgrading our package version.

```bash
composer require spatie/laravel-multitenancy:^4.0
```

### Removed `UsesTenantModel` trait
Remove any reference to our old trait `Spatie\Models\Concerns\UsesTenantModel`, because now the right `Tenant` instance can be resolved using `app(IsTenant::class)`.

### Tenant finder
If you are using the default finder included in the package, no changes are required by your side. However, when you are using a custom finder, you need to change the returned value in `findForRequest` method to `?IsTenant`. Example:

```php
use Illuminate\Http\Request;
use Spatie\Multitenancy\Contracts\IsTenant;

class YourCustomTenantFinder extends TenantFinder
{
public function findForRequest(Request $request): ?IsTenant
{
// ...
}
}
```

### Custom tasks
As has already been pointed out for the finder, the same change is required for any task because our `SwitchTenantTask` interface now is:
```php
public function makeCurrent(IsTenant $tenant): void;
```

So, it requires replacing the method parameter from `Tenant $tenant` to `IsTenant $tenant.`
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ A task is any class that implements `Spatie\Multitenancy\Tasks\SwitchTenantTask`
```php
namespace Spatie\Multitenancy\Tasks;

use Spatie\Multitenancy\Models\Tenant;

interface SwitchTenantTask
use Spatie\Multitenancy\Contracts\IsTenant;interface SwitchTenantTask
{
public function makeCurrent(Tenant $tenant): void;
public function makeCurrent(IsTenant $tenant): void;

public function forgetCurrent(): void;
}
Expand All @@ -27,7 +25,7 @@ Here is an example implementation where we are going to use a prefix when a tena
```php
namespace Spatie\Multitenancy\Tasks;

use Spatie\Multitenancy\Models\Tenant;
use Spatie\Multitenancy\Contracts\IsTenant;

class PrefixCacheTask implements SwitchTenantTask
{
Expand All @@ -36,7 +34,7 @@ class PrefixCacheTask implements SwitchTenantTask
$this->originalPrefix ??= config('cache.prefix');
}

public function makeCurrent(Tenant $tenant): void
public function makeCurrent(IsTenant $tenant): void
{
$this->setCachePrefix("tenant_{$tenant->id}");
}
Expand Down
Loading

0 comments on commit 8a22870

Please sign in to comment.