thinkphp实现二级域名绑定与短信通道隔离,关键在于按子域名动态加载独立短信配置(如网关、签名、模板),通过route::domain()绑定路由分组,结合nginx透传http_host及dns泛解析,确保各业务线(admin/api/shop)短信服务完全隔离。

ThinkPHP 实现二级域名绑定 + 短信通道隔离,关键不在“绑一起”,而在“分开管”:每个子域名(如 admin.example.com、api.example.com、shop.example.com)对应独立业务线,应使用专属短信网关与签名模板,避免混用导致审核失败、限流误伤或风控拦截。
一、按子域名区分短信配置源
不共用一个 sms.php 静态配置,而是根据当前请求的子域名动态加载对应网关参数。核心逻辑在服务类中判断:
- 从
$request->host()提取子域名(如admin、shop) - 查表或读取配置映射:
['admin' => 'aliyun_admin', 'shop' => 'yunpian_shop'] - 构造 EasySms 配置数组时,只注入该业务线允许的网关及密钥(如 shop 线禁用阿里云,只配云片)
- 签名名(
sign_name)和模板码(template_code)也按子域名隔离,确保平台审核通过且不跨线复用
二、路由层绑定子域名与应用,自然隔离业务上下文
先让框架识别出是哪个业务线在发请求,后续短信服务才能精准匹配:
- 在
config/app.php中启用:'url_domain_deploy' => true - 在
route/app.php中注册明确绑定:Route::domain('admin', function () { require __DIR__ . '/admin.php'; }); - 各子域名路由文件(如
admin.php)里只定义本业务线可用接口,控制器命名空间可统一为app\admin\controller\,天然携带业务标识 - 这样,
SmsService构造时就能通过App::getAppNamespace()或请求上下文获知当前业务线,无需硬编码传参
三、短信服务类支持多通道运行时切换
封装的 SmsService 不应绑定固定网关,而要支持按场景动态选型:
- 构造函数接收
think\Cache和Overtrue\EasySms\SmsManager实例,但不立即初始化网关 - 新增
useChannel(string $channel)方法,用于指定本次发送使用的配置键(如'yunpian_shop') -
sendCode()内部调用前,先调用$this->sms->setConfig($configForChannel)切换上下文 - 验证码缓存 Key 也带上子域名维度:
cache()->tag('sms')->set("sms:code:{$mobile}:{$scene}:{$subDomain}", $code, 900)
四、Web服务器与DNS配合,确保 Host 可达
再精细的 PHP 层逻辑,也依赖底层能正确传递子域名信息:
- Nginx 配置中必须包含:
fastcgi_param HTTP_HOST $host;,否则$request->host()可能为空或错误 - 若用泛解析(
*.example.com),Nginx 的server_name建议写成~^(?<sub>.+)\.example\.com$</sub>,并透传$sub变量供 PHP 使用 - DNS 解析需确保所有子域名都指向同一台服务器 IP,避免部分子域无法访问导致配置失效
- 本地测试时,在
/etc/hosts或 Windows 的hosts文件中添加多行映射:127.0.0.1 admin.example.com、127.0.0.1 shop.example.com
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











