Instal driver PHP untuk SQL Server di Windows

Gunakan artikel ini untuk menginstal driver SQLSRV dan PDO_SQLSRV untuk PHP di Windows. Driver tersebut adalah ekstensi PHP yang menggunakan Microsoft ODBC Driver for SQL Server.

Sebelum memulai, pastikan versi PHP, arsitektur, dan mode thread-safety Anda didukung dalam matriks dukungan. Runtime PHP yang digunakan oleh proses baris perintah dan runtime yang digunakan oleh server web dapat menggunakan file php.ini yang berbeda. Konfigurasikan dan verifikasi setiap runtime secara terpisah.

Di akhir prosedur, baik sqlsrv_connect() driver maupun driver PDO sqlsrv harus tersedia untuk CLI atau aplikasi web yang dimaksud, dan setiap API harus berhasil menjalankan kueri uji. Salinan file yang berhasil saja bukanlah instalasi yang selesai.

Pilih metode penginstalan

Metode Gunakan saat Apa yang diinstal
PHP Installer untuk Ekstensi (PIE) Anda ingin installer memilih build driver untuk executable PHP Tidak berversi php_sqlsrv.dll dan php_pdo_sqlsrv.dll, dengan upaya konfigurasi otomatis
Paket ZIP rilis Anda perlu memilih, memeriksa, atau menyebarkan file prebuilt yang tepat sendiri DLL versi yang dipilih berdasarkan versi minor PHP, mode keamanan thread, dan arsitektur

Gunakan satu metode untuk kedua ekstensi. Jangan biarkan entri konfigurasi PIE dan ZIP aktif secara bersamaan.

Prasyarat instal

  1. Instal build PHP yang didukung dari situs PHP untuk Windows. Tambahkan direktori PHP ke PATH.

  2. Instal Visual C++ Redistributable yang dibutuhkan oleh build PHP Anda. Cocokkan arsitektur x64 atau x86 dengan PHP, seperti yang dijelaskan dalam persyaratan PHP untuk Windows.

  3. Instal Driver Microsoft ODBC terbaru untuk SQL Server.

  4. Jalankan perintah berikut untuk mengonfirmasi runtime dan file konfigurasi PHP:

    php --version
    php --ini
    

    Jika File Konfigurasi yang Dimuat adalah (none), salin php.ini-development ke php.ini di direktori PHP.

  5. Di php.ini, atur direktori ekstensi dan aktifkan ekstensi yang dibutuhkan oleh PHP Installer for Extensions (PIE):

    extension_dir = "ext"
    extension=openssl
    extension=zip
    
  6. Pastikan PHP dapat menemukan ekstensi prasyarat:

    php --ri openssl
    php --ri zip
    

    Perbaiki prasyarat ini sebelum mengunduh PIE.

Pasang dengan PIE

PIE menginstal driver yang sudah dikompilasi sebelumnya yang sesuai untuk runtime PHP. Ini tidak memerlukan kompiler C di Windows.

  1. Ubah ke direktori yang memiliki izin tulis, dan unduh arsip PIE PHP terbaru (PHAR):

    curl.exe -fL --output pie.phar https://github.com/php/pie/releases/latest/download/pie.phar
    

    Perintah PIE yang tersisa merujuk pada file sebagai .\pie.phar, jadi jalankan perintah-perintah tersebut dari direktori yang sama.

    Sebelum Anda menjalankan PHAR, verifikasi dengan antarmuka baris perintah GitHub (CLI):

    gh attestation verify --owner php .\pie.phar
    

    Konfirmasi unduhan sebelum melanjutkan:

    dir pie.phar
    php .\pie.phar --version
    
  2. Pasang setiap driver secara terpisah:

    php .\pie.phar install microsoft/sqlsrv
    php .\pie.phar install microsoft/pdo_sqlsrv
    
  3. Verifikasi runtime baris perintah:

    php --ri sqlsrv
    php --ri pdo_sqlsrv
    php -m | findstr /I "sqlsrv pdo_sqlsrv"
    

