Microsoft SQL Server 用 PHP ドライバー

PHP ドライバーのダウンロード

Microsoft Drivers for PHP for SQL Serverは、PHPスクリプトからMicrosoft SQL データベース エンジンでデータを読み書きするためのPHP拡張機能です。 2つの拡張機能は同じMicrosoft ODBCドライバfor SQL Serverを使用していますが、異なるPHP APIやドライバー固有のオプションを提供しています。

  • SQLSRVはSQL Server機能に合わせた手続き型API(sqlsrv_*関数)を公開します。
  • PDO_SQLSRV は PHPデータオブジェクト(PDO) インターフェースを実装しています。 PDOコールは既存のデータベースコードに残すことができますが、データベースを切り替える前にクエリやドライバー固有の設定を確認してください。

両ドライバーはAzure SQL Database、Microsoft FabricのSQLデータベース、Azure SQL Managed Instance、およびExpressエディションを含むSQL Serverのサポートされているすべてのバージョンとエディションに接続しています。 両方のドライバーはPHPストリームを入力パラメータとして受け入れています。 SQLSRVは大きなバイナリおよび文字値をストリームとして取得することをサポートしています。 PDO_SQLSRV が同じ出力ストリーミング動作をすると想定しないでください。

出発点を選択する

Azure SQLの運用ベースライン

このPDO_SQLSRV例は環境変数からサーバーとデータベースを読み取り、管理対象 ID を使用して接続します。 データソース名(DSN)を構築し、証明書検証によるトランスポート層セキュリティ(TLS)を可能にします。 これらの値は、ウェブリクエストパラメータではなく、信頼できるアプリケーション設定から読み取ってください。 アイデンティティにデータベースへのアクセスを許可した後、マネージドアイデンティティエンドポイントを持つホスト上でプログラムを実行します。

ヘルパー機能は、リストされたエラーが発生した場合、最大3回まで接続するか、読み取り専用クエリを実行します。 試行の間隔が長くなり、これは指数バックオフと呼ばれる再試行パターンです。 クエリエラーで新しい接続が必要な場合、クエリヘルパーは呼び出しコードが処理する例外をスローします。

サポートされているPHPバージョン、PDO_SQLSRV拡張機能、SQL Server 用 Microsoft ODBC Driver 18 を使用してください。 サポートされる認証の値については、「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];

// This read helper retries only the listed errors on the same connection.
// Other errors propagate; the caller must decide whether to reconnect.
const RETRYABLE_READ_ERROR_CODES = [1205, 1222, 40501, 10928, 10929];

/**
 * 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);
            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');
}

/**
 * Retry the standalone read-only query for errors that allow connection reuse.
 */
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, RETRYABLE_READ_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.');
}
$databaseValue = '{' . str_replace('}', '}}', $database) . '}';

$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,
    $databaseValue
);

$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 name FROM sys.databases WHERE database_id > ? ORDER BY name', [1]);
foreach ($stmt as $row) {
    echo $row['name'], PHP_EOL;
}

これらの設定はAzure SQL DatabaseのフェイルオーバーグループとAzure SQL Managed Instanceに使ってください。

  • Driver={ODBC Driver 18 for SQL Server} ドライバー検出に頼らず、ODBCドライバー18を明示的に選択します。 例を動かす前にインストールしてください。

  • SQL_DATABASEを実際のデータベース名に設定してください。 このプログラムは閉鎖ブレースを二重にし、名前をブレースで囲んでからDSNに配置します。 エスケープすることで、名前の特殊文字がドライバーの接続設定の読み取り方を変えるのを防ぎます。

  • ConnectRetryCount と ConnectRetryInterval は ODBCのアイドル接続の回復力を制御します。 ステートメントのクエリタイムアウトは実行中の回復の範囲を制限します。 サンプルの30秒のクエリタイムアウトがあるため、ODBCは5回の再接続試行をすべて終える前に停止する可能性があります。 LoginTimeout=90 接続の確立をコントロールするのであって、そのリカバリー予算ではありません。 アプリケーションレベルのヘルパーは、選択したサーバーエラーを再試行します。クエリのタイムアウト時に再試行したり、部分的に取得された結果を再実行したりはしません。

  • プログラムの error_log() コールと同時にドライバーログを有効にしてください。 PDO_SQLSRVの場合は、php.ini で、または実行時に ini_set() を使用して、pdo_sqlsrv.log_severity を設定してください。 SQLSRVの場合は、LogSubsystemsを使用してLogSeverityとsqlsrv_configure()を設定してください。 詳細については 、「ログ活動」をご覧ください。

    ; 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 Service または Azure Container Instance で識別元のクライアント ID を使い、そうでなければオブジェクト ID を使います。 PHPドライバーはこの動作を基盤となるMicrosoft ODBC Driver for SQL Serverから継承しています。詳細は「Using Microsoft Entra ID with the ODBC Driver」をご覧ください。 DSNにIDを埋め込むのではなく、PDOコンストラクタのユーザー名引数を使用してください。 ユーザー(サンプルがそうする)としてnullを渡すことで、Azureホストのシステム割り当て管理IDを選択します。 SQLSRV(手続き型)では、接続オプション配列に UID を渡します。

  • フェイルオーバーグループリスナー、可用性グループリスナー、またはフェイルオーバークラスタインスタンスエンドポイントに接続する際に MultiSubnetFailover=true 設定してください。 設定すると、単一サブネットおよび複数サブネットの可用性グループリスナーの両方の接続性能が向上します。 詳細については、 高可用性のサポート、災害復旧をご覧ください。

  • 読み取りスケールアウトまたは読み取り可能なセカンダリの場合は、DSN に ApplicationIntent=ReadOnly を追加してください。

  • SQLサービスが提供するクラウド固有のドメインを含むエンドポイントを使用してください。 証明書名の不一致を調査し、証明書検証を無効にするのではなく調査しましょう。 そのエンドポイントに対して予期される証明書名が分かっている場合にのみ、HostNameInCertificateを使ってください。

  • ODBCはマネージドIDおよびサービス主体認証のためのトークンを取得します。 AccessTokenの場合、アプリケーションがトークンを取得してドライバーに渡します。ODBCが代わりに取得するわけではありません。 詳細情報については、「ODBC ドライバーでの Microsoft Entra ID の使用」をご覧ください。

  • 接続情報はコード外に保管してください。 アプリケーションの設定システムに保存し、秘密情報はAzure Key Vaultを使ってください。

  • SQLSRVでは、sqlsrv_connect() に渡す配列内で接続オプションを設定してください。 false の戻り値を確認し、再試行するかどうかを判断する前に sqlsrv_errors() を確認してください。 QueryTimeout を使用して、ステートメントのタイムアウトを個別に設定してください。 アイドル接続のレジリエンシー は、アプリケーションレベルの再試行ループではなく、ODBCの再接続を示します。

  • リトライ ヘルパーは、isset() で保護された $e->errorInfo[1] を読み取ります。 PDOException::$errorInfo は ?array として宣言され、デフォルトは nullとなるため、防御チェックは 0 のドライバーコードにフォールバックし、SQLSTATE 08 プレフィックスが再試行の判断をします。

この構成の各部分の詳細については、以下を参照してください。

Azure SQL一時的なエラーのカタログについては、「一時的な接続エラーのトラブルシューティング」を参照してください。

主要な機能

  • 2つのPHP API: SQLSRVは手続き型関数を提供します。 PDO_SQLSRV は PDO の実装です。 拡張機能のどちらか、または両方をインストールしてください。
  • 幅広いプラットフォームサポート:Windows、Linux、macOSで動作し、PHP版もサポートされています。
  • 暗号化接続: Encrypt=trueによるTLS暗号化接続で、サーバー証明書の検証は TrustServerCertificateによって制御されます。
  • Microsoft Entra ID認証:管理されたID、サービスプリンシパル、および基盤となるMicrosoft ODBCドライバfor SQL Serverを通じて外部取得されたアクセストークン。 マネージド ID はパスワード不要です。ActiveDirectoryServicePrincipal はクライアント シークレットを使用します。
  • Always Encrypted: クライアント側で機密カラムを暗号化し、暗号化されたデータに対するサポート対象の操作にはセキュア エンクレーブを使用します。
  • 接続の回復性: ConnectRetryCount と ConnectRetryInterval による、アイドル接続の再試行機能を内蔵。
  • PHPストリーム:ストリームパラメータから大きなバイナリ値や文字値をいずれのAPIでも送信します。 ストリーミング取得にはSQLSRVを使いましょう。
  • 豊富なSQL Serverデータ型のサポート:datetimeoffset、table-valued parameters、nvarchar、Unicodeと PDO::SQLSRV_ENCODING_UTF8。

概要

[アーティクル] Description
システム要件 PHP、オペレーティングシステム、SQL Serverのバージョンに対応しています。
サポート マトリックス PHPドライバリリースの詳細な互換性マトリックス。
Microsoft Drivers for PHP for SQL Server をダウンロードしてください リンクをダウンロードし、アーティファクトを公開してください。
LinuxおよびmacOSのインストールチュートリアル LinuxとmacOSにドライバーとそのODBCの前提条件をインストールしてください。
ドライバーの読み込み php.iniで拡張機能を有効にしてください。
クイックスタート:PHP用Microsoftドライバーと接続しクエリを 拡張を検証し、接続を設定し、同じパラメータ付きクエリをSQLSRVやPDO_SQLSRVで実行します。
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 認証を使用して接続する マネージドIDフロー、サービスプリンシパル、アクセストークン、パスワードフロー。
SQL Server認証による接続 ユーザー名とパスワードを入力したSQLログインを使いましょう。
Windows 認証で接続 Windowsでは統合認証を、LinuxやmacOSではKerberosを使いましょう。

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データの送信および取得 SQLSRVの CharacterSet オプションまたはPDO_SQLSRVの PDO::SQLSRV_ATTR_ENCODING 属性を設定してください。
LinuxおよびmacOSでASCIIデータの送受信 非WindowsホストでのASCII往復処理を行ってください。
小数点と貨幣のフォーマット(SQLSRV) SQLSRVドライバーで 10進数 と マネー の列をフォーマットしてください。
フォーマット:小数点と貨幣(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 Drivers for PHP for SQL Server GitHub リポジトリで Issue を作成してください。