必须同时满足PHP版本+TS/NTS+架构三重匹配,且安装Microsoft ODBC Driver 18为硬性前提;ThinkPHP 8需配置'type'=>'sqlsrv'、'hostname'=>'(local)'或实例名、显式指定'hostport'=>'1433'、'charset'=>'utf8',并实测PDO直连验证。

ThinkPHP 8 连 SQL Server 不是改个 DB_TYPE 就能通的,核心卡点在驱动匹配、ODBC 底层依赖和配置项细节。直接上结论:必须同时满足「PHP 版本+TS/NTS+架构」三重匹配,且 Microsoft ODBC Driver for SQL Server 是硬性前置条件,缺一不可。
确认 PHP 环境类型(TS/NTS + 架构)
很多连接失败根本没报错,只是 pdo_sqlsrv 加载失败——因为 DLL 文件名和你的 PHP 实际运行模式不一致。
- 运行
php -v查小版本号,比如输出PHP 8.3.12,就要找83开头的驱动 - 运行
php -i | findstr "Thread Safety"(Windows)或php -i | grep "Thread Safety"(Linux/macOS),结果为enabled→ 选ts;disabled→ 选nts - 查系统是 x64 还是 x86:
php -i | findstr "Architecture",绝大多数 Windows Server 2016+ 都是x64 - 别信“随便下个 php_sqlsrv.dll 就行”,文件名必须严格对应,例如
php_pdo_sqlsrv_83_nts_x64.dll
安装 Microsoft ODBC Driver(不是可选,是必须)
pdo_sqlsrv 扩展本身不直接通信,它依赖 Microsoft ODBC Driver for SQL Server 做底层协议转换。跳过这步,哪怕扩展加载成功,sqlsrv_connect() 或 PDO DSN 也会静默失败或抛出 TLS/SSL 协议错误。
- 去微软官网下载
ODBC Driver 18 for SQL Server(2026 年推荐首选,兼容 SQL Server 2022 + TLS 1.2+) - 安装时勾选「Register this driver as the default ODBC driver」,避免多版本冲突
- 装完后不用重启 PHP,但建议用
odbcad32.exe(Windows 自带)验证是否注册成功:打开「ODBC 数据源管理器」→「驱动程序」标签页,应能看到ODBC Driver 18 for SQL Server - 旧版如 ODBC Driver 11/13/17 容易在连接 SQL Server 2022 时因加密协商失败而卡住
ThinkPHP 8 的 database.php 配置要点
TP8 使用 config/database.php,不是旧版的 DB_TYPE 风格。常见错误是照搬 MySQL 配置习惯,漏掉关键参数或写错键名。
立即学习“PHP免费学习笔记(深入)”;
-
'type' => 'sqlsrv'必须小写,大写或拼错(如sqlserver)会报undefined db type -
'hostname'别写localhost或127.0.0.1—— SQL Server 默认不监听本地回环的 TCP/IP,改用(local)、.或完整实例名,如SERVERNAME\MSSQLSERVER -
'hostport'必须显式写'hostport' => '1433',即使默认端口也不能省略,否则 TP8 会忽略端口导致连接超时 -
'charset'推荐写'utf8'(不是utf-8或UTF8),SQL Server 对字符集名敏感,错写会导致中文乱码或连接中断 - 如果 SQL Server 启用了命名实例(如
SQLEXPRESS),DSN 中需包含实例名,但 TP8 不支持自动解析,此时建议直接用'hostname' => 'SERVERNAME\SQLEXPRESS',并确保 SQL Server Browser 服务已启动
验证连接是否真通(不止看 phpinfo)
看到 phpinfo 里有 pdo_sqlsrv 只代表扩展加载了,不代表数据库能连上。必须实测一次查询。
- 在控制器里写一段最小化测试代码,避开 TP8 的 Db 类封装,直连 PDO:
try {
$dsn = 'sqlsrv:server=(local);Database=Demo;CharacterSet=utf8';
$pdo = new PDO($dsn, 'sa', 'sql@2025');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->query('SELECT TOP 1 * FROM sys.tables');
var_dump($stmt->fetch());
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}- 错误信息比
Driver not found更有价值:如果是Login failed for user,说明网络通但认证失败;如果是Named Pipes Provider, error: 40,大概率是 SQL Server TCP/IP 协议未启用或防火墙挡了 1433 - SQL Server Management Studio 能连 ≠ PHP 能连——SSMS 可能走的是 Named Pipes,而 PHP 默认走 TCP/IP,两者协议栈不同
- 如果用的是云 SQL Server(如 Azure SQL),DSN 中必须加
Encrypt=yes;TrustServerCertificate=no;,否则 PDO 会因证书校验失败而中断
最常被忽略的一点:SQL Server 的 TCP/IP 协议启用后,必须手动重启 SQL Server 服务才生效,只重启 Web 服务或 PHP-FPM 没用。这个操作看似简单,却是生产环境里排查耗时最长的环节之一。



















