pronique/multitenant

此软件包已被废弃,不再维护。未建议替代软件包。

MultiTenant CakePHP 插件 - 使用此插件可以轻松构建启用 SaaS 的 Web 应用程序。

安装: 983

依赖项: 0

建议者: 0

安全: 0

星星: 36

观察者: 12

分支: 16

开放问题: 6

类型:cakephp-plugin

dev-master 2017-01-05 15:26 UTC

This package is not auto-updated.

Last update: 2021-08-16 16:50:25 UTC


README

MultiTenant CakePHP 插件 - 使用此插件可以轻松构建启用 SaaS 的 Web 应用程序。

版本说明

此插件仅支持 CakePHP 3.x

项目目前正在开发中,目前处于实验阶段。

简介

最好在开始开发应用程序时实施 MultiTenant 插件,但通过一些工作,您应该能够将现有应用程序修改为使用该插件。

插件目前实现了以下多租户架构(策略):

域名策略

  • 共享数据库,共享模式
  • 单个应用程序实例
  • 每个租户一个子域

租户

插件引入了租户的概念,租户代表每个客户账户。

租户可以有自己的用户、组和记录。数据范围到租户,租户在数据库中以账户(或您通过配置指定的任何模型/表)的形式表示。

上下文

MultiTenant 插件引入了上下文的概念,上下文是多租户插件工作的一部分。有两个预定义的上下文:“租户”和“全局”。

“全局”上下文

默认情况下,“全局”映射到 www.mydomain.com,并且您将在其中实现应用程序的非租户部分。例如,注册/注册代码。

“租户”上下文

“租户”上下文代表此租户。当用户通过子域访问应用程序时,这被认为是“租户”上下文。

自定义上下文

插件支持定义额外的上下文,这些自定义上下文映射到子域。现在,您的应用程序可以调用 MTApp::getContext() 来实现上下文感知的代码。

例如,创建一个名为“admin”的上下文并将其映射到子域“admin.mydomain.com”。

注意:上下文不是基于角色的授权的替代品,但在某些情况下可能是补充的。

作用域

您的应用程序的每个模型都可以实现五种作用域行为之一,这将根据上下文指定可访问的数据。这些作用域作为 CakePHP 行为实现。

全局作用域

全局作用域模型提供的数据可以被任何租户查询,但“租户”上下文中不允许插入/更新/删除操作。

租户作用域

在租户范围模型中提供的数据只能由所有者(租户)查询。插入操作限定于当前租户。更新和删除操作强制执行所有权,因此租户1不能更新/删除租户2的记录。

混合范围

混合范围模型在同一张表中提供全局记录和租户范围记录。当租户查询该表(在“租户”上下文中)时,将返回该租户的记录以及表中存在的全局记录。

租户插入的任何记录都限定于租户。租户不能更新/删除表中存在的全局记录。当然,租户也不能在表中选择/插入/更新/删除其他租户的记录。

共享范围

共享范围模型充当社区数据表。租户可以查询表中的所有记录,包括其他租户的记录。插入操作限定于当前租户。租户不能更新/删除其他租户的记录。

无范围

无范围模型为模型添加了范围,这是表达模型根本不设置范围的一种冗长方式。如果表有 account_id 字段,则使用插入租户的 id 来标记谁插入的记录。由于没有执行范围限制,任何租户都可以删除任何记录。

安装

composer

此插件的推荐安装方法是使用 composer。只需将其添加到您的 composer.json 配置文件中

{
	"require" : {
		"pronique/multitenant": "master-dev"
	}
}

git clone

或者,您可以将代码通过 git clone 直接克隆到您的应用程序中

git clone git://github.com/pronique/multitenant.git app/Plugin/MultiTenant

git submodule

或者将其添加为 git 模块,这比 git clone 更推荐,因为这样可以更容易地保持与开发同步

git submodule add git://github.com/pronique/multitenant.git app/Plugin/MultiTenant

配置

将以下内容添加到您的 config/bootstrap.php

<?php
Plugin::load('MultiTenant', ['bootstrap' => true, 'routes' => false]);
?>

将以下内容添加到应用程序配置文件 app.php 的底部

