排除 Microsoft PHP 驅動程式(針對 SQL Server 的程式)

下載 PHP 驅動程式

使用 Microsoft Drivers for PHP for SQL Server 連接 SQL Server、Azure SQL Database、Azure SQL 受控執行個體 及 SQL 資料庫時,診斷並解決常見問題Microsoft Fabric。

關於一般錯誤與警告處理模式,請參見 處理錯誤與警告。 關於駕駛者側的診斷擷取,請參見 日誌活動

安裝問題

擴充功能未載入

徵兆:

  • phpinfo() 沒有列出 sqlsrv 某個或部分 pdo_sqlsrv
  • PDOException: could not find driver當用 sqlsrv: DSN 構造 a PDO 時。
  • Fatal error: Uncaught Error: Call to undefined function sqlsrv_connect()

多個原因與解決方案

  • php.ini中未啟用擴充功能 。 確認兩者extension=sqlsrvextension=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 與 Debiansudo apt-get install unixodbc-dev
  • Red Hat、Fedora 與 CentOSsudo dnf install unixODBC-devel
  • 阿爾卑斯:apk add unixodbc-dev
  • macOS:brew install unixodbc

然後再試一次:

sudo pecl install sqlsrv
sudo pecl install pdo_sqlsrv

如果 pecl 安裝完接頭後仍然失敗,可能是建置工具鏈不完整。 安裝 phpizere2c,以及一個 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=ActiveDirectoryMsiAuthentication=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 的值,例如 或 ActiveDirectoryServicePrincipalActiveDirectoryDefault,甚至 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 關鍵字的允許清單,且不接受 UIDPWD 包含在 DSN 裡。 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 程序驅動程式接受 UIDPWD 在連線選項陣列中傳遞給 sqlsrv_connect()

PDO_SQLSRV 默默忽略選項陣列中的 AccessToken

症狀

你有一個Microsoft Entra存取權杖(例如來自 az account get-access-token --resource https://database.windows.net/、 、 或 ClientSecretCredential),然後像第四個建構子參數一樣,將它傳給PDO_SQLSRV ['AccessToken' => $token]ManagedIdentityCredential。 連線嘗試失敗時會出現令人困惑的錯誤,例如 Windows logins are not supported in this version of SQL ServerLogin 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的(秒數計)值。 故障轉移群組故障轉移與冷啟動資料庫可能花費的時間超過短期客戶端逾時所能提供的時間。 請參閱 連接選項選項 參考。
  • 閒置重連預算被削減。 如果你設定 ConnectRetryCountConnectRetryInterval,請確保 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_SILENTPDO::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 支援模擬語句與原生預備語句。 模擬準備(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::p repare

資料型別問題

Unicode 字元呈現為或 ? 模糊

徵兆:

PHP 寫入的列包含問號或替換字元,而非原本的非 ASCII 字元。 閱讀回傳模糊文字。

多個原因與解決方案

  • 欄位類型是 VARCHAR,不是 NVARCHAR。 varchar 欄位使用的是代碼頁,而非 Unicode。 國際化文字使用 nvarchar

  • 缺少 UTF-8 編碼提示,PDO_SQLSRV。 當你的 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-8SQLSRV_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總是以精確的精確度和刻度取得十 進位數字 值作為字串。 設定 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(),錯誤時回try/catch滾:commit()

<?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_transactionsqlsrv_commitsqlsrv_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

安裝 pdo_sqlsrv.log_severityphp.ini 重新啟動網頁伺服器。 此設定僅在初始化時可讀取:

[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
紅帽與軟呢帽 sudo dnf install unixODBC krb5-libs
Alpine apk add unixodbc gcompat

然後從 Microsoft 套件倉庫安裝msodbcsql18。 關於發行版專屬的套件庫與版本,請參閱 ODBC 驅動程式安裝指南

Docker 映像建置成功,但連線在執行時會失敗

徵兆:

映像檔編譯並啟動 PHP,但 PDO::__construct() 會跳出 ODBC 驅動程式找不到錯誤。

修正:

確認 ODBC 驅動程式已 安裝在執行時映像中,而不只是建置階段。 安裝 msodbcsql18unixodbc-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/*