视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
教你在几分钟内使Laravel应用拥有多租户功能
2020-11-02 18:44:43 责编:小采
文档


工作原理

这个包的独特之处在于它不会强迫您以特定的方式编写应用程序。你可以像你习惯的那样编写你的应用程序,它会在后台自动生成多租户。您甚至可以将包集成到现有的应用程序中。

以下是它的工作原理:

1.当服务器接收到用户请求
2.程序便可以通过请求识别该请求属于哪个租户。(通过主域名,子域名,路径,请求头,query 参数,等)
3.程序将会从 default 数据库链接切换为当前租户链接。
4.任意的数据库调用,缓存调用,队列调用,等操作都会自动匹配租户并切换。

安装

第一步,通过 composer 安装 package,命令如下:

composer require stancl/tenancy

然后,执行 tenancy:install 命令,如下:

php artisan tenancy:install

该操作会产生以下文件:迁移文件,配置文件,路由文件和一个服务提供者。

下面让我们把数据库建立起来,通过以下命令执行数据库迁移:

php artisan migrate

然后在 config/app.php注册服务提供者。请确定将代码放于以下位置:

/*
 * Application Service Providers...
 */
AppProvidersAppServiceProvider::class,
AppProvidersAuthServiceProvider::class,
// AppProvidersBroadcastServiceProvider::class,
AppProvidersEventServiceProvider::class,
AppProvidersRouteServiceProvider::class,
AppProvidersTenancyServiceProvider::class, // <-- 放于此处

现在,我们创建一个自定义的 tenant 模型。该程序包是不受的,因此要使用单独的数据库和域,我们需要创建一个略微定制的 tenant 模型。使用以下代码创建一个 app/Tenant.php 文件:

<?php

namespace App;

use StanclTenancyDatabaseModelsTenant as BaseTenant;
use StanclTenancyContractsTenantWithDatabase;
use StanclTenancyDatabaseConcernsHasDatabase;
use StanclTenancyDatabaseConcernsHasDomains;

class Tenant extends BaseTenant implements TenantWithDatabase
{
 use HasDatabase, HasDomains;
}

现在,我们告诉程序包将该模型用于 tenants:

// config/tenancy.php file

'tenant_model' => AppTenant::class,

两个部分

软件包将您的应用程序视为两个的部分:

  • central 应用程序 —— 承载登录页面,可能是管理 tenants 的仪表板等
  • tenant 应用程序 —— 这是您的用户 (tenants) 使用的部分。这很可能是大多数业务逻辑都存在的地方
  • 拆分应用

    了解了这两个部分,让我们将应用进行相应的拆分。

    Central app

    首先让我们确保 central 应用仅在中心域上可访问。

    转到 app/Providers/RouteServiceProvider.php,并确保您的 webapi 路由仅在域上加载:

    protected function mapWebRoutes()
    {
     foreach ($this->centralDomains() as $domain) {
     Route::middleware('web')
     ->domain($domain)
     ->namespace($this->namespace)
     ->group(base_path('routes/web.php'));
     }
    }
    
    protected function mapApiRoutes()
    {
     foreach ($this->centralDomains() as $domain) {
     Route::prefix('api')
     ->domain($domain)
     ->middleware('api')
     ->namespace($this->namespace)
     ->group(base_path('routes/api.php'));
     }
    }
    
    protected function centralDomains(): array
    {
     return config('tenancy.central_domains');
    }

    现在转到您的文件 config/tenancy.php,实际添加中心域。

    我使用的是 Valet,所以对我来说,中心域是 saas.test,租户域以 foo.saas.testbar.saas.test 为例。

    因此,我们设置 central_domains 键:

    'central_domains' => [
     'saas.test', // Add the ones that you use. I use this one with Laravel Valet.
    ],

    Tenant app

    现在是有趣的部分。这一部分几乎太简单了。

    要使某些代码具有租户意识,您只需执行以下操作:

  • 将迁移移动到 tenant/ 目录
  • 将路由移动到 tenant.php 路由文件
  • 就是这样。

    在该特定文件夹中进行迁移并且在该特定路由文件中包含路由将通知包标识该路由上的租户。

    如果您有现有的应用程序,请使用您的代码执行此操作。如果您使用的是全新应用,请按照以下示例操作:

    默认情况下,您的租户路由如下所示:

    Route::middleware([
     'web',
     InitializeTenancyByDomain::class,
     PreventAccessFromCentralDomains::class,
    ])->group(function () {
     Route::get('/', function () {
     return 'This is your multi-tenant application. The id of the current tenant is ' . tenant('id');
     });
    });

    这些路由只能在 tenant (非中心) 域上访问 —— PreventAccessFromCentralDomains 中间件会强制执行这一点。

    让我们做一点小更改以转储数据库中的所有用户,以便我们可以实际看到多租户工作。将此添加到中间件组:

    Route::get('/', function () {
     dd(AppUser::all());
     return 'This is your multi-tenant application. The id of the current tenant is ' . tenant('id');
    });

    现在,迁移。只需将与租户应用程序相关的迁移移动到database/migrations/tenant目录中即可。

    因此,对于我们的示例:要使用户进入租户数据库,让我们将users表迁移移至数据库/迁移/租户。这将防止在数据库中创建表,而是在创建租户时在租户数据库中创建表。

    尝试一下

    现在让我们创建一些租户。

    我们还没有可供租户注册的登录页面,但是我们可以在修补程序中创建他们!

    因此,让我们打开php artisan tinker并创建一些租户。租户实际上只是模型,因此您可以像其他任何Eloquent模型一样创建它们。

    请注意,我们在 这里使用域标识因此,请确保您使用的域指向您的应用程序。我正在使用代客,所以我正在*.saas.test用于租户。如果使用php artisan serve,则可以使用foo.localhost

     >> $tenant1 = Tenant::create(['id' => 'foo']);
     >> $tenant1->domains()->create(['domain' => 'foo.saas.test']);
    >>>
     >> $tenant2 = Tenant::create(['id' => 'bar']);
     >> $tenant2->domains()->create(['domain' => 'bar.saas.test']);

    现在,我们将在每个租户的数据库中创建一个用户:

    AppTenant::all()->runForEach(function () {
     factory(AppUser::class)->create();
    });

    就是这样- 我们有一个多租户应用程序!

    如果您访问 foo.saas.test (或与您的环境相当),则会看到用户转储。

    如果访问bar.saas.test,您将看到不同用户的转储 。数据库是100%分离的,我们使用的代码 —AppUser::all()— 根本不需要了解租约!这一切都会在后台自动发生。您只需像以前那样编写应用程序,而不必考虑自己的范围界定,并且一切都正常。

    当然,现在,租户应用程序中将有一个更复杂的应用程序。仅转储用户的SaaS可能用处不大。这就是您的工作-编写将由租户使用的业务逻辑。包装将处理其余部分。

    不过,Tenancy for Laravel 项目的帮助并没有到此结束。该软件包将为您完成与多租户相关的所有繁重工作。但是,如果您要构建SaaS,则仍然需要自己编写计费逻辑,入门流程和类似的标准内容。如果您有兴趣,该项目还提供了一个优质产品:multi-tenant SaaS boilerplate。它旨在通过为您提供通常需要编写的SaaS功能来节省您的时间。所有这些都打包在一个随时可以部署的多租户应用程序中。

    原文地址:https://laravel-news.com/multi-tenant

    译文地址:https://learnku.com/laravel/t/47951

    下载本文
    显示全文
    专题