PHP code example of michaelnabil230 / laravel-multi-tenancy
1. Go to this page and download the library: Download michaelnabil230/laravel-multi-tenancy library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
michaelnabil230 / laravel-multi-tenancy example snippets
use MichaelNabil230\MultiTenancy\Events;
use MichaelNabil230\MultiTenancy\Listeners;
return [
/**
* NameServer of the server for ex:'ns1.contabo.net'.
*/
'name_server' => null,
/**
* The list of domains hosting your central app.
*
* Only relevant if you're using the domain or subdomain identification middleware.
*/
'central_domains' => [
'127.0.0.1',
'localhost',
],
/*
* These fields are used by tenant:artisan command to match one or more tenant
*/
'artisan_search_fields' => [
'id',
],
/**
* All events for tenancy
*/
'events' => [
// Tenant events
Events\Tenant\CreatingTenant::class => [],
Events\Tenant\TenantCreated::class => [
Listeners\SeedDatabase::class,
],
Events\Tenant\SavingTenant::class => [],
Events\Tenant\TenantSaved::class => [],
Events\Tenant\UpdatingTenant::class => [],
Events\Tenant\TenantUpdated::class => [],
Events\Tenant\DeletingTenant::class => [],
Events\Tenant\TenantDeleted::class => [],
// Domain events
Events\Domain\CreatingDomain::class => [],
Events\Domain\DomainCreated::class => [],
Events\Domain\SavingDomain::class => [],
Events\Domain\DomainSaved::class => [],
Events\Domain\UpdatingDomain::class => [],
Events\Domain\DomainUpdated::class => [],
Events\Domain\DeletingDomain::class => [],
Events\Domain\DomainDeleted::class => [],
// DataBase events
Events\DataBase\SeedingDatabase::class => [],
Events\DataBase\DatabaseSeeded::class => [],
// Tenancy events
Events\Tenancy\InitializingTenancy::class => [],
Events\Tenancy\TenancyInitialized::class => [
Listeners\BootstrapTenancy::class,
],
Events\Tenancy\EndingTenancy::class => [],
Events\Tenancy\TenancyEnded::class => [
Listeners\RevertToCentralContext::class,
],
Events\Tenancy\BootstrappingTenancy::class => [],
Events\Tenancy\TenancyBootstrapped::class => [],
Events\RevertingToCentralContext::class => [],
Events\RevertedToCentralContext::class => [],
],
/**
* Tenancy bootstrappers are executed when the tenancy is initialized.
* Their responsibility is making Laravel features tenant-aware.
*
* To configure their behavior, see the config keys below.
*/
'bootstrappers' => [
MichaelNabil230\MultiTenancy\Bootstrappers\CacheTenancyBootstrapper::class,
MichaelNabil230\MultiTenancy\Bootstrappers\FilesystemTenancyBootstrapper::class,
MichaelNabil230\MultiTenancy\Bootstrappers\QueueTenancyBootstrapper::class,
// MichaelNabil230\MultiTenancy\Bootstrappers\RedisTenancyBootstrapper::class, // Note: phpredis is needed
],
/**
* Redis tenancy config. Used by RedisTenancyBootstrapper.
*
* Note: You need phpredis to use Redis tenancy.
*
* Note: You don't need to use this if you're using Redis only for the cache.
* Redis tenancy is only relevant if you're making direct Redis calls,
* either using the Redis facade or injecting it as a dependency.
*/
'redis' => [
'prefix_base' => 'tenant', // Each key in Redis will be prepended by this prefix_base, followed by the tenant id.
'prefixed_connections' => [ // Redis connections whose keys are prefixed, to separate one tenant's keys from another.
// 'default',
],
],
/**
* Cache tenancy config. Used by CacheTenancyBootstrapper.
*
* This works for all Cache facade calls, cache() helper
* calls and direct calls to injected cache stores.
*/
'cache_prefix_key' => 'tenant_id_',
/**
* The session key Middleware in `ScopeSessions`
*/
'session_key' => 'ensure_valid_tenant_session_tenant_id',
/**
* Filesystem tenancy config. Used by FilesystemTenancyBootstrapper.
*/
'filesystem' => [
/**
* Each disk listed in the 'disks' array will be suffixed by the suffix_base, followed by the tenant_id.
*/
'suffix_base' => 'tenant',
'disks' => [
'local',
'public',
// 's3',
],
/**
* Use this for local disks.
*/
'root_override' => [
// Disks whose roots should be override after storage_path() is suffixed.
'local' => '%storage_path%/app/',
'public' => '%storage_path%/app/public/',
],
/**
* Should storage_path() be suffixed.
*
* Note: Disabling this will likely break local disk tenancy. Only disable this if you're using an external file storage service like S3.
*
* For the vast majority of applications, this feature should be enabled. But in some
* edge cases, it can cause issues (like using Passport with Vapor - see #196), so
* you may want to disable this if you are experiencing these edge case issues.
*/
'suffix_storage_path' => true,
/**
* By default, asset() calls are made multi-tenant too. You can use mix()
* for global, non-tenant-specific assets. However, you might have some issues when using
* packages that use asset() calls inside the tenant app. To avoid such issues, you can
* disable asset() helper tenancy and explicitly use tenant_asset() calls in places
* where you want to use tenant-specific assets (product images, avatars, etc).
*/
'asset_helper_tenancy' => true,
],
/**
* Features are classes that provide additional functionality
* not needed for the tenancy to be bootstrapped. They are run
* regardless of whether the tenancy has been initialized.
*
* See the documentation page for each class to
* understand which ones you want to enable.
*/
'features' => [
// MichaelNabil230\MultiTenancy\Features\TelescopeTags::class,
// MichaelNabil230\MultiTenancy\Features\TenantSetting::class,
],
/**
* Parameters used by the db:seed command.
*/
'seeder_parameters' => [
'--class' => 'TenantDatabaseSeeder',
'--force' => true,
],
/**
* Subscription for Tenant
*/
'subscription' => [
/**
* Enable if you need tenant has subscription in your application
*/
'enable' => false,
/**
* Route for the subscription index
*/
'route' => null,
/**
* All events for subscription
*/
'events' => [
// Subscription events
Events\Subscription\SubscriptionCreated::class => [],
Events\Subscription\SubscriptionUpdated::class => [],
Events\Subscription\SubscriptionCancelled::class => [],
Events\Subscription\SubscriptionChangePlan::class => [],
Events\Subscription\SubscriptionRenewed::class => [],
Events\Subscription\SubscriptionResume::class => [],
],
],
];
\MichaelNabil230\MultiTenancy\MultiTenancy::$onFail = function () {
return redirect('https://my-central-domain.com/');
};
MultiTenancy::tenant();
// Can be change with the pass model name.
MultiTenancy::useTenantModel(Model::class);
MultiTenancy::domain();
// Can be change with the pass model name.
MultiTenancy::useDomainModel(Model::class);
Route::middleware([
'web',
InitializeTenancyByDomain::class,
])->group(function () {
Route::get('/', function () {
return 'This is your multi-tenant application. The id of the current tenant is ' . tenant('id');
});
});
class Post extends Model
{
use BelongsToTenant;
public function comments()
{
return $this->hasMany(Comment::class);
}
}
class Comment extends Model
{
public function post()
{
return $this->belongsTo(Post::class);
}
}
Comment::all();
class Comment extends Model
{
use BelongsToPrimaryModel;
public function getRelationshipToPrimaryModel(): string
{
return 'post';
}
public function post()
{
return $this->belongsTo(Post::class);
}
}
$table->unique('slug');
$table->unique(['tenant_id', 'slug']);
// Imagine we're in a 'comments' table migration
$table->unique(['post_id', 'user_id']);
// You may retrieve the current tenant using the tenant() helper.
// $tenant = tenant();
$rules = [
'id' => $tenant->exists('posts'),
'slug' => $tenant->unique('posts'),
]
use Illuminate\Console\Command;
use MichaelNabil230\MultiTenancy\Commands\Concerns\TenantAware;
class YourFavoriteCommand extends Command
{
use TenantAware;
protected $name = 'your-favorite-command';
public function handle()
{
return $this->line('The tenant is '. Tenant::current()->name);
}
}
use MichaelNabil230\MultiTenancy\MultiTenancy;
$plan = MultiTenancy::plan()->create([
'name' => 'Pro',
'description' => 'Pro plan',
'price' => 9.99,
'invoice_period' => 1,
'invoice_interval' => 'month',
'trial_period' => 15,
'trial_interval' => 'day',
]);
// Create multiple plan features at once
$plan->features()->saveMany([
new Feature(['name' => 'listings']),
new Feature(['name' => 'pictures_per_listing']),
new Feature(['name' => 'listing_duration_days', 'resettable_period' => 1, 'resettable_interval' => 'month']),
new Feature(['name' => 'listing_title_bold'])
]);
$plans = MultiTenancy::plans();
$plan = MultiTenancy::plan()->find(1);
// Get all plan features
$plan->features;
// Get all plan subscriptions
$plan->subscriptions;
// Check if the plan is free
$plan->isFree();
// Check if the plan has trial period
$plan->hasTrial();
// Get subscriptions by plan
$subscriptions = MultiTenancy::subscription()->planId($planId)->get();
// Get subscriptions recurring
$subscriptions = MultiTenancy::subscription()->recurring()->get();
// Get subscriptions canceled
$subscriptions = MultiTenancy::subscription()->canceled()->get();
// Get subscriptions not canceled
$subscriptions = MultiTenancy::subscription()->notCanceled()->get();
// Get subscriptions with ended period
$subscriptions = MultiTenancy::subscription()->ended()->get();
// Get subscriptions with on trial period
$subscriptions = MultiTenancy::subscription()->onTrial()->get();
// Get subscriptions with expired trial period
$subscriptions = MultiTenancy::subscription()->expiredTrial()->get();
// Get subscriptions with not on trial
$subscriptions = MultiTenancy::subscription()->notOnTrial()->get();
// Get subscriptions with on grace period
$subscriptions = MultiTenancy::subscription()->onGracePeriod()->get();
// Get subscriptions with not on grace period
$subscriptions = MultiTenancy::subscription()->notOnGracePeriod()->get();