當您使用 Microsoft Drivers for PHP for SQL Server 連線到 SQL Server、Azure SQL Database、Azure SQL 受控執行個體 及 Microsoft Fabric 中的 SQL 資料庫時,診斷並解決常見問題。
關於一般錯誤與警告處理模式,請參見 處理錯誤與警告。 關於駕駛者側的診斷擷取,請參見 日誌活動。
安裝問題
擴充功能未載入
徵兆:
-
phpinfo()沒有列出sqlsrv或pdo_sqlsrv區段。 -
PDOException: could not find driver當使用sqlsrv:DSN 建構PDO時。 -
Fatal error: Uncaught Error: Call to undefined function sqlsrv_connect()。
多個原因與解決方案:
-
php.ini中未啟用擴充功能 。 確認
extension=sqlsrv和extension=pdo_sqlsrv都未被註解。 在 Windows 上,請使用完整檔名(extension=php_sqlsrv_84_ts_x64.dll)。 詳情請參見 載入驅動程式。 -
錯誤的執行緒安全建置。 驅動程式二進位檔必須與您的 PHP 建置的執行緒安全性相符(
ts表示執行緒安全,nts表示非執行緒安全)。 執行php -i | grep "Thread Safety"來檢查。 從 下載頁面下載匹配的二進位檔。 -
Microsoft ODBC 驅動程式遺失。 PHP 驅動程式封裝了 Microsoft ODBC for SQL Server 驅動程式。 在 Linux 和 macOS 上,請先使用套件管理器安裝
msodbcsql18(或msodbcsql17),再載入擴充功能。 在 Windows 上,從下載頁面安裝 ODBC 驅動程式。
確認安裝成功:
php -m | grep -i sqlsrv
你應該會在輸出中看到兩者pdo_sqlsrvsqlsrv。
PECL 安裝在 Linux 或 macOS 上失敗
徵兆:
error: ‘SQL_HANDLE_DBC’ undeclared (first use in this function)
fatal error: 'sql.h' file not found
修正:
在執行 pecl install 之前,請先安裝 ODBC 開發標頭檔:
-
Ubuntu 與 Debian:
sudo apt-get install unixodbc-dev -
Red Hat、Fedora 與 CentOS:
sudo dnf install unixODBC-devel -
阿爾卑斯:
apk add unixodbc-dev -
macOS:
brew install unixodbc
然後再試一次:
sudo pecl install sqlsrv
sudo pecl install pdo_sqlsrv
如果在安裝標頭檔後,pecl 仍然失敗,則建置工具鏈可能不完整。 安裝 phpize、 re2c,以及一個 C++ 編譯器(build-essential 在 Debian 和 Ubuntu,在 gcc-c++ make Red Hat 和 Fedora,在 build-base Alpine 上)。
完整安裝路徑請參見 Linux 與 macOS 安裝教學。
安裝了多個 PHP 版本
徵兆:
phpinfo() 在您的網頁伺服器中顯示的是某個 PHP 版本,但在命令列執行 php -v 時顯示的卻是另一個版本,而且驅動程式似乎只在其中一個版本中載入。
修正:
每個 PHP 版本都有自己的php.iniext目錄。 在缺少驅動程式的環境中,透過 php --ini 找到正確的設定檔,然後在該處加入 extension= 這幾行。 任何 php.ini 變更後,重新啟動網頁伺服器(Apache、Nginx + PHP-FPM 或 IIS)。
連線問題
無法連接伺服器
徵兆:
SQLSTATE[08001]: [Microsoft][ODBC Driver 18 for SQL Server]TCP Provider: A connection attempt failed
SQLSTATE[HYT00]: [Microsoft][ODBC Driver 18 for SQL Server]Login timeout expired
多個原因與解決方案:
伺服器無法連線。 請檢查伺服器名稱和埠是否正確。 從 PHP 主機測試原始的 TCP 連線。
# Linux and macOS nc -vz <server>.database.windows.net 1433 # Windows PowerShell Test-NetConnection -ComputerName <server>.database.windows.net -Port 1433防火牆封鎖了1433號的外撥。 企業防火牆和雲端 NSG 經常封鎖出站埠 1433。 新增例外規則,或允許您所在區域的 Azure SQL Database IP 範圍。
Azure SQL server firewall. 在 Azure 入口網站中,將用戶端的公用 IP 新增至伺服器層級防火牆規則。
命名實例。 對於命名實例,請確認 SQL Server 瀏覽器服務是否在伺服器上執行,且 UDP 1434 是否開啟。 或者,用埠口連接,而不是用實例名稱。
登入失敗
徵兆:
SQLSTATE[28000]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Login failed for user '<user_id>'.
多個原因與解決方案:
- SQL 認證模式已停用。 本地 SQL Server 實例預設僅使用 Windows 認證。 在 SQL Server Management Studio 的 Server 屬性>安全性下啟用混合模式認證,然後重新啟動 SQL Server 服務。
-
Azure SQL credentials format. Azure SQL 在連接不會自動附加使用者名稱的工具時,需要完整限定的使用者名稱(
user@servername)。 - 使用者未映射到資料庫。 確認登入在目標資料庫中有使用者對應,且使用者是否擁有所需權限。
-
Prefer Microsoft Entra ID. 對於 Azure SQL、Azure SQL 受控執行個體 以及 Fabric 中的 SQL 資料庫,請使用 Microsoft Entra 認證(
Authentication=ActiveDirectoryMsi或Authentication=ActiveDirectoryServicePrincipal存取權杖)代替 SQL 登入。 請參見 使用 Microsoft Entra 認證連接。
為連接字串屬性 'Authentication' 指定了無效的值
徵兆:
SQLSTATE[08001]: [Microsoft][ODBC Driver 17 for SQL Server]Invalid value specified for connection string attribute 'Authentication'
原因:
ODBC 驅動程式會回報該錯誤,但真正的問題是 PDO_SQLSRV 繫結到的是 哪個 驅動程式。 如果 DSN 沒有包含 Driver= 關鍵字,且主機同時安裝了 ODBC 17 和 ODBC 18,PDO_SQLSRV 可以綁定到舊版本。 較舊的 ODBC 17.x 組建無法識別較新的 Authentication 值,例如 ActiveDirectoryServicePrincipal 或 ActiveDirectoryDefault;就連 ActiveDirectoryMsi 也需要 ODBC 17.3.1.1 或更新版本。
修正:
將驅動程式固定在 DSN 中:
<?php
$dsn = "sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=$server;Database=$db;" .
"Encrypt=true;Authentication=ActiveDirectoryMsi";
$conn = new PDO($dsn, null, null, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
括號內的形式({ODBC Driver 18 for SQL Server})可跳脫驅動程式名稱中的空格。 錯誤訊息本身總是會標明通報的驅動程式,因此錯誤前綴 [Microsoft][ODBC Driver 17 for SQL Server] 是確認錯誤驅動綁定最快的方式。
DSN 字串中指定了無效關鍵字 'UID'
徵兆:
SQLSTATE[IMSSP]: An invalid keyword 'UID' was specified in the DSN string.
原因:
PDO_SQLSRV 只允許使用許可清單中的 DSN 關鍵字,且不接受在 DSN 中使用 UID 或 PWD。 PDO 保留第二和第三個建構子參數給這些,PDO_SQLSRV 在內部將它們轉換成 ODBC UID/PWD 。
修正:
將使用者名稱(以及用於 SQL 認證的密碼)移到 PDO 建構子中:
<?php
// SQL authentication.
$dsn = "sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=$server;Database=$db;Encrypt=true";
$conn = new PDO($dsn, $user, $password);
// User-assigned managed identity. Pass the identity's client ID as $username.
$dsn = "sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=$server;Database=$db;" .
"Encrypt=true;Authentication=ActiveDirectoryMsi";
$conn = new PDO($dsn, $clientId, null);
相較之下,SQLSRV 程序驅動程式接受 UID 和 PWD 在連線選項陣列中傳遞給 sqlsrv_connect()。
PDO_SQLSRV 默默忽略選項陣列中的 AccessToken
症狀:
你有一個 Microsoft Entra 存取權杖(例如,來自 az account get-access-token --resource https://database.windows.net/、ManagedIdentityCredential 或 ClientSecretCredential),並在第四個建構函式引數中將它作為 ['AccessToken' => $token] 傳遞給 PDO_SQLSRV。 連線嘗試失敗時會出現令人困惑的錯誤,例如 Windows logins are not supported in this version of SQL Server 或 Login failed for user '',彷彿沒有提供憑證。
原因:
PDO 的第四個建構子參數保留給驅動程式特定的屬性常數(如 PDO::ATTR_ERRMODE整數鍵)。 PDO 會悄悄捨棄像 AccessToken 這類以字串為鍵的項目,因此 PDO_SQLSRV 根本看不到該標記。 連線隨後退回到 Windows 整合驗證,伺服器會拒絕該認證。
修正:
將 AccessToken 移入 DSN 字串中。 將選項陣列保留給 PDO::ATTR_* 常數。
<?php
$server = '<server>.database.windows.net';
$token = getenv('SQL_ACCESS_TOKEN'); // raw JWT, no "Bearer " prefix
$dsn = "sqlsrv:Server=$server;Database=<database>;Encrypt=true;AccessToken=$token";
$conn = new PDO($dsn, null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
如需更多Microsoft Entra認證範例,包括PDO_SQLSRV的 DSN 表單,請參見使用 Microsoft Entra 認證連接。
對於 SQLSRV 程序式, AccessToken 屬於傳給 sqlsrv_connect()的 connection-info 陣列,這會將原始的 JWT 包裝成 SQL_COPT_SS_ACCESS_TOKEN :
<?php
$server = '<server>.database.windows.net';
$token = getenv('SQL_ACCESS_TOKEN'); // raw JWT, no "Bearer " prefix
$connectionInfo = [
'Database' => '<database>',
'AccessToken' => $token,
'Encrypt' => true,
'TrustServerCertificate' => false,
'Driver' => '{ODBC Driver 18 for SQL Server}',
];
$conn = sqlsrv_connect($server, $connectionInfo);
if ($conn === false) {
print_r(sqlsrv_errors());
exit(1);
}
TLS 憑證錯誤
徵兆:
SQLSTATE[08001]: SSL Provider: The certificate chain was issued by an authority that is not trusted
SQLSTATE[08001]: SSL Provider: The target principal name is incorrect
解決方案:
偏好可信憑證。 僅將 TrustServerCertificate=true 用於針對你所控制的伺服器進行本機開發。
如果是針對自我簽署憑證進行開發:
<?php
$server = 'localhost';
$database = '<database>';
$user = '<user_id>';
$password = '<password>';
$dsn = "sqlsrv:Server=$server;Database=$database;Encrypt=true;TrustServerCertificate=true";
$conn = new PDO($dsn, $user, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
注意事項
TrustServerCertificate=true 停用伺服器憑證驗證。 絕不要將這種設定帶入製作、舞台或共用環境。
對於與憑證通用名稱不符的生產主機名稱(例如透過監聽器連線時),請指定實際的憑證主體:
<?php
$dsn = "sqlsrv:Server=<listener>;Database=<database>;Encrypt=true;HostNameInCertificate=*.database.windows.net;Authentication=ActiveDirectoryMsi";
$conn = new PDO($dsn, null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
連線超時
徵兆:
SQLSTATE[HYT00]: Login timeout expired
多個原因與解決方案:
-
LoginTimeout沒有設定或設定太低,無法進行冷備援轉移。 連接 Azure SQL 時,在 DSN 中設定明確LoginTimeout的(秒數計)值。 容錯移轉群組的容錯移轉作業和冷啟動的資料庫所需時間,可能會超過較短的用戶端逾時設定所允許的時間。 請參閱 連接選項選項 參考。 -
閒置重新連線預算被截斷。 如果你設定
ConnectRetryCount和ConnectRetryInterval,請確保LoginTimeout >= ConnectRetryCount * ConnectRetryInterval。 否則登入逾時會提前結束重連迴圈。 參見閒置連線韌性。
<?php
$dsn = "sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=<server>.database.windows.net;Database=<database>;" .
"Encrypt=true;LoginTimeout=90;ConnectRetryCount=5;ConnectRetryInterval=15;" .
"Authentication=ActiveDirectoryMsi";
$conn = new PDO($dsn, null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
查詢執行問題
PDO的無聲故障
症狀:
A PDO::exec() 或 PDOStatement::execute() call 回傳 false ,但不會拋出例外。
修正:
在 PHP 8.0 及更新版本中,預設的 PDO 錯誤模式為 PDO::ERRMODE_EXCEPTION。 若呼叫回傳 false 且未拋出,應用程式會將模式切換為 PDO::ERRMODE_SILENT 或 PDO::ERRMODE_WARNING。 將它設回例外模式,讓失敗時拋出例外:
<?php
$conn = new PDO($dsn, $user, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
如果無法全域更改模式,請每次通話後檢查 $conn->errorInfo() (或 $stmt->errorInfo())。 陣列包含 [SQLSTATE, driver code, driver message]。
無效的物件名稱。
徵兆:
SQLSTATE[42S02]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Invalid object name 'Products'.
多個原因與解決方案:
資料庫上下文錯誤。 請用一個快速查詢來驗證:
<?php $stmt = $conn->query("SELECT DB_NAME()"); echo $stmt->fetchColumn();缺少結構限定詞。 使用完全限定的名稱以避免依賴呼叫者的預設結構:
SELECT * FROM dbo.Products;區分大小寫。 以大小寫區分的排序建立的資料庫,會視為
productsProducts不同的物件。 與表格定義中的完全相同情況。
參數數量錯誤
徵兆:
SQLSTATE[HY093]: Invalid parameter number
SQLSTATE[07002]: COUNT field incorrect or syntax error
修正:
對於PDO_SQLSRV,佔位符的數量 ? 必須與你傳遞到 execute()的值數相匹配,且每個 ? 值綁定一個純量(而非陣列)。 對於命名參數,SQL 中的每個 :name 參數都必須出現在陣列中,反之亦然。
<?php
$stmt = $conn->prepare(
"SELECT * FROM dbo.Products WHERE CategoryID = ? AND ListPrice > ?"
);
$stmt->execute([1, 50.0]);
foreach ($stmt as $row) {
// ...
}
對於 SQLSRV,將參數陣列傳給 sqlsrv_query() 或 sqlsrv_prepare():
<?php
$stmt = sqlsrv_query(
$conn,
"SELECT * FROM dbo.Products WHERE CategoryID = ? AND ListPrice > ?",
[1, 50.0]
);
if ($stmt === false) {
die(print_r(sqlsrv_errors(), true));
}
欲了解參數綁定的更廣泛介紹,請參見 執行參數化查詢。
PDO 模擬預備語句會掩蓋錯誤
徵兆:
一個敘述在一個連線上成功執行,但在另一個使用相同查詢文字的連線上會拋出語法錯誤。
原因:
PDO_SQLSRV 支援模擬語句與原生預備語句。 模擬 prepared statements(PDO::ATTR_EMULATE_PREPARES = true)會在用戶端代入參數。 Native prepare (false) 會分別將查詢與參數傳送給伺服器。 對於 TOP (?)、表值參數以及型別強制轉換中的某些邊緣情況,行為會有所不同。
修正:
在生產環境中優先使用原生準備機制。 設定 PDO::ATTR_EMULATE_PREPARES => false 在連線時間,以確保行為在不同環境中保持一致:
<?php
$conn = new PDO($dsn, null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
]);
如需瞭解何時使用各種模式的詳細資訊,請參閱 PDO::prepare。
資料型別問題
Unicode 字元顯示為 ? 或亂碼
徵兆:
PHP 寫入的列包含問號或替換字元,而非原本的非 ASCII 字元。 讀取時會出現亂碼。
多個原因與解決方案:
欄位類型是 VARCHAR,不是 NVARCHAR。 varchar 欄位使用的是代碼頁,而非 Unicode。 對於國際化文字,請使用 nvarchar。
PDO_SQLSRV 缺少 UTF-8 編碼提示。 當你的 SQL Server 欄位是 nvarchar,PHP 資料是 UTF-8 時,告訴驅動程式在 UTF-8(用戶端)和 UTF-16(伺服器)之間轉換:
<?php $conn = new PDO( "sqlsrv:Server=<server>;Database=<database>;Encrypt=true", $user, $password, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8, ] );SQLSRV 驅動程式:明確請求 UTF-8。
SQLSRV_ENC_CHAR是預設的 8 位元系統代碼頁,而非 UTF-8。 對於帶有 SQLSRV 的 UTF-8,在連線上設值"CharacterSet" => "UTF-8",並在擷取或綁定時將 的文字'UTF-8'傳遞給SQLSRV_PHPTYPE_STRING。 請參見 「傳送與取回 UTF-8 資料」。
日期時間轉換錯誤
徵兆:
SQLSTATE[22007]: Invalid character value for cast specification
修正:
在PDO_SQLSRV,不要綁定原始 DateTime 物件。 PDO 會先將綁定值轉成字串再進行綁定,而 PHP 的 DateTime 沒有 __toString() 方法,因此 execute([new DateTime(...)]) 會引發 Object of class DateTime could not be converted to string。 先格式化該值,或傳遞 ISO 8601 字串(YYYY-MM-DD HH:MM:SS[.fff]),而非區域格式字串。
<?php
$stmt = $conn->prepare("INSERT INTO dbo.Events (EventDate) VALUES (?)");
$stmt->execute([(new DateTime("2026-03-15 10:00:00"))->format("Y-m-d H:i:s.u")]);
若要將 datetime 欄位作為 DateTime 物件擷取,而非 PDO_SQLSRV 上的字串,請設定 statement 屬性:
<?php
$stmt = $conn->prepare("SELECT EventDate FROM dbo.Events");
$stmt->setAttribute(PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE, true);
$stmt->execute();
詳情請參見 「擷取日期時間物件(PDO_SQLSRV)」。
十進位格式問題
徵兆:
-1 到 1 之間的值缺少前置零,或是 金錢 和 小錢 的值顯示出意想不到的小數位數。
修正:
PDO_SQLSRV 一律會將 decimal 和 numeric 值以其精確的有效位數與小數位數擷取為字串。 設定 PDO::SQLSRV_ATTR_FORMAT_DECIMALS 在介於 -1 到 1 之間的值中加上一個前置零:
<?php
$conn->setAttribute(PDO::SQLSRV_ATTR_FORMAT_DECIMALS, true);
PDO::SQLSRV_ATTR_DECIMAL_PLACES 僅適用於 貨幣 和 小額貨幣 的價值。 它會將其顯示尺度設為 0 到 4,且可能會將顯示值四捨五入。 它不影響 小數 或 數字 。
詳情請參見格式化十進位與貨幣(PDO_SQLSRV)或格式化十進位與貨幣(SQLSRV)。
交易問題
資料變更不會保留
徵兆:
你在 PHP 中插入或更新的資料列,在另一個工作階段中查詢時不會顯示。
原因:
PDO::beginTransaction() 開啟一個明確的交易,該交易需要明確的 commit()。 如果 PHP 指令碼結束時尚未呼叫 commit(),PDO 會在連線清理期間將交易復原。
修正:
請務必將 beginTransaction() 與 commit() 配對使用,並在發生錯誤時使用 try/catch 進行回復:
<?php
try {
$conn->beginTransaction();
$conn->exec("INSERT INTO dbo.Orders (CustomerID, Total) VALUES (1, 100)");
$conn->exec("UPDATE dbo.Inventory SET Stock = Stock - 1 WHERE ProductID = 5");
$conn->commit();
} catch (PDOException $e) {
$conn->rollBack();
throw $e;
}
對於 SQLSRV,請使用 sqlsrv_begin_transaction、 sqlsrv_commit、 sqlsrv_rollback和 。
死結錯誤
徵兆:
SQLSTATE[40001]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Transaction (Process ID 62) was deadlocked
修正:
用重試邏輯處理暫時性死鎖錯誤。 將整個交易(而不只是失敗的陳述式)封裝起來,讓先前的陳述式能在全新的交易中重新執行。 關於生產導向的重試模式,請參閱 PHP 驅動程式登陸頁面上的範例。
反覆出現的死結表示設計有問題。 擷取死結圖,並分析涉及哪些語句與鎖類型。 常見的修正包括重新排序操作,使競爭交易能以相同順序取得鎖、縮小交易範圍,以及增加索引以縮短鎖的持續時間。 完整攻略請參考 Deadlocks 指南。
連線韌性問題
重新連結不會發生
徵兆:
閒置的連線在 Azure SQL Database 故障轉移後仍然中斷,即使您已設定 ConnectRetryCount 和 ConnectRetryInterval。
多個原因與解決方案:
-
伺服器端游標是主動的。 閒置連線彈性只會重新連接 閒置 連線。 開啟的伺服器端游標或待處理的交易會保持連線的活躍狀態。 透過在故障轉移視窗前使用
sqlsrv_free_stmt()或$stmt = null;(PDO)釋放伺服器端游標,或切換到客戶端緩衝游標即可。 參見閒置連線韌性。 -
無法恢復的會話狀態。 有些會話狀態無法重新建立,包括暫存資料表、全域與本地游標、交易上下文、應用程式鎖定、
EXECUTE AS/REVERTOLE 自動化句柄、準備好的 XML 句柄以及追蹤旗標。 這些會話狀態中的任何一個都會阻止自動重新連線。 -
LoginTimeout太小了。 若ConnectRetryCount * ConnectRetryInterval > LoginTimeout,駕駛員在LoginTimeout達到時停止重試。 提高LoginTimeout以涵蓋整個重試預算。
效能問題
關於慢查詢、冷啟動、大型結果集及大量插入的診斷與修復,請參見 效能調整。
啟用驅動程式診斷
當應用程式層 error_log() 級呼叫無法提供足夠資訊時,請開啟駕駛端記錄功能。 它會報告司機打的每通 ODBC 電話。
PDO_SQLSRV
在 php.ini 中設定 pdo_sqlsrv.log_severity,然後重新啟動網頁伺服器。 此設定僅在初始化時可讀取:
[pdo_sqlsrv]
pdo_sqlsrv.log_severity = 1
數值分別為 0 (關閉,預設值)、 -1 (錯誤、警告與通知)、 1 (錯誤)、 2 (警告)及 4 (通知)。
SQLSRV
在執行時啟用日誌,並使用:sqlsrv_configure()
<?php
sqlsrv_configure("LogSubsystems", SQLSRV_LOG_SYSTEM_CONN | SQLSRV_LOG_SYSTEM_STMT);
sqlsrv_configure("LogSeverity", SQLSRV_LOG_SEVERITY_ERROR | SQLSRV_LOG_SEVERITY_WARNING);
日誌項目會寫入在 php.ini 中由 error_log 設定的檔案。 完整的子系統與嚴重度列表,請參見 日誌活動。
容器與 CI 問題
Linux 缺少的系統函式庫
徵兆:
error while loading shared libraries: libodbc.so.2: cannot open shared object file
error while loading shared libraries: libssl.so.1.1: cannot open shared object file
修正:
安裝 PHP 驅動程式前,先安裝執行時相依系統:
| 分布 | 安裝指令 |
|---|---|
| Ubuntu 和 Debian | sudo apt-get install unixodbc libgssapi-krb5-2 |
| Red Hat 與 Fedora | sudo dnf install unixODBC krb5-libs |
| Alpine | apk add unixodbc gcompat |
然後從 Microsoft 套件倉庫安裝msodbcsql18。 關於發行版專屬的套件庫與版本,請參閱 ODBC 驅動程式安裝指南。
Docker 映像建置成功,但連線在執行時會失敗
徵兆:
映像檔已建置完成,PHP 也能啟動,但 PDO::__construct() 會拋出找不到 ODBC 驅動程式的錯誤。
修正:
確認 ODBC 驅動程式已 安裝在執行時映像中,而不只是建置階段。 在部署到正式環境的同一個階段中安裝 msodbcsql18 和 unixodbc-dev。 在多階段建置中,請在最終階段安裝它們。 基於 Debian 的單階段安裝如下:
# Pin to a specific PHP minor version in production, for example php:8.4.11-cli.
FROM php:8.4-cli
RUN apt-get update && apt-get install -y --no-install-recommends \
curl gnupg2 apt-transport-https ca-certificates \
&& curl -sSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /usr/share/keyrings/microsoft.gpg \
&& echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft.gpg] https://packages.microsoft.com/debian/12/prod bookworm main" > /etc/apt/sources.list.d/mssql-release.list \
&& apt-get update \
&& ACCEPT_EULA=Y apt-get install -y --no-install-recommends msodbcsql18 unixodbc-dev \
# $PHPIZE_DEPS ships in the official php image and includes gcc, make, autoconf, and re2c.
&& apt-get install -y --no-install-recommends $PHPIZE_DEPS \
&& pecl install sqlsrv pdo_sqlsrv \
&& docker-php-ext-enable sqlsrv pdo_sqlsrv \
&& apt-get purge -y --auto-remove $PHPIZE_DEPS \
&& rm -rf /var/lib/apt/lists/*