Tenant Models
When working with Laravel, you're almost always going to be working with Eloquent, and tenants are no different.
This page assumes that you've read the tenants documentation and are familiar with the concept of tenants within Sprout.
Introduction
Every multitenanted application needs a tenant, and if you're using Laravel, you're probably using Eloquent, so it stands to reason that your tenant will be an Eloquent model. If this is the case, you'll be pleased to know that Sprout comes with a handful of functionality to make creating tenants that are Eloquent models as simple as can be.
Creating the tenant model
The first thing you're going to want to do is create your model,
whether you do that manually or using the make:model
artisan command.
Once you've got this done, you'll want to implement the Sprout\Contracts\Tenant
interface.
1namespace Workbench\App\Models; 2 3use Illuminate\Database\Eloquent\Model; 4use Sprout\Contracts\Tenant; 5 6class Blog extends Model implements Tenant 7{ 8 protected $table = 'blogs'; 9 10 protected $fillable = [11 'name',12 'identifier',13 ];14}
Now, rather than implement all the methods required by the Sprout\Contracts\Tenant
class manually,
you can make use of the Sprout\Database\Eloquent\Concerns\IsTenant
trait.
1namespace Workbench\App\Models; 2 3use Illuminate\Database\Eloquent\Model; 4use Sprout\Contracts\Tenant; 5use Sprout\Database\Eloquent\Concerns\IsTenant; 6 7class Blog extends Model implements Tenant 8{ 9 use IsTenant;10 11 protected $table = 'blogs';12 13 protected $fillable = [14 'name',15 'identifier',16 ];17}
And there you have it, a fully working tenant model. Remember to add it to the tenant providers config using the eloquent tenant provider.
Tenant models with Resources
If your tenant has resources,
you'll also want to implement the Sprout\Contracts\TenantHasResources
interface.
1namespace Workbench\App\Models; 2 3use Illuminate\Database\Eloquent\Model; 4use Sprout\Contracts\Tenant; 5use Sprout\Contracts\TenantHasResources; 6use Sprout\Database\Eloquent\Concerns\IsTenant; 7 8class Blog extends Model implements Tenant, TenantHasResources 9{10 use IsTenant;11 12 protected $table = 'blogs';13 14 protected $fillable = [15 'name',16 'identifier',17 'resource_key',18 ];19}
Again, rather than implement all the methods manually,
you can use the Sprout\Database\Eloquent\Concerns\HasTenantResources
trait.
1namespace Workbench\App\Models; 2 3use Illuminate\Database\Eloquent\Model; 4use Sprout\Contracts\Tenant; 5use Sprout\Contracts\TenantHasResources; 6use Sprout\Database\Eloquent\Concerns\IsTenant; 7use Sprout\Database\Eloquent\Concerns\HasTenantResources; 8 9class Blog extends Model implements Tenant, TenantHasResources10{11 use IsTenant, HasTenantResources;12 13 protected $table = 'blogs';14 15 protected $fillable = [16 'name',17 'identifier',18 ];19}
How it works
While the above code will work fine, and will be all that's required for the majority of use cases, there will be times when you need to customise it. To do this, you'll need to understand what's happening.
The tenant identifier
When using this trait,
it is assumed that the tenant identifier is called identifier
,
as provided by the getTenantIdentifierName()
implementation.
The getTenantIdentifier()
method actually makes use of the name method,
so if you need to change the attribute used as an identifier, just override the getTenantIdentifierName()
method.
1public function getTenantIdentifier(): string2{3 return $this->getAttribute($this->getTenantIdentifierName());4}5 6public function getTenantIdentifierName(): string7{8 return 'identifier';9}
The tenant key
When using this trait, the tenant key functionality piggybacks on the primary key functionality provided by Eloquent, so you'll want to make sure that your model is configured correctly.
1public function getTenantKey(): int|string2{3 return $this->getKey();4}5 6public function getTenantKeyName(): string7{8 return $this->getKeyName();9}
The tenant resource key
If your tenant has resources,
and you're using the Sprout\Database\Eloquent\Concerns\HasTenantResources
trait,
the key is assumed to be contained within the resource_key
attribute.
Just like with the identifier, if you want to override this,
you only need to override the getTenantResourceKeyName()
method.
1public function getTenantResourceKey(): string2{3 return (string)$this->getAttribute($this->getTenantResourceKeyName());4}5 6public function getTenantResourceKeyName(): string7{8 return 'resource_key';9}
Automatic UUIDs
The HasTenantResources
trait also does one other thing.
When a model is being created (it is being saved but hasn't been sent to the database yet),
if the resource key attribute is null
, it will be set with a UUID using Illuminate\Support\Str::uuid()
.
1static::creating(static function (Model&TenantHasResources $model) {2 if ($model->getAttribute($model->getTenantResourceKeyName()) === null) {3 $model->setAttribute(4 $model->getTenantResourceKeyName(),5 Str::uuid()6 );7 }8});
If you're manually setting the tenant resource key, this code will never run, so you don't need to worry about it.