PIE berusaha mengaktifkan ekstensi dalam konfigurasi yang digunakan oleh executable baris perintah. Jika PIE melaporkan tidak dapat mengaktifkan ekstensi, tambahkan entri ekstensi spesifik PIE.

Jika server web Anda menggunakan instalasi PHP lain, instal kedua driver untuk versi, arsitektur, dan mode thread-safety dari instalasi PHP tersebut sebelum mengonfigurasinya. Jika instalasi PHP yang sama menggunakan php.ini yang berbeda untuk server web, aktifkan driver yang terpasang di file tersebut. Verifikasi web runtime secara terpisah, dan restart web server setelah mengubah konfigurasinya.

PIE mengubah instalasi PHP yang dipilih. Tidak mengonfigurasi IIS, memilih situs IIS, atau memulai ulang proses PHP yang sudah ada.

Instal secara manual paket ZIP yang telah dirilis

Gunakan metode ini saat Anda perlu memilih file driver sendiri atau ketika PIE tidak sesuai.

  1. Unduh file ZIP Windows untuk versi rilis driver dari halaman rilis Microsoft Drivers for PHP for SQL Server.

  2. Jalankan php -i | findstr /I "PHP Version Thread Safety Architecture extension_dir" dan rekam versi PHP, mode keamanan thread, arsitektur, dan direktori ekstensi.

  3. Dari ZIP, salin kedua pustaka tautan dinamis (DLL) yang cocok ke direktori ekstensi:

    php_sqlsrv_<php-version>_<ts-or-nts>_<x86-or-x64>.dll
    php_pdo_sqlsrv_<php-version>_<ts-or-nts>_<x86-or-x64>.dll
    

    Sebagai contoh, runtime thread-safe PHP 8.5 x64 menggunakan php_sqlsrv_85_ts_x64.dll dan php_pdo_sqlsrv_85_ts_x64.dll.

  4. Tambahkan nama ekstensi yang sesuai ke php.ini yang digunakan oleh runtime:

    extension=php_sqlsrv_85_ts_x64.dll
    extension=php_pdo_sqlsrv_85_ts_x64.dll
    

    Ganti 85, ts, dan x64 dengan nilai untuk runtime PHP Anda. Jangan mencampur file thread-safe dan non-thread-safe, file 32-bit dan 64-bit, atau file yang dibuat untuk versi minor PHP lainnya.

  5. Verifikasi runtime dengan php --ri sqlsrv, php --ri pdo_sqlsrv, dan php -m. Untuk server web, batasi akses halaman diagnostik sebelum membuat phpinfo() halaman sementara. Verifikasi File Konfigurasi yang Dimuat dan kedua bagian driver, lalu hapus halaman tersebut.

Konfigurasikan server web

Untuk IIS, konfigurasikan php-cgi.exe yang dimaksud sebagai aplikasi FastCGI dengan mengikuti panduan instalasi PHP IIS. Pastikan aplikasi FastCGI menggunakan direktori PHP dan arsitektur yang sama seperti yang Anda gunakan untuk menginstal driver.

Untuk server web Windows apa pun:

  1. Batasi akses halaman diagnostik sebelum membuat halaman sementara phpinfo() . Identifikasi executable PHP server web dan konfigurasi aktif php.ini.

  2. Pastikan kedua driver terpasang untuk runtime web. Untuk instalasi PHP terpisah, gunakan PIE dengan executable PHP instalasi tersebut, atau salin kedua DLL yang sesuai dari ZIP yang dirilis ke direktori ekstensinya. Tambahkan entri driver ke konfigurasi milik runtime web, termasuk ketika hanya php.ini yang berbeda dari CLI.

  3. Restart web server atau proses FastCGI.

  4. Pastikan halaman berisi bagian terpisah sqlsrv dan pdo_sqlsrv bagian.

  5. Hapus phpinfo() halaman.

Uji keduanya API PHP

Simpan program ini sebagai 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);

Jalankan terlebih dahulu dari baris perintah:

php verify-php-drivers.php

Output yang diharapkan:

SQLSRV and PDO_SQLSRV are available.

