Symfony 连不上 SQL Server 的根本原因是 PDO 驱动、连接协议与 SQL Server 认证三者未对齐:必须安装并启用 pdo_sqlsrv 扩展,DATABASE_URL 使用 sqlsrv:// 协议且 host 为 127.0.0.1(非 localhost),端口显式指定,密码 URL 编码,并确保 SQL Server 启用混合认证模式、用户具备 CREATE DATABASE 权限,同时防火墙/Docker 网络放行 1433 端口。

symfony 连不上 SQL Server,不是 Doctrine 默认支持的问题,而是驱动、协议、认证三者没对齐。Symfony 本身不关心数据库类型,真正卡住的是底层 PDO 和 Microsoft 官方驱动(pdo_sqlsrv 或 sqlsrv)是否装好、能否加载、是否匹配 SQL Server 实际配置。
pdo_sqlsrv 扩展没装或没启用
Doctrine 在 Symfony 里默认只认 mysql、pgsql、sqlite 协议;连 SQL Server 必须显式用 sqlsrv:// 或 pdo_sqlsrv://,且 PHP 必须加载对应扩展。
- 运行
php -m | grep sqlsrv,没输出说明扩展根本没装 - Linux 上要装微软官方 repo +
php-sqlsrv包(Ubuntu/Debian 是php-sqlsrv,RHEL/CentOS 是php-sqlsrv或php74-sqlsrv等,版本必须匹配 PHP) - Windows 下需手动把
php_pdo_sqlsrv.dll放进ext/目录,并在php.ini里加extension=php_pdo_sqlsrv.dll - 装完必须重启 PHP-FPM 或 Apache,
phpinfo()页面里得看到sqlsrv和pdo_sqlsrv模块
DATABASE_URL 协议头写成 mysql:// 或错用 localhost
Symfony 的 DATABASE_URL 必须用 sqlsrv://(不是 mysql://),且主机不能写 localhost——SQL Server 在 Linux 上默认不监听 localhost 的 Unix socket,而 localhost 会触发 DNS 解析失败或走错协议。
- 正确写法:
sqlsrv://sa:yourpass@127.0.0.1:1433/mydb?charset=utf8 -
127.0.0.1强制走 TCP;localhost在某些环境会被解析成 IPv6 地址或触发命名管道,直接报SQLSTATE[08001] - 端口必须显式写(哪怕用默认 1433),否则驱动可能忽略
- 密码含
@、/、:等字符必须 URL 编码,比如Pass@123→Pass%40123
SQL Server 认证模式和用户权限不匹配
Symfony 命令(如 doctrine:database:create)用的是 DATABASE_URL 里的账号,不是 sa,也不是 Windows 身份验证——它走的是 SQL Server 的混合模式(SQL Auth),且该用户必须有 CREATE DATABASE 权限。
- 检查 SQL Server 是否启用了“SQL Server 和 Windows 身份验证模式”(仅 Windows 身份验证模式下,
sqlsrv驱动无法登录) - 用 SSMS 登录后,执行:
SELECT name, type_desc, is_disabled FROM sys.sql_logins WHERE name = 'your_user';,确认账号存在且is_disabled = 0 - 确保该用户在目标库(或
master)上有dbcreator角色,或显式授权:GRANT CREATE ANY DATABASE TO [your_user]; - 如果用 Docker 启的 SQL Server(如
mcr.microsoft.com/mssql/server:2019-latest),初始sa密码必须 ≥ 8 位且含大小写字母+数字+符号,否则容器启动失败,但日志里只报“accepting connections”不提密码问题
防火墙 / 网络层拦截 1433 端口
本地开发时容易忽略:Linux 主机防火墙(ufw 或 firewalld)、Docker bridge 网络策略、甚至 Windows WSL2 的端口转发,都可能让 127.0.0.1:1433 对 PHP 进程不可达。
- 先在终端跑:
telnet 127.0.0.1 1433,通了再试 PHP;不通就查服务是否真在监听:sudo ss -tulpn | grep :1433 - Docker 场景下,确认
docker run加了-p 1433:1433,且 SQL Server 容器日志里有Server is listening on [::]:1433 - WSL2 用户注意:
localhost在 WSL2 里指向 WSL2 自身,不是 Windows 主机;若 SQL Server 装在 Windows 上,PHP 在 WSL2 里连,得用 Windows 主机真实 IP(查cat /etc/resolv.conf | grep nameserver后的地址),不能用127.0.0.1
最常被跳过的点:以为装了扩展就万事大吉,结果 php -v 和 phpinfo() 用的是不同 php.ini;或者 DATABASE_URL 写对了,但 doctrine.yaml 里还留着 driver: 'pdo_mysql' 这种硬编码覆盖;又或者 SQL Server 容器起来了,但 ACCEPT_EULA=Y 和 MSSQL_SA_PASSWORD 没设导致服务压根没启动——这些细节一漏,错误日志里只报模糊的 Connection refused,实际跟 Doctrine 配置毫无关系。


















