Laravel-hyn/multi-tenancy多租戶擴展的使用

       使用相同的Laravel安裝來運行多個網站,同時將租戶特定的數據分開以實現完全獨立的多域設置。沒錯你沒聽錯,就是這麼爽,Saas項目的福音,由此可見laravel有多香。目前這個包還在維護中,使用人數就已經超過1000了,我花了3-5天研究了一下這個東西,是真的香。由於是歪果仁開發的,所以文檔對國內開發者不是特別友好,造成了衆多小夥伴使用不便,這裏我就給大家分享一下我的經驗。

       很多人不理解這個包是幹什麼的,所以上去就開始看文檔,這樣很浪費時間。正如文章開頭說的,使用相同的Laravel安裝來運行多個網站,同時將租戶特定的數據分開以實現完全獨立的多域設置。其原理就是配置生成的子域會同時生成相對應的數據庫,生成的域和數據庫由包的內置程序生成的UUID來綁定關係,訪問域名的時候程序就會訪問對應的數據庫,從而實現多租戶之間的數據隔離(傳統意義上的分庫)。你要說它的用處在哪,那就是多用於Saas服務,同一套代碼不需要重新部署服務器環境就可以提供給多個用戶(這裏大多都是需要建站的客戶)使用,而租戶之間的數據是隔離的,也可用於b2b開發等。現在你大概知道它是幹什麼的吧。

       這裏我以laravel生態中的一個開源電商cms來講解具體如何使用它。

       1.首先你得確保本地安裝好一個項目並可以運行,這裏我就不演示了,我本地的項目就是Bagisto(cms項目),地址是https://xueyuanjun.com/post/19446.html

       2.安裝hyn包,composer安裝不用多說了吧,都懂。

       安裝之前的環境配置:  

  • Laravel 5.6或5.7。
  • PHP 7.2或更高版本。
  • MySQL 5.7以上版本,MariaDB 10.2.0以上版本或PostgreSQL 9以上版本。
  • (可選)Apache 2.4+或Nginx 1.12+。
  • Laravel的應用經驗

      由於這裏的cms項目是laravel5.6的,所以我使用的是hyn5.3,這裏順帶一提hyn目前更新到5.5版本,但不是特別穩定,官方推薦使用5.4版。順帶一提,國內常用的PHP本地開發集成環境一般使用的是wamp和PHPstudy等,這裏我建議使用後者,PHPstudy目前已更新到8.1版,功能強大方便實用,php開發者必備神器!

      安裝準備:

      a.本地數據庫準備(這裏我使用的是mysql),由於多租戶的數據是分庫來處理的,所以需要數據庫用戶有創庫權限,利用的是mysql的“GRANT OPTION”特性,在本地mysql中運行以下代碼:

CREATE DATABASE IF NOT EXISTS bagisto;
CREATE USER IF NOT EXISTS root@localhost IDENTIFIED BY 'yourPASSWORD';
GRANT ALL PRIVILEGES ON *.* TO root@localhost WITH GRANT OPTION;

     *注意這裏的“bagisto”是我本地cms的數據庫,下面會說明會將其設置爲系統數據庫,給root用戶權限。

      b.配置系統數據庫,在你的項目中config/database.php中創建系統數據庫連接配置:

'system' => [
    'driver' => 'mysql',
    'host' => env('TENANCY_HOST', '127.0.0.1'),
    'port' => env('TENANCY_PORT', '3306'),
    'database' => env('TENANCY_DATABASE', 'bagisto'),
    'username' => env('TENANCY_USERNAME', 'root'),
    'password' => env('TENANCY_PASSWORD', 'yourPASSWORD'),
    'unix_socket' => env('DB_SOCKET', ''),
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => '',
    'strict' => true,
    'engine' => null,
]

     *注意建議將配置信息寫到.env文件中,不需要創建'tenant'數據庫配置項,hyn包在連接租戶數據庫情況下會自動創建'tenant'連接

     c.在config/tenancy.php配置裏將website->uuid-limit-length-to-32狀態設置爲開啓

     安裝:

     運行composer命令以添加租賃包作爲依賴項

composer require "hyn/multi-tenant:5.3.*"

     發佈配置文件和遷移以進行租用,配置軟件包

php artisan vendor:publish --tag=tenancy

     選擇你要遷移的數據庫遷移,主要是生成hostname和websites表

php artisan migrate --database=system

 生成了system連接庫的遷移文件後,就可將其庫內表遷移到新建的網站庫裏了,在tenancy.php配置中,將其設置db > tenant-migrations-path爲有效的絕對路徑,並且默認情況下,所有新租戶將運行這些遷移。 

// ..
  "tenant-migrations-path" => database_path('migrations/tenant'),
// ..

 如果你還想填充新創建和遷移的租戶的數據庫,則可以db > tenant-seed-classtenancy.php 配置文件中啓用。將此設置更改爲完全命名空間的類名,程序包將在運行自動遷移後自動運行該遷移。

租賃已將--website_id[=WEBSITE_ID]選項添加到以下每個本機Laravel遷移和種子命令中,並相應地爲其命名空間。

  • tenancy:migrate -運行數據庫遷移
  • tenancy:migrate:refresh -重置並重新運行所有遷移
  • tenancy:migrate:reset -回滾所有數據庫遷移
  • tenancy:migrate:rollback -回滾上一次數據庫遷移
  • tenancy:db:seed -用記錄爲數據庫播種

--website_id可選選項接受多個值。儘管是可選的,但如果保留該選項,它將對所有租戶運行該命令。例如:

  • php artisan tenancy:migrate --website_id=1 僅遷移租戶網站1。
  • php artisan tenancy:migrate --website_id=1 --website_id=2 遷移租戶網站1和2。
  • php artisan tenancy:migrate 遷移所有租戶網站。 

website_id對應了自動遞增id的網站列並不是UUID。 

   至此你的安裝算是完成了。

   3.創建網站和使用

   文檔中給出的代碼示例很清晰,但如果你是像我一樣爲cms部署多網站訪問,你就會進入誤區,這段創建新站的代碼在那裏寫?!如果你正在開發一個新項目,那這段建站代碼就是你要開發的建站功能,在哪裏寫就不用多說了吧!但如果你和我一樣,是爲了節約開發成本,部署一個cms的多站訪問,那就可以直接php artisan tinker運行建站代碼。這裏我就以我的方式來講解。

   在調試臺中運行建站代碼之前,你需要知道hyn訪問子域的原理。我們都知道,如果你在本地部署一個項目就必須通hostname來訪問(這裏以apache服務舉例),這個時候在apache中就會生成一個vhost文件,這個conf文件的作用就不用多說了吧,而建站代碼中會生成一個conf文件在項目中(位置在storage/app/tenancy/webserver/apache2/),這個時候你需要在本地服務的配置文件中將這個生成的臨時conf加載到本地apache服務中,而hyn就會依據這個臨時conf文件去訪問這個項目(注意此時的臨時conf文件和創建的子域是有綁定關係的,這個在建站代碼中邏輯清晰可見)。所以你需要做的有兩步:

    a.在項目config/webserver.php中開啓生成臨時conf文件配置apache2->enabled,注意這裏是一非常重要的步驟,生成的臨時文件不會自動加載到apache服務中,如果你是在本地部署,那隻需要重啓本地apache服務,如果是在生產環境中,就必須修改websrever.php文件中重新啓動apache服務的命令,否則你每創建一個新站就要重啓線上環境,修改代碼如下:

            /**
             * Actions to run to work with the Apache2 service.
             */
            'actions' => [
                /**
                 * Action that asserts Apache2 is installed.
                 */
                'exists' => 'F:/phpstudy_pro/Extensions/Apache2.4.39/bin',
                /**
                 * Action to run to test the apache configuration.
                 *
                 * @set to a boolean to force the response of the test command.
                 * @info true succeeds, false fails
                 */
                'test-config' => 'httpd -t',
                /**
                 * Action to run to reload the apache service.
                 *
                 * @info set to null to disable reloading.
                 */
                'reload' => 'httpd -k restart'
            ]

    如何修改就不多說,根據你線上apache命令將httpd命令替換即可。

    b.在apache的配置文件中加載臨時vhost文件的路徑,只需添加以下代碼(我本地)

IncludeOptional F:/phpstudy_pro/WWW/bagisto/storage/app/tenancy/webserver/apache2/*.conf
 線上環境自行修改加載路徑。

  創建並綁定網站(這裏我是php artisan tinker直接運行):

use Hyn\Tenancy\Models\Website;
use Hyn\Tenancy\Contracts\Repositories\WebsiteRepository;
use Hyn\Tenancy\Models\Hostname;
use Hyn\Tenancy\Contracts\Repositories\HostnameRepository;

$website = new Website;
app(WebsiteRepository::class)->create($website);

$hostname = new Hostname;
$hostname->fqdn = 'dev.example.com';
$hostname = app(HostnameRepository::class)->create($hostname);
app(HostnameRepository::class)->attach($hostname, $website);

這裏生成的UUID是綁定網站和數據庫關係的標識,長度爲32位,如果不想使用系統中創建UUID的方法,文檔中也提供了另一種方法。

    新站的訪問:

    前文已經提到,創建新站(也可是子域)後就會生成這個網站對應的數據庫,但當前這個數據庫是一個空庫,要實現原項目的所有功能就必須將system連接的庫中所有表遷移過來,所以下一步就是將system連接庫的表遷移到當前庫裏(遷移表不填充數據,爲了在訪問時區分是否是新站)。一般的項目都不會將數據庫的表直接創建成遷移文件放在項目中,所以這個時候就需要逆向將表創建成遷移文件,再執行遷移命令將表遷移到新庫中,這裏順帶給大家安利一下另一個laravel的工具(xethron/migrations-generator)。安裝依賴和執行命令如下:

composer require --dev "xethron/migrations-generator"

下載完成後再app中註冊服務

// 省略之前內容
'providers'       => [
    // 省略之前內容
    Way\Generators\GeneratorsServiceProvider::class,
    Xethron\MigrationsGenerator\MigrationsGeneratorServiceProvider::class,
],

指定某張表生成遷移文件

php artisan migrate:generate table1,table2,table3

反向忽略某些表

php artisan migrate:generate --ignore="table3,table4,table5"

*注意這裏的system連接數據庫中,hostname和websites表不需要遷移,所以建議忽略這兩張表

  4.訪問新建站點

   a.訪問你新建的站點“dev.example.com”,如果你本地使用的是PHPstudy8.1,可能會出現無法解析php文件的問題,這是因爲生成的臨時vhost文件中沒有加載使用php的路徑,而新版PHPstudy8.1中vhost文件配置了php的加載路徑,這是爲了可以選用php版本而添加的配置項,所以你需要修改臨時的vhost文件(可建立“www.example.com”vhost文件,仿照修改)。如果你覺得這樣麻煩還可以去修改生成臨時vhost文件的模板,在vendor/hyn/multi-tenant/assets/generators/webserver/apache/blocks/中。

  b.訪問成功後測試數據是否是新庫數據(或者連接的是否是新庫)。

   hyn在訪問新站點域名時會自動生成一個tenant連接,這個連接對應的數據庫即是當前網站的數據庫,不過在這之前,你需要在所有映射表model裏面use 兩個Traits,即Notifiable和UsesTenantConnection,否則訪問的任然是system連接庫,或者可以使用租戶路由(這裏不多做解釋,可以查看文檔)。

   至此,hyn就算是運用成功了。

整理不易,轉載請帶出處!!!

參考文檔https://tenancy.dev/docs

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章