MultisiteGroup

MultisiteGroup

Learn how to scope model records to a site group for multi-tenancy.

For an overview of when to use this trait versus Multisite or Translatable, see the Introduction.

The MultisiteGroup trait scopes model records to a site group, providing multi-tenancy support. Unlike the Multisite trait which creates duplicate rows per site, MultisiteGroup filters a single set of records by the active site group. Each site group typically represents a distinct website or tenant.

For example, a "Dogs" website and a "Cats" website might share the same October CMS installation but have completely separate product catalogs. MultisiteGroup ensures each tenant only sees its own data.

# Declaration

To scope a model by site group, apply the October\Rain\Database\Traits\MultisiteGroup trait.

class Product extends Model
{
    use \October\Rain\Database\Traits\MultisiteGroup;
}

To add a site_group_id column to your table, use the integer method inside a migration.

Schema::table('products', function ($table) {
    $table->integer('site_group_id')->nullable()->index();
});

# How It Works

The trait registers a global scope that automatically filters queries by the active site group. When a model is saved, the site_group_id column is automatically set to the current site group from context.

// Only returns products belonging to the active site group
$products = Product::all();

When the global context is active (via Site::withGlobalContext), the scope is bypassed and records from all site groups are accessible.

Site::withGlobalContext(function() {
    // Returns products from all site groups
    $allProducts = Product::all();
});

# Programmatic Toggling

The isMultisiteGroupEnabled method returns true by default. Override it to conditionally disable the global scope.

public function isMultisiteGroupEnabled(): bool
{
    return Site::hasSiteGroups();
}

# Custom Column Name

By default the trait uses site_group_id as the column name. You may customize this by defining the SITE_GROUP_ID constant on your model.

const SITE_GROUP_ID = 'my_group_column';

# Combining with Translatable

MultisiteGroup and Translatable work naturally together. The group scopes which records are visible, while Translatable handles per-attribute translations within the group's languages.

class Product extends Model
{
    use \October\Rain\Database\Traits\MultisiteGroup;
    use \October\Rain\Database\Traits\Translatable;

    public $translatable = ['name', 'description'];
}

In this configuration, each site group (tenant) has its own product catalog, and the product names and descriptions can be translated across the languages defined within that group.

# See Also