Microsoft PHP for SQL Server 驅動程式是 PHP 擴充功能,允許你從 PHP 腳本讀寫 Microsoft SQL 資料庫引擎 中的資料。 該套件附帶兩個驅動程式,這些驅動程式都包裹相同的 Microsoft ODBC 驅動程式 for SQL Server,且共享相同的連線選項,因此你可以選擇適合你程式碼庫的 API:
-
SQLSRV 會暴露一個針對 SQL Server 功能量身打造的程序式 API(
sqlsrv_*函式)。 - PDO_SQLSRV實作了 PHP 資料物件(PDO)介面,因此已使用 PDO 用於其他資料庫的程式碼也能以最小的修改來鎖定SQL Server。
兩個驅動程式都連接 Azure SQL Database、Microsoft Fabric 中的 SQL 資料庫、Azure SQL 受控執行個體,以及所有支援的 SQL Server 版本(包括 Express 版本)。 它們使用 PHP 串流來移動大型二進位和字元值,且不會完全載入記憶體。
選擇你的起點
- 要建立 PHP 開發環境並執行第一個查詢,先從 步驟 1:設定開發環境開始,接著步驟 2:建立 SQL 資料庫 ,步驟 3:使用 PHP 連接 SQL 的概念驗證。
- 要在 Linux 或 macOS 上安裝驅動程式,請先從 Linux 和 macOS 的安裝教學開始,並下載 Microsoft PHP for SQL Server 的驅動程式。
- 若要使用無密碼驗證連線到 Azure SQL,請先參閱 使用 Microsoft Entra 驗證進行連線 和 連線選項。
- 要讓現有應用程式對短暫故障具備韌性,請前往 閒置連線韌性 ,步驟 4:用 PHP 韌性連接 SQL。
- 要在 SQLSRV 和 PDO_SQLSRV 之間做決定,請參考 PHP Microsoft 驅動程式概覽,SQL Server 和執行函式比較。
- 要診斷安裝、連線或查詢問題,請前往 「故障排除」、「 處理錯誤與警告」以及 「日誌活動」。
- 要讓現有應用程式更快,請前往 效能調整。
Azure SQL 的生產環境基準
使用此片段作為與 PDO_SQLSRV 驅動程式建立生產導向Azure SQL連線的起點。 它會從環境變數(例如 Azure App 服務 應用程式設定)讀取伺服器和資料庫,使用管理身份驗證,啟用傳輸層安全(TLS)並驗證伺服器憑證,設定登入逾時以涵蓋冷啟動故障轉移,並設定 ConnectRetryCountConnectRetryInterval SQL Server 閒置連線韌性。 應用程式層 connectWithRetry 級與 queryWithRetry 輔助工具會以有界指數退讓包覆初始連線與每個語句,並將暫態連線錯誤(需要重新連線)與暫態查詢錯誤(重複使用同一連線)區分開來。
需要 PHP 8.0 及更新版本、PDO_SQLSRV 擴充功能,以及 SQL Server 17.3.1.1 及更新版本的 Microsoft ODBC 驅動程式。Authentication=ActiveDirectoryMsi 完整支援Authentication的數值清單,請參見使用 Microsoft Entra 認證連接。
<?php
declare(strict_types=1);
// Transient errors that require a fresh connection to recover. SQLSTATE values
// starting with '08' cover ODBC connection-established and connection-broken
// states (for example, 08001, 08S01).
const CONNECT_RETRY_SQLSTATE_PREFIX = '08';
// SQL Server error codes that are transient regardless of when they surface:
// 1205 (deadlock victim), 1222 (lock request timeout), and the Azure SQL
// throttling, mid-query failover, and "database not currently available"
// codes that arrive with SQLSTATE HY000.
const TRANSIENT_SERVER_ERROR_CODES = [1205, 1222, 40501, 40613, 40197, 10928, 10929, 49918];
/**
* Open a connection, retrying transient failures with exponential backoff.
*/
function connectWithRetry(string $dsn, array $options, int $maxAttempts = 3): PDO
{
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
try {
$pdo = new PDO($dsn, null, null, $options);
error_log(sprintf('connected on attempt %d/%d', $attempt, $maxAttempts));
return $pdo;
} catch (PDOException $e) {
$sqlstate = (string) $e->getCode();
$driverCode = isset($e->errorInfo[1]) ? (int) $e->errorInfo[1] : 0;
$isTransient = str_starts_with($sqlstate, CONNECT_RETRY_SQLSTATE_PREFIX)
|| in_array($driverCode, TRANSIENT_SERVER_ERROR_CODES, true);
if (!$isTransient || $attempt === $maxAttempts) {
error_log(sprintf('connect failed on attempt %d/%d: %s', $attempt, $maxAttempts, $e->getMessage()));
throw $e;
}
$delay = 2 ** ($attempt - 1); // 1, 2, 4 seconds
error_log(sprintf('connect attempt %d hit transient %s/%d; retrying in %d seconds', $attempt, $sqlstate, $driverCode, $delay));
sleep($delay);
}
}
throw new RuntimeException('connectWithRetry exhausted retries');
}
/**
* Run a parameterized query, retrying transient statement failures on the same
* connection. Deadlocks (1205) roll back the transaction before the driver sees
* the error, so rerunning a single statement is safe. If the statement was part
* of a multistatement transaction, wrap the whole transaction in your own retry
* loop so earlier statements replay too.
*/
function queryWithRetry(PDO $pdo, string $sql, array $params = [], int $maxAttempts = 3): PDOStatement
{
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
try {
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return $stmt;
} catch (PDOException $e) {
$driverCode = isset($e->errorInfo[1]) ? (int) $e->errorInfo[1] : 0;
$isTransient = in_array($driverCode, TRANSIENT_SERVER_ERROR_CODES, true);
if (!$isTransient || $attempt === $maxAttempts) {
error_log(sprintf('query failed on attempt %d/%d: %s', $attempt, $maxAttempts, $e->getMessage()));
throw $e;
}
$delay = 2 ** ($attempt - 1);
error_log(sprintf('query attempt %d hit transient code %d; retrying in %d seconds', $attempt, $driverCode, $delay));
sleep($delay);
}
}
throw new RuntimeException('queryWithRetry exhausted retries');
}
// Load endpoint details from application configuration. In Azure App Service,
// these can come from app settings or Key Vault-backed settings.
$server = getenv('SQL_SERVER') ?: null;
$database = getenv('SQL_DATABASE') ?: null;
if ($server === null || $database === null) {
throw new RuntimeException('Set SQL_SERVER and SQL_DATABASE in your application configuration.');
}
$dsn = sprintf(
'sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=%s;Database=%s;'
. 'Encrypt=true;TrustServerCertificate=false;'
. 'LoginTimeout=90;Authentication=ActiveDirectoryMsi;'
. 'ConnectRetryCount=5;ConnectRetryInterval=15;'
. 'MultiSubnetFailover=true;',
$server,
$database
);
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::SQLSRV_ATTR_QUERY_TIMEOUT => 30,
];
$pdo = connectWithRetry($dsn, $options);
$stmt = queryWithRetry($pdo, 'SELECT TOP (?) name FROM sys.databases ORDER BY name', [5]);
foreach ($stmt as $row) {
echo $row['name'], PHP_EOL;
}
此程式碼片段已針對 Azure SQL Database 故障轉移群組和 Azure SQL 受控執行個體 進行最佳化。
Driver={ODBC Driver 18 for SQL Server}會將 ODBC 18 驅動程式版本固定下來。 如果主機同時安裝了 ODBC 17,PDO_SQLSRV 可以綁定到 ODBC 17。 較舊的 17.x 組建版本會拒絕較新的Authentication值;例如,Authentication=ActiveDirectoryMsi需要 ODBC 17.3.1.1 或更新版本。 請參閱 連接字串 屬性「Authentication」所指定的無效值。ConnectRetryCount和ConnectRetryInterval是 ODBC 連線字串關鍵字,可啟用 SQL Server 的閒置連線恢復能力:驅動程式會以透明方式重新連線中斷的閒置連線。 這與應用程式層queryWithRetry級不同,後者會重試因僵局或查詢逾時等暫態錯誤而失敗的 語句 。 兩者互補,所以兩者都保留。 請確保LoginTimeout至少為ConnectRetryCount * ConnectRetryInterval,這樣閒置重新連線路徑才能獲得完整的時間預算;範例使用 90 秒,以涵蓋 5 × 15 秒的重試時間,並保留冷容錯移轉時初次登入所需的餘裕。以驅動程式端診斷來補強應用程式層級的
error_log()呼叫。 對於 PDO_SQLSRV,設定pdo_sqlsrv.log_severity在php.ini(僅可於初始化時設定);對於 SQLSRV,則在執行時呼叫sqlsrv_configure("LogSubsystems", ...)。 欲了解更多資訊,請參閱 日誌活動。; php.ini - enable PDO_SQLSRV driver diagnostics alongside the application-level ; error_log() calls in the sample. Use 1 (errors) in production; -1 (all) is ; useful during triage but very chatty. [pdo_sqlsrv] pdo_sqlsrv.log_severity = 1對於 使用者指派 的受控識別,請將該識別的 ID 作為 PDO 的
$username引數傳遞(new PDO($dsn, $identityId, null, $options))。 在 Azure App 服務 或 Azure Container Instance 上使用該身分的 client ID;否則,使用其 object ID。 PHP 驅動程式會繼承底層 Microsoft ODBC Driver for SQL Server 的此行為;如需詳細資訊,請參閱 使用 Microsoft Entra ID 搭配 ODBC Driver。 PDO_SQLSRV DSN 本身會被UID拒絕,所以要用建構槽。 假扮null使用者(如範例所示)選擇系統指派的 Azure 主機管理身份。 對於 SQLSRV(程序式),請在連線選項陣列中傳遞UID。當您連線到容錯移轉群組接聽程式、可用性群組接聽程式或容錯移轉叢集執行個體端點時,請設定
MultiSubnetFailover=true。 設定此值可提升單子網及多子網可用性群組監聽者的連線效能。 欲了解更多資訊,請參閱 高可用性支援與災難復原。若要讀取擴展或可讀的次級資料,則可加入
ApplicationIntent=ReadOnly資料來源名稱(DSN)。對於主權雲端,若憑證主體別名 (SAN) 未包含您要連線到的主機,請將
HostNameInCertificate加入 DSN(例如,Azure Government 為*.database.usgovcloudapi.net)。該驅動程式依賴底層的 Microsoft ODBC 驅動程式 for SQL Server 來取得令牌。 受控識別、服務主體和存取權杖流程皆透過 ODBC 進行。 如需詳細資訊,請參閱搭配使用 Microsoft Entra ID 與 ODBC 驅動程式。
為了提升安全性與跨環境的可攜性,請將連線資訊排除在程式碼之外。 將連線資訊儲存在應用程式的設定系統中,並使用 Azure Key Vault 來管理敏感值及集中管理的連線設定。
等效的 SQLSRV 連線會使用
sqlsrv_connect($server, ['Database' => $database, 'Encrypt' => true, 'Authentication' => 'ActiveDirectoryMsi', /* ... */])並回傳一個資源。 重試模式相同:捕捉來自sqlsrv_connect的false傳回值,檢查sqlsrv_errors()中的 SQLSTATE,並在重試前先延後一段時間。 如需逐步範例,請參閱 步驟 4:使用 PHP 以具復原能力的方式連線至 SQL。重試輔助程式會讀取由
isset()保護的$e->errorInfo[1]。PDOException::$errorInfo宣告為?array,且預設為null,因此防禦性檢查會回退使用0作為驅動程式代碼,並由 SQLSTATE08前綴決定是否重試。
關於此配置各部分的更多資訊,請參見:
如需 Azure SQL 暫態錯誤清單,請參閱 「Troubleshoot transient connection errors」。
重點功能
- 兩個 API 與一個驅動程式套件:程序式 SQLSRV 用於SQL Server優先程式碼,或 PDO_SQLSRV 用於可攜式 PDO 程式碼。
- 廣泛支援平台:可在 Windows、Linux 及 macOS 上運行,並支援 PHP 版本。
-
加密連線:透過
Encrypt=true的 TLS 加密連線,伺服器憑證驗證由TrustServerCertificate控制。 - Microsoft Entra ID 認證:無密碼連線,包含受管理身份、服務主體及存取權杖,皆透過底層的 Microsoft ODBC 驅動程式 for SQL Server 進行。
- 始終加密:用戶端加密用於敏感欄位,並可選地設置安全隔區用於原地操作。
-
連線韌性:內建使用
ConnectRetryCount和ConnectRetryInterval的閒置連線重試機制。 - PHP 串流:將大型二進位與字元值讀寫為串流,而非載入記憶體。
-
豐富的 SQL Server 資料型別支援:datetimeoffset、table-valued parameters、nvarchar 以及帶有
PDO::SQLSRV_ENCODING_UTF8的 Unicode。
開始
| 文章 | Description |
|---|---|
| 系統需求 | 支援 PHP、作業系統及 SQL Server 版本。 |
| 支援矩陣 | PHP 驅動程式版本的詳細相容性矩陣。 |
| 下載 Microsoft PHP for SQL Server 驅動程式 | 下載連結並發布相關資料。 |
| Linux 與 macOS 安裝教學 | 在 Linux 和 macOS 上安裝驅動程式及其 ODBC 前置條件。 |
| 載入驅動程式 | 在 php.ini 中啟用擴充功能。 |
| 開始使用 PHP SQL 驅動程式 | 端對端逐步解說,將四個入門步驟串接起來。 |
| PHP SQL 驅動程式概述 | 套件裡有什麼?什麼時候該選擇 SQLSRV 或 PDO_SQLSRV。 |
設定和連線
| 文章 | Description |
|---|---|
| 連接伺服器 | 從 PHP 開啟一個連接到 SQL Server 實例的連線。 |
| 連線選項 | 完整參考資料,包含連線關鍵字、預設值及其設定方法。 |
| 連線到 Microsoft Azure SQL Database | 將 PHP 應用程式連接到 Azure SQL Database。 |
| 連接指定的埠口 | 鎖定非預設的 TCP 埠。 |
| 連接共用 | 在 PHP 請求間重複使用 ODBC 連線。 |
| 停用多個主動結果集(MARS) | 關閉 MARS 以達成相容性。 |
| LocalDB 的支援 | 連接到 SQL Server 的 LocalDB 實例。 |
| 高可用性支援與災難復原 | 可用性群組監聽器與多子網故障轉移。 |
| 閒置連線韌性 | 空閒連線斷裂時自動重新連接。 |
Authenticate
| 文章 | Description |
|---|---|
| 使用 Microsoft Entra 驗證進行連線 | 管理身份、服務主體、存取權杖和密碼流程。 |
| 使用 SQL Server 認證連接 | 使用包含使用者名稱和密碼的 SQL 登入。 |
| 使用 Windows 驗證連線 | 在網域加入的主機上使用 Windows 整合認證。 |
Secure
| 文章 | Description |
|---|---|
| 安全性考量 | PHP 應用的威脅模型與防禦深度指引。 |
| 一直用 PHP 驅動程式加密 | 為敏感欄位設定客戶端加密。 |
| Always Encrypted 具有安全記憶體保護區 | 啟用加密欄位的豐富操作,並具備安全區塊。 |
資料擷取與更新
| 文章 | Description |
|---|---|
| 程式指南 | 兩種驅動程式的端對端程式設計指南。 |
| 執行函數比較 | 選擇適合你工作負載的執行函式。 |
| 直接執行與預備語句執行(PDO_SQLSRV) | 何時使用直接執行,何時使用預先陳述。 |
| 資料擷取 | 取得列、欄和串流值。 |
| 更新資料 | 插入、更新和刪除資料列。 |
| 執行參數化查詢 | 綁定參數以防範 SQL 注入。 |
| 以串流方式傳送資料 | 將大型二進位和字元值串流到 SQL Server。 |
| 執行交易 | 將語句組成原子事務。 |
| 使用表格值參數 | 將 TABLE 參數傳遞給預存程序。 |
| 指定游標類型並選擇列 | 選擇僅前進、靜態、動態或鍵集游標。 |
數據類型
| 文章 | Description |
|---|---|
| 資料型態轉換 | 驅動程式如何將 PHP 型別映射到 SQL Server 型別。 |
| 預設 SQL Server 資料型態 | 每個 PHP 值的預設 SQL Server 類型。 |
| 預設 PHP 資料型態 | 每個 SQL Server 欄位類型的預設 PHP 類型。 |
| 指定 SQL Server 資料型別(SQLSRV) | 綁定參數時覆寫 SQL Server 類型。 |
| 指定 PHP 資料型別 | 擷取時要覆蓋 PHP 類型。 |
| 傳送與取回 UTF-8 資料 | 將 PDO::SQLSRV_ENCODING_UTF8 用於 Unicode 來回轉換。 |
| 在 Linux 和 macOS 上傳送與取回 ASCII 資料 | 在非 Windows 主機上處理 ASCII 的來回轉換。 |
| 格式化小數與貨幣(SQLSRV) | 使用 SQLSRV 驅動程式格式化 十進位 和 金錢 欄位。 |
| 格式化小數和貨幣(PDO_SQLSRV) | 使用 PDO_SQLSRV 驅動程式格式化 decimal 和 money 欄位。 |
| 非系統區域設定 | 局部十進位分隔符及其他地區考量。 |
錯誤和診斷
| 文章 | Description |
|---|---|
| 處理錯誤與警告 | 兩個驅動程式都有錯誤與警告處理。 |
| 配置錯誤與警告處理(SQLSRV) | 調整 SQLSRV 驅動程式如何回報錯誤與警告。 |
| 處理錯誤與警告(SQLSRV) | 檢查 SQLSRV 函式所回傳的錯誤。 |
| 記錄活動 | 啟用驅動程式日誌以進行診斷擷取。 |
部署和操作
| 文章 | Description |
|---|---|
| 性能調校 | 連線管理、批次處理、預備語句、游標、記憶體,以及伺服器端監控。 |
| Troubleshooting | 診斷常見的安裝、連線、查詢、資料型別、交易及容器問題。 |
參考內容
| 文章 | Description |
|---|---|
| SQLSRV 驅動程式 API 參考 | 所有 sqlsrv_* 函式、參數與回傳值。 |
| PDO_SQLSRV 驅動程式參考 | PDO_SQLSRV 驅動程式所支援的 PDO 和 PDOStatement 方法。 |
| 常數 | 驅動程式會暴露的常數,包括型別與編碼常數。 |
相關工作
| 文章 | Description |
|---|---|
| 發行說明 | 各版本歷史,包含新功能、錯誤修正、平台支援變更及下載連結。 |
| 關於文件中的程式碼範例 | 本節範例程式碼所使用的慣例。 |
| PHP SQL 驅動程式的範例 | SQLSRV 與 PDO_SQLSRV 的端到端範例應用程式。 |
| 支援資源 | 社群與支援管道。 |
相關內容
- Microsoft PHP for SQL Server 驅動程式於 GitHub 上
- 適用於 SQL Server 的 Microsoft ODBC 驅動程式
- Microsoft SQL Database 的
連線模組