/**
 * MultiTenant Plugin Configuration
 *
 *
 * ## Options
 *
 * - `strategy` - 'domain' is currently the only implemented strategy
 * - `primaryDomain` - The domain for the main application
 *    value to false, when dealing with older versions of IE, Chrome Frame or certain web-browsing devices and AJAX
 * - `model` - The model that represents the tenant, usually 'Accounts'
 * - `redirectInactive` - URI to redirect when the tenant is not active or does not exist.  This should be a uri at the
 *	  primary domain, usually your signup page or feature pitch page with call-to-action signup button.
 * - `reservedDomains` - An array of names that cannot be chosen at signup
 * - `contextMap` - Associative array used to define additional custom contexts besides 'global' and 'tenant', 
 *    i.e. when domain admin.domain.com is matched MTApp::getContext() will return the custom context 'admin'. 
 * - `ScopedBehavior` - Application wide defaults for the ScopedBehavior Behavior
 * - `MixedBehavior` - Application wide defaults for the MixedBehavior Behavior
 *
 */
	'MultiTenant' => [
		'strategy'=>'domain',
		'primaryDomain'=>'www.example.com',
		'model'=>[
		  'className'=>'Accounts',
		  'field'=>'domain', //field of model that holds subdomain/domain tenants
		  'conditions'=>['is_active'=>1] //query conditions to match active accounts
		],
		'redirectInactive'=>'/register',
		'reservedDomains'=>[
			'admin',
			'superuser',
			'system',
			'www'
		],
		'contextMap' => [
			'admin'=>'admin.example.com' //an example of a custom context
		],
		'scopeBehavior'=>[
			'global_value'=>0, //global records are matched by this value
			'foreign_key_field'=>'account_id' //the foreign key field that associates records to tenant model
		]
	]

注意:粘贴上述配置时,别忘了在底部配置部分添加逗号。config\app.php 中的语法错误会导致静默失败(空白页面)。

使用方法

MTApp

MTApp 是一个静态类,您可以在应用程序的任何地方调用它。

use MultiTenant\Core\MTApp;

//Returns an entity of the current tenant
$tenant = MTApp::tenant();
echo $tenant->id;
//output 1

//Or the same thing in a single line;
echo MTApp::tenant()->id;
//output 1

//Another Example, you can reference any field in the underlying model
echo MTApp::tenant()->name;
//output Acme Corp.
use MultiTenant\Core\MTApp;

// Based on URL, we are in a tenant's sudomain, customera.example.com
echo MTApp::getContext();
//output 'tenant'

// Based on URL, we are in at the primary sudomain www.example.com
echo MTApp::getContext();
//output 'global'

// Assumming we have defined a custom context, we are in at the sudomain admin.example.com
echo MTApp::getContext();
//output 'admin'

var_dump( MTApp::isPrimary() );
//returns true if we are at the primaryDomain, false if we are at a tenant's subdomain or in a custom context.

您可以通过使用完整命名空间来调用类而省略 use MultiTenant\Core\MTApp;

\MultiTenant\Core\MTApp::tenant();

行为使用示例

TenantScopeBehavior

class SomeTenantTable extends Table {
	
	public function initialize(array $config) {
		...
		$this->addBehavior('MultiTenant.TenantScope');
		...
	}
	...
}

MixedScopeBehavior

class SomeMixedTable extends Table {
	
	public function initialize(array $config) {
		...
		$this->addBehavior('MultiTenant.MixedScope');
		...
	}
	...
}

GlobalScopeBehavior

class SomeCommonTable extends Table {
	
	public function initialize(array $config) {
		...
		$this->addBehavior('MultiTenant.GlobalScope');
		...
	}
	...
}

SharedScopeBehavior

class SomeSharedTable extends Table {
	
	public function initialize(array $config) {
		...
		$this->addBehavior('MultiTenant.SharedScope');
		...
	}
	...
}

无范围行为

class JustARegularTable extends Table {
	
	public function initialize(array $config) {
		...
		$this->addBehavior('MultiTenant.NoScope');
		...
	}
	...
}

错误

如果您偶然发现了一个错误,请随时创建一个带有修复方案、错误描述以及错误解决方法的pull request。

功能

提出新的功能建议的最佳方式是通过pull request。