이 글을 사용해 Windows에서 SQLSRV와 PDO_SQLSRV 드라이버를 설치하세요. 드라이버는 Microsoft ODBC 드라이버 for SQL Server를 사용하는 PHP 확장 기능입니다.
시작하기 전에 PHP 버전, 아키텍처, 스레드 세이프티 모드가 지원 매트릭스에서 지원되는지 확인하세요. 명령줄 프로세스에서 사용하는 PHP 런타임과 웹 서버가 사용하는 런타임은 서로 다른 php.ini 파일을 사용할 수 있습니다. 각 런타임을 별도로 구성하고 검증하세요.
절차가 끝나면 sqlsrv_connect()와 PDO sqlsrv 드라이버 둘 다 대상 CLI 또는 웹 애플리케이션에서 사용할 수 있어야 하며, 각 API는 테스트 쿼리를 완료해야 합니다. 성공적인 파일 복사만으로는 완전한 설치가 아닙니다.
설치 방법 선택
| Method | 사용해야 하는 경우 | 설치 항목 |
|---|---|---|
| 확장 기능을 위한 PHP 설치 프로그램(PIE) | 설치 프로그램이 PHP 실행 파일에 맞는 드라이버 빌드를 선택하도록 하려는 경우 | 버전이 지정되지 않은 php_sqlsrv.dll 및 php_pdo_sqlsrv.dll, 자동 구성 시도됨 |
| 출시된 ZIP 패키지 | 직접 미리 만들어진 파일을 선택하고, 검사하거나, 배포해야 합니다 | PHP 마이너 버전, 스레드 세이프티 모드, 아키텍처별로 선택된 버전별 DLL |
두 확장 모두 하나의 방법을 사용하세요. PIE와 ZIP 구성 항목을 동시에 활성화하지 마세요.
필수 구성 요소 설치
PHP for Windows 사이트에서 지원되는 PHP 빌드를 설치하세요.
PATH에 PHP 디렉터리를 추가합니다.PHP 빌드에 필요한 Visual C++ Redistributable을 설치하세요. Windows용 PHP 요구 사항에 설명된 대로 x64 또는 x86 아키텍처를 PHP와 일치시키세요.
최신 Microsoft ODBC 드라이버 for SQL Server를 설치하세요.
PHP 런타임과 구성 파일을 확인하기 위해 다음 명령을 실행하세요:
php --version php --ini로드된 구성 파일이
(none)이면,php.ini-development를 PHP 디렉터리의php.ini에 복사합니다.php.ini에서 확장 프로그램 디렉터리를 설정하고 PHP 확장 설치 프로그램(PIE)에서 요구하는 확장 기능을 활성화합니다:extension_dir = "ext" extension=openssl extension=zipPHP가 필요한 확장 기능을 찾을 수 있는지 확인하세요:
php --ri openssl php --ri zipPIE를 다운로드하기 전에 이 사전 요구 사항을 먼저 수정하세요.
PIE로 설치
PIE 는 PHP 런타임에 맞는 사전 컴파일된 드라이버를 설치합니다. Windows에서는 C 컴파일러가 필요하지 않습니다.
작성할 수 있는 디렉터리로 변경하여 최신 PIE PHP 아카이브(PHAR)를 다운로드하세요:
curl.exe -fL --output pie.phar https://github.com/php/pie/releases/latest/download/pie.phar나머지 PIE 명령어들은 파일을
.\pie.phar로 참조하므로 같은 디렉터리에서 실행하세요.PHAR을 실행하기 전에 GitHub 명령줄 인터페이스(CLI)로 확인해 보세요:
gh attestation verify --owner php .\pie.phar계속하기 전에 다운로드를 확인하세요:
dir pie.phar php .\pie.phar --version각 드라이버를 따로따로 설치하세요:
php .\pie.phar install microsoft/sqlsrv php .\pie.phar install microsoft/pdo_sqlsrv명령줄 런타임을 확인하세요:
php --ri sqlsrv php --ri pdo_sqlsrv php -m | findstr /I "sqlsrv pdo_sqlsrv"
PIE는 명령줄 실행 파일에서 사용하는 구성에서 확장을 활성화하려고 시도합니다. PIE가 확장 기능을 활성화할 수 없다고 보고하면 PIE 전용 확장 항목을 추가하세요.
웹 서버가 다른 PHP 설치를 사용한다면, 설정하기 전에 해당 설치의 PHP 버전, 아키텍처, 스레드 안전성 모드에 맞는 두 드라이버를 설치하세요. 같은 PHP 설치가 웹 서버에 다른 php.ini을(를) 사용한다면, 해당 파일에서 설치된 드라이버를 활성화하세요. 웹 런타임을 별도로 검증하고, 설정 변경 후 웹 서버를 재시작하세요.
PIE는 선택한 PHP 설치를 변경합니다. IIS를 구성하거나 IIS 사이트를 선택하거나 기존 PHP 프로세스를 재시작하지 않습니다.
수동으로 배포된 ZIP 패키지를 설치하세요
드라이버 파일을 직접 선택해야 하거나 PIE가 적합하지 않을 때 이 방법을 사용하세요.
Microsoft PHP for SQL Server 드라이버 릴리스 페이지에서 출시된 드라이버 버전에 대한 Windows ZIP을 다운로드하세요.
php -i | findstr /I "PHP Version Thread Safety Architecture extension_dir"를 실행하고 PHP 버전, 스레드 세이프티 모드, 아키텍처 및 확장 디렉터리를 기록하세요.ZIP에서 일치하는 두 개의 동적 링크 라이브러리(DLL)를 확장 디렉터리로 복사합니다:
php_sqlsrv_<php-version>_<ts-or-nts>_<x86-or-x64>.dll php_pdo_sqlsrv_<php-version>_<ts-or-nts>_<x86-or-x64>.dll예를 들어, PHP 8.5 x64 스레드 안전 런타임은
php_pdo_sqlsrv_85_ts_x64.dll와php_sqlsrv_85_ts_x64.dll를 사용합니다.런타임에서 사용하는
php.ini에 일치하는 확장 이름을 추가합니다:extension=php_sqlsrv_85_ts_x64.dll extension=php_pdo_sqlsrv_85_ts_x64.dllts,x64,85를 PHP 런타임 값으로 바꾸세요. 스레드 안전과 비스레드 안전 파일, 32비트와 64비트 파일, 또는 다른 PHP 마이너 버전을 위해 만들어진 파일을 섞지 마세요.php --ri sqlsrv,php --ri pdo_sqlsrv,php -m로 런타임을 검증합니다. 웹 서버의 경우, 임시 페이지를 만들기 전에phpinfo()하세요. 로드된 구성 파일과 두 드라이버 섹션을 모두 확인한 후 페이지를 제거하세요.
웹 서버 구성
IIS의 경우, php-cgi.exe에 따라 해당 을(를) FastCGI 애플리케이션으로 구성하세요. FastCGI 애플리케이션이 드라이버 설치 시 사용한 동일한 PHP 디렉터리와 아키텍처를 사용하는지 확인하세요.
모든 Windows 웹 서버에 대해:
임시 페이지를 만들기 전에
phpinfo()하세요. 웹 서버의 PHP 실행 파일과 활성php.ini을 식별합니다.웹 런타임에 두 드라이버가 모두 설치되어 있는지 확인하세요. 별도의 PHP 설치를 위해서는 해당 설치의 PHP 실행 파일과 함께 PIE를 사용하거나, 릴리스된 ZIP에서 일치하는 두 DLL을 확장 디렉터리로 복사하세요. CLI와 비교해
php.ini만 다른 경우도 포함하여 드라이버 항목을 웹 런타임 구성에 추가합니다.웹 서버나 FastCGI 프로세스를 재시작하세요.
페이지에 별도의
sqlsrv섹션과pdo_sqlsrv섹션이 있는지 확인하세요.phpinfo()페이지를 삭제하세요.
두 가지 PHP API 모두 테스트해 보세요
이 프로그램을 다음과 같이 verify-php-drivers.php저장하세요:
<?php
$failures = [];
if (!extension_loaded('sqlsrv') || !function_exists('sqlsrv_connect')) {
$failures[] = 'SQLSRV is not available.';
}
if (!extension_loaded('pdo_sqlsrv') || !in_array('sqlsrv', PDO::getAvailableDrivers(), true)) {
$failures[] = 'PDO_SQLSRV is not available.';
}
echo $failures === []
? "SQLSRV and PDO_SQLSRV are available." . PHP_EOL
: implode(PHP_EOL, $failures) . PHP_EOL;
exit($failures === [] ? 0 : 1);
먼저 명령줄에서 실행하세요:
php verify-php-drivers.php
예상 출력:
SQLSRV and PDO_SQLSRV are available.
웹 런타임을 검증해야 한다면, 해당 파일을 일시적으로 사이트 문서 루트에 저장하고 브라우저에서 해당 파일에 접속하세요. 테스트 후 제거하세요. 이 프로그램은 데이터베이스 자격 증명을 요구하거나 노출하지 않고 PHP API를 검증합니다.
데이터베이스 연결 테스트
확장 로딩은 첫 번째 설치 점검일 뿐입니다. 두 API 모두 애플리케이션이 사용하는 데이터베이스 대상에 대해 테스트하세요. 이렇게 하면 테스트가 ODBC 드라이버, 네트워크 경로, 암호화, 인증, 쿼리 실행, 반환 값, 정리도 다루게 됩니다.
PowerShell에서 프롬프트에 응답하여 임시 환경 변수를 설정하세요. 서버와 데이터베이스 이름을 따옴표나 드라이버 인코딩 없이 원시 값으로 입력합니다. 자격 증명 대화상자나 프롬프트를 사용해 데이터베이스에 연결할 수 있는 테스트 계정을 사용하세요. 명령줄이나 녹화된 터미널 세션에 자격 증명을 포함하지 마세요:
$env:SQL_SERVER_NAME = Read-Host "Server name (tcp:<server>,1433)"
$env:SQL_DATABASE = Read-Host "Database name"
$credential = Get-Credential -Message "Enter the database test account"
if ($null -eq $credential) {
throw "Database test credentials are required."
}
$env:SQL_UID = $credential.UserName
$env:SQL_PWD = $credential.GetNetworkCredential().Password
Remove-Variable credential
자격증명 프롬프트가 비밀번호를 가립니다. 환경에는 PHP가 읽을 수 있도록 평문 비밀번호가 포함되어 있습니다. 이 변수들은 테스트 세션에서만 사용하고, 출력하지 말고, 테스트 후에는 지우세요.
이 프로그램을 test-php-drivers.php로 저장하세요. 환경 값은 변경하지 말고 그대로 유지하세요. 프로그램은 닫는 중괄호를 두 배로 늘리고 바깥쪽 중괄호를 추가한 후 데이터베이스 이름, 사용자 이름, 비밀번호를 드라이버에 전달합니다. 이 인코딩은 문자 그대로의 중괄호를 보존하고 세미콜론이 연결 옵션을 구분하는 것을 방지합니다.
<?php
$serverName = getenv('SQL_SERVER_NAME');
$database = getenv('SQL_DATABASE');
$uid = getenv('SQL_UID');
$pwd = getenv('SQL_PWD');
if ($serverName === false || $serverName === ''
|| $database === false || $database === ''
|| $uid === false || $uid === ''
|| $pwd === false || $pwd === '') {
fwrite(STDERR, "Set SQL_SERVER_NAME, SQL_DATABASE, SQL_UID, and SQL_PWD." . PHP_EOL);
exit(1);
}
$database = '{' . str_replace('}', '}}', $database) . '}';
$uid = '{' . str_replace('}', '}}', $uid) . '}';
$pwd = '{' . str_replace('}', '}}', $pwd) . '}';
$connectionOptions = [
"Database" => $database,
"UID" => $uid,
"PWD" => $pwd,
"Encrypt" => 1,
"TrustServerCertificate" => 0,
];
$sqlsrvConnection = sqlsrv_connect($serverName, $connectionOptions);
if ($sqlsrvConnection === false) {
foreach (sqlsrv_errors() as $error) {
fwrite(
STDERR,
"SQLSRV {$error['SQLSTATE']} ({$error['code']}): {$error['message']}" . PHP_EOL
);
}
exit(1);
}
$sqlsrvStatement = sqlsrv_query($sqlsrvConnection, "SELECT 1 AS TEST_VALUE");
if ($sqlsrvStatement === false) {
foreach (sqlsrv_errors() as $error) {
fwrite(
STDERR,
"SQLSRV {$error['SQLSTATE']} ({$error['code']}): {$error['message']}" . PHP_EOL
);
}
sqlsrv_close($sqlsrvConnection);
exit(1);
}
$sqlsrvRow = sqlsrv_fetch_array($sqlsrvStatement, SQLSRV_FETCH_ASSOC);
if ($sqlsrvRow === false || $sqlsrvRow === null || (int) $sqlsrvRow['TEST_VALUE'] !== 1) {
fwrite(STDERR, "SQLSRV returned an unexpected result." . PHP_EOL);
sqlsrv_free_stmt($sqlsrvStatement);
sqlsrv_close($sqlsrvConnection);
exit(1);
}
echo "SQLSRV query: 1" . PHP_EOL;
sqlsrv_free_stmt($sqlsrvStatement);
sqlsrv_close($sqlsrvConnection);
$failed = false;
try {
$pdoConnection = new PDO(
"sqlsrv:server=$serverName;Database=$database;Encrypt=1;TrustServerCertificate=0",
$uid,
$pwd,
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
$pdoStatement = $pdoConnection->query("SELECT 1 AS TEST_VALUE");
$pdoRow = $pdoStatement->fetch(PDO::FETCH_ASSOC);
if ($pdoRow === false || (int) $pdoRow['TEST_VALUE'] !== 1) {
throw new RuntimeException("PDO_SQLSRV returned an unexpected result.");
}
echo "PDO_SQLSRV query: 1" . PHP_EOL;
} catch (Throwable $exception) {
fwrite(STDERR, $exception->getMessage() . PHP_EOL);
$failed = true;
} finally {
unset($pdoStatement);
unset($pdoConnection);
}
exit($failed ? 1 : 0);
확인한 동일한 PHP 실행 파일로 프로그램을 실행하세요:
php test-php-drivers.php
예상 출력:
SQLSRV query: 1
PDO_SQLSRV query: 1
확장 검사가 통과했지만 이 프로그램이 실패하면, SQLSTATE와 네이티브 오류를 사용해 오류를 소유한 계층을 식별합니다. 네트워크, 인증서, 인증, 데이터베이스 권한 오류 때문에 PHP 확장 기능을 재설치하지 마세요.
테스트 후 스크립트와 임시 변수를 제거하세요:
Remove-Item .\verify-php-drivers.php, .\test-php-drivers.php
Remove-Item Env:\SQL_SERVER_NAME, Env:\SQL_DATABASE, Env:\SQL_UID, Env:\SQL_PWD
Troubleshooting
| 증상 | 확인할 사항 | 수정 |
|---|---|---|
Could not open input file: .\pie.phar |
현재 디렉토리 및 다운로드 위치 | 검증된 PHAR이 포함된 디렉터리로 돌아가거나, 다운로드하여 다시 검증하세요 |
Unable to load dynamic library |
extension_dir, 정확한 DLL 이름, PHP 마이너 버전, 아키텍처, 그리고 스레드 세이프티 모드 |
일치하는 DLL을 선택하거나 의도된 PHP 실행 파일로 PIE를 재실행합니다 |
The specified module could not be found |
드라이버 DLL 의존성 | 확장 DLL이 존재하는지 확인하고, 일치하는 Visual C++ 재배포 가능 패키지를 설치하며, 남아 있는 DLL 의존성을 점검하세요 |
| CLI는 두 드라이버를 모두 로드하지만 IIS는 그렇지 않습니다 | 다른 PHP 실행 파일이나 php.ini |
phpinfo()와 php --ini를 비교하여 IIS 런타임을 구성하고 FastCGI를 재시작하세요 |
Module "sqlsrv" is already loaded |
PIE와 ZIP 항목 모두 또는 반복 항목 | SQLSRV 항목 하나와 PDO_SQLSRV 항목 하나를 유지하세요 |
PDO 보고 could not find driver |
PDO_SQLSRV 구성 | 실행하고 php --ri pdo_sqlsrv 확인해 PDO::getAvailableDrivers() |
| PIE는 성공을 보고하지만 오래된 버전은 남아 있습니다 | 버전화된 ZIP 항목이 여전히 활성화되어 있습니다 | 이전 항목을 PIE의 버전이 없는 DLL 항목으로 교체하고 모든 PHP 프로세스를 재시작하세요 |
두 확장 모두 로드되면 PHP가 API를 호출할 수 있습니다. 드라이버 파일을 변경하기 전에 SQLSRV 오류나 PDO 예외를 캡처하세요. 네트워크, 인증, 암호화, 인증서 및 데이터베이스 권한 오류는 PHP 확장 기능을 재설치한다고 해결되지 않습니다.