mirror of
https://github.com/stancl/tenancy-docs.git
synced 2025-12-12 18:24:03 +00:00
* fixed typo Don't know what exactly this line is referring to (eg, `CentralConnection` concern, the `$tenant->run...` function, or something else)...but I'm 95% sure this was a typo in one direction or the other. Hope that helps! * Update tenants.blade.md Co-authored-by: Samuel Štancl <samuel@archte.ch>
144 lines
5.2 KiB
Markdown
144 lines
5.2 KiB
Markdown
---
|
|
title: Tenants
|
|
extends: _layouts.documentation
|
|
section: content
|
|
---
|
|
|
|
# Tenants {#tenants}
|
|
|
|
A tenant can be any model that implements the `Stancl\Tenancy\Contracts\Tenant` interface.
|
|
|
|
The package comes with a base `Tenant` model that's ready for common things, though will require extending in most cases as it attempts not to be too opinionated.
|
|
|
|
The base model has the following features on top of the ones that are necessary by the interface:
|
|
|
|
- Forced central connection (lets you interact with `Tenant` models even in the tenant context)
|
|
- Data column trait — lets you store arbitrary keys. Attributes that don't exist as columns on your `tenants` table go to the `data` column as serialized JSON.
|
|
- Id generation trait — when you don't supply an ID, a random uuid will be generated. An alternative to this would be using AUTOINCREMENT columns. If you wish to use numerical ids, change the `create_tenants_table` migration to use `bigIncrements()` or some such column type, and set `tenancy.id_generator` config to null. That will disable the ID generation altogether, falling back to the database's autoincrement mechanism.
|
|
|
|
## Tenant Model {#tenant-model}
|
|
**Most** applications using this package will want domain/subdomain identification and tenant databases. To do this, create a new model, e.g. `App\Tenant`, that looks like this:
|
|
|
|
```php
|
|
<?php
|
|
|
|
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, configure the package to use this model in `config/tenancy.php`:
|
|
|
|
```php
|
|
'tenant_model' => \App\Tenant::class,
|
|
```
|
|
|
|
If you want to customize the `Domain` model, you can do that too.
|
|
|
|
**If you don't need domains or databases, ignore the steps above.** Everything will work just as well.
|
|
|
|
## Creating tenants {#creating-tenants}
|
|
|
|
You can create tenants like any other models:
|
|
|
|
```php
|
|
$tenant = Tenant::create([
|
|
'plan' => 'free',
|
|
]);
|
|
```
|
|
|
|
After the tenant is created, an event will be fired. This will result in things like the database being created and migrated, depending on what jobs listen to the event.
|
|
|
|
## Custom columns {#custom-columns}
|
|
|
|
Attributes of the tenant model which don't have their own column will be stored in the `data` JSON column. You can set these attributes like you'd set normal model attributes:
|
|
|
|
```php
|
|
$tenant->update([
|
|
'attributeThatHasNoColumn' => 'value', // stored in the `data` JSON column
|
|
'plan' => 'free' // stored in the dedicated `plan` column (see below)
|
|
]);
|
|
```
|
|
or
|
|
```php
|
|
$tenant->customAttribute = 'value'; // stored in the `data` JSON column
|
|
$tenant->plan = 'free'; // stored in the `plan` column (see below)
|
|
$tenant->save();
|
|
```
|
|
|
|
You may define the custom columns (that **won't** be stored in the `data` JSON column) by overriding the `getCustomColumns()` method on your `Tenant` model:
|
|
|
|
```php
|
|
public static function getCustomColumns(): array
|
|
{
|
|
return [
|
|
'id',
|
|
'plan',
|
|
];
|
|
}
|
|
```
|
|
|
|
**Don't forget to keep `id` in the custom columns!**
|
|
|
|
If you want to rename the `data` column, rename it in a migration and implement this method on your model:
|
|
|
|
```php
|
|
public static function getDataColumn(): string
|
|
{
|
|
return 'my-data-column';
|
|
}
|
|
```
|
|
|
|
Note that querying data inside the `data` column with `where()` will require that you do for example:
|
|
```php
|
|
where('data->foo', 'bar')
|
|
```
|
|
|
|
The data column is encoded/decoded only on model retrieval and saving.
|
|
|
|
Also a good rule of thumb is that when you need to query the data with `WHERE` clauses, it should have a dedicated column. This will improve performance and you won't have to think about the `data->` prefixing.
|
|
|
|
## Running commands in the tenant context {#running-commands-in-the-tenant-context}
|
|
|
|
You may run commands in a tenant's context and then return to the previous context (be it central, or another tenant's) by passing a callable to the `run()` method on the tenant object. For example:
|
|
|
|
```php
|
|
$tenant->run(function () {
|
|
User::create(...);
|
|
});
|
|
```
|
|
|
|
## Internal keys {#internal-keys}
|
|
|
|
Keys that start with the internal prefix (`tenancy_` by default, but you can customize this by overriding the `internalPrefix()` method) are for internal use, so don't start any attribute/column names with that.
|
|
|
|
## Events {#events}
|
|
|
|
The `Tenant` model dispatches Eloquent events, all of which have their own respective class. You can read more about this on the [Event system]({{ $page->link('event-system') }}) page.
|
|
|
|
## Accessing the current tenant {#accessing-the-current-tenant}
|
|
|
|
You may access the current tenant using the `tenant()` helper. You can also pass an argument to get an attribute from that tenant model, e.g. `tenant('id')`.
|
|
|
|
Alternatively, you may typehint the `Stancl\Tenancy\Contracts\Tenant` interface to inject the model using the service container.
|
|
|
|
## Incrementing IDs {#incrementing-ids}
|
|
|
|
By default, the migration uses `string` for the `id` column, and the model generates UUIDs when you don't supply an `id` during tenant creation.
|
|
|
|
If you'd like to use incrementing ids instead, you can override the `getIncrementing()` method:
|
|
|
|
```php
|
|
public function getIncrementing()
|
|
{
|
|
return true;
|
|
}
|
|
```
|