Jika Anda perlu memverifikasi runtime web, tempatkan file tersebut sementara di root dokumen situs dan akses file tersebut di browser. Lepaskan itu setelah pengujian. Program ini memverifikasi API PHP tanpa memerlukan atau mengekspos kredensial basis data.

Uji koneksi database

Loading ekstensi hanyalah pemeriksaan pertama saat instalasi. Uji kedua API terhadap target basis data yang digunakan aplikasi sehingga pengujian juga mencakup driver ODBC, jalur jaringan, enkripsi, autentikasi, eksekusi kueri, nilai yang dikembalikan, dan pembersihan.

Atur variabel lingkungan sementara di PowerShell dengan menjawab pertanyaan. Masukkan nama server dan database sebagai nilai mentah, tanpa tanda kutip atau pengkodean driver. Gunakan dialog kredensial atau prompt kredensial untuk akun uji yang dapat terhubung ke database. Jangan sertakan kredensial dalam baris perintah atau sesi terminal yang direkam:

$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

Prompt kredensial menutupi kata sandi. Lingkungan berisi kata sandi dalam teks biasa sehingga PHP dapat membacanya. Gunakan variabel ini hanya dalam sesi pengujian, jangan cetak variabel ini, dan hapus variabel ini setelah pengujian.

Simpan program ini sebagai test-php-drivers.php. Biarkan nilai variabel lingkungan tetap tidak berubah. Program ini menggandakan kurawal penutup dan menambahkan kurungan luar sebelum mengirimkan nama database, nama pengguna, dan kata sandi ke driver. Pengkodean ini mempertahankan kurung literal dan mencegah titik koma memisahkan opsi koneksi.

<?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);

Jalankan program dengan executable PHP yang sama seperti yang Anda verifikasi:

php test-php-drivers.php

Output yang diharapkan:

SQLSRV query: 1
PDO_SQLSRV query: 1

Jika pemeriksaan ekstensi lolos tetapi program ini gagal, gunakan SQLSTATE dan error native untuk mengidentifikasi layer pemiliknya. Jangan instal ulang ekstensi PHP karena kesalahan jaringan, sertifikat, autentikasi, atau izin database.

Hapus skrip dan variabel sementara setelah pengujian:

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

Gejala Apa yang harus diperiksa Perbaiki
Could not open input file: .\pie.phar Direktori saat ini dan lokasi unduhan Kembali ke direktori yang berisi PHAR yang telah diverifikasi, atau unduh dan verifikasi PHAR tersebut lagi
Unable to load dynamic library extension_dir, nama DLL tepat, versi minor PHP, arsitektur, dan mode keamanan thread Pilih DLL yang sesuai atau jalankan ulang PIE dengan executable PHP yang diinginkan
The specified module could not be found Ketergantungan DLL driver Konfirmasi DLL ekstensi ada, instal Visual C++ Redistributable yang sesuai, dan periksa ketergantungan DLL yang masih hilang
CLI memuat kedua driver tapi IIS tidak File executable PHP yang berbeda atau php.ini Bandingkan php --ini dengan phpinfo(), konfigurasikan runtime IIS, dan restart FastCGI
Module "sqlsrv" is already loaded Baik entri PIE maupun ZIP, atau entri berulang Pertahankan satu entri SQLSRV dan satu entri PDO_SQLSRV
PDO laporan could not find driver Konfigurasi PDO_SQLSRV Jalankan php --ri pdo_sqlsrv dan periksa PDO::getAvailableDrivers()
PIE melaporkan keberhasilan tetapi versi lama tetap ada Entri ZIP berversi masih aktif Ganti entri lama dengan entri DLL PIE yang tidak diversi dan mulai ulang setiap proses PHP

Jika kedua ekstensi dimuat, PHP dapat memanggil API mereka. Tangkap kesalahan SQLSRV atau pengecualian PDO sebelum mengubah file driver. Kesalahan jaringan, autentikasi, enkripsi, sertifikat, dan izin database tidak diperbaiki dengan menginstal ulang ekstensi PHP.