使用相同的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-class
在tenancy.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就算是運用成功了。
整理不易,轉載請帶出處!!!