Instala los controladores PHP para SQL Server en Windows

Utiliza este artículo para instalar los controladores SQLSRV y PDO_SQLSRV para PHP en Windows. Los controladores son extensiones PHP que utilizan el Microsoft ODBC Driver for SQL Server.

Antes de empezar, confirma que tu versión de PHP, arquitectura y modo de seguridad de hilos están soportados en la matriz de soporte. El entorno de ejecución de PHP usado por un proceso de línea de comandos y el entorno de ejecución usado por un servidor web pueden usar archivos de configuración diferentes php.ini. Configura y verifica cada entorno de ejecución por separado.

Al final del procedimiento, tanto sqlsrv_connect() como el controlador PDO sqlsrv deben estar disponibles para la CLI o aplicación web prevista, y cada API debe completar una consulta de prueba. Una copia exitosa de archivo por sí sola no es una instalación completa.

Elección de un método de instalación

Method Úselo cuando Qué instala
Instalador PHP para extensiones (PIE) Quieres que el instalador seleccione la versión del controlador para el ejecutable PHP Sin versión php_sqlsrv.dll y php_pdo_sqlsrv.dll, con intento de configuración automática
Paquete ZIP lanzado Tienes que elegir, inspeccionar o desplegar tú mismo los archivos precompilados exactos DLL versionadas seleccionadas por la versión menor de PHP, el modo de seguridad de hilos y la arquitectura

Usa un método para las dos extensiones. No mantengas activas las entradas de configuración PIE y ZIP al mismo tiempo.

Requisitos previos de instalación

  1. Instala una compilación de PHP compatible desde el sitio PHP para Windows. Añadir el directorio PHP a PATH.

  2. Instala el Visual C++ Redistributable que requiere tu compilación en PHP. Haz coincidir su arquitectura x64 o x86 con la de PHP, como se describe en los requisitos de PHP para Windows.

  3. Instala el último controlador ODBC de Microsoft para SQL Server.

  4. Ejecuta los siguientes comandos para confirmar el entorno de ejecución de PHP y el archivo de configuración:

    php --version
    php --ini
    

    Si el archivo de configuración cargado es (none), copia php.ini-development a php.ini en el directorio PHP.

  5. En php.ini, establezca el directorio de extensiones y habilite las extensiones requeridas por el PHP Installer for Extensions (PIE):

    extension_dir = "ext"
    extension=openssl
    extension=zip
    
  6. Confirma que PHP puede localizar las extensiones necesarias:

    php --ri openssl
    php --ri zip
    

    Corrige estos requisitos antes de descargar PIE.

Instalar con PIE

PIE instala el controlador precompilado correspondiente para el entorno de ejecución de PHP. No requiere un compilador C en Windows.

  1. Ve a un directorio en el que puedas escribir y descarga el último archivo PHP de PIE (PHAR):

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

    Los comandos PIE restantes se refieren al archivo como .\pie.phar, así que ejecútalos desde ese mismo directorio.

    Antes de ejecutar el PHAR, verifícalo con la interfaz de línea de comandos (CLI) de GitHub:

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

    Confirma la descarga antes de continuar:

    dir pie.phar
    php .\pie.phar --version
    
  2. Instala cada controlador por separado:

    php .\pie.phar install microsoft/sqlsrv
    php .\pie.phar install microsoft/pdo_sqlsrv
    
  3. Verifica el entorno de ejecución de línea de comandos:

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

PIE intenta habilitar las extensiones en la configuración utilizada por el ejecutable de línea de comandos. Si PIE informa que no pudo habilitar una extensión, añade las entradas de extensión específicas de PIE.

Si tu servidor web utiliza otra instalación de PHP, instala ambos controladores para la versión de PHP, la arquitectura y el modo thread-safe/no thread-safe de esa instalación antes de configurarlo. Si la misma instalación de PHP usa otro php.ini para el servidor web, activa los controladores instalados en ese archivo. Verifica el entorno de ejecución web por separado y reinicia el servidor web tras cambiar su configuración.

PIE cambia la instalación PHP seleccionada. No configura IIS, no selecciona un sitio IIS ni reinicia procesos PHP existentes.

Instalar manualmente un paquete ZIP publicado

Usa este método cuando necesites seleccionar tú mismo los archivos de controladores o cuando PIE no sea adecuado.

  1. Descarga el ZIP de Windows para la versión lanzada del controlador desde la página de versiones de Microsoft Drivers for PHP for SQL Server.

  2. Ejecuta php -i | findstr /I "PHP Version Thread Safety Architecture extension_dir" y graba la versión de PHP, el modo thread-safe, la arquitectura y el directorio de extensiones.

  3. Desde el ZIP, copia ambas bibliotecas de enlace dinámico (DLL) correspondientes al directorio de extensión:

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

    Por ejemplo, un entorno de ejecución PHP 8.5 x64 seguro para hilos utiliza php_sqlsrv_85_ts_x64.dll y php_pdo_sqlsrv_85_ts_x64.dll.

  4. Añade los nombres de extensión correspondientes al php.ini usado por el entorno de ejecución:

    extension=php_sqlsrv_85_ts_x64.dll
    extension=php_pdo_sqlsrv_85_ts_x64.dll
    

    Sustituye 85, ts, y x64 por los valores de tu entorno de ejecución PHP. No mezcles archivos seguros para subprocesos y no seguros para subprocesos, archivos de 32 y 64 bits, o archivos construidos para otra versión menor de PHP.

  5. Verifica el tiempo de ejecución con php --ri sqlsrv, php --ri pdo_sqlsrv, y php -m. Para un servidor web, restrinja el acceso a páginas de diagnóstico antes de crear una phpinfo() página temporal. Verifica el archivo de configuración cargado y ambas secciones de controladores, luego elimina la página.

Configurar un servidor web

Para IIS, configura el php-cgi.exe previsto como una aplicación FastCGI siguiendo las guías de instalación de PHP para IIS. Confirma que la aplicación FastCGI utiliza el mismo directorio y arquitectura PHP que tú usaste para instalar los controladores.

Para cualquier servidor web de Windows:

  1. Restringir el acceso a la página de diagnóstico antes de crear una página temporal phpinfo(). Identifica el ejecutable PHP del servidor web y la configuración activa php.ini.

  2. Asegúrate de que ambos drivers estén instalados para el runtime web. Para una instalación PHP separada, usa PIE con el ejecutable PHP de esa instalación, o copia ambas DLLs coincidentes del ZIP liberado a su directorio de extensiones. Añade las entradas del controlador a la configuración del entorno web, incluyendo cuando solo su php.ini difiere de la CLI.

  3. Reinicia el servidor web o los procesos de FastCGI.

  4. Confirma que la página contiene secciones separadas sqlsrv y pdo_sqlsrv separadas.

  5. Quita la phpinfo() página.

Prueba ambas APIs PHP

Guarda este programa como 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);

Ejecútalo primero desde la línea de comandos:

php verify-php-drivers.php

Resultado esperado:

SQLSRV and PDO_SQLSRV are available.

Si necesitas verificar un entorno de ejecución web, coloca el archivo temporalmente en la raíz del documento del sitio y solicítalo desde un navegador. Sácalo después de las pruebas. Este programa verifica las APIs de PHP sin requerir ni exponer credenciales de base de datos.

Prueba una conexión a una base de datos

La carga de extensiones es solo la primera comprobación de instalación. Prueba ambas APIs con el destino de la base de datos que utiliza la aplicación, de modo que la prueba también cubra el controlador ODBC, la ruta de red, el cifrado, la autenticación, la ejecución de consultas, los valores devueltos y la limpieza.

Establece variables temporales de entorno en PowerShell respondiendo a las preguntas. Introduce los nombres del servidor y la base de datos como valores en bruto, sin comillas ni codificación del controlador. Utiliza el diálogo o la solicitud de credenciales para una cuenta de prueba que pueda conectarse a la base de datos. No incluyas credenciales en una línea de comandos ni en una sesión terminal grabada:

$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

La solicitud de credenciales oculta la contraseña. El entorno contiene la contraseña en texto plano para que PHP pueda leerla. Usa estas variables solo en la sesión de prueba, no las imprimas y elimínalas después de la prueba.

Guarda este programa como test-php-drivers.php. Mantén los valores del entorno sin cambios. El programa duplica las llaves de cierre y añade las llaves exteriores antes de pasar el nombre de la base de datos, nombre de usuario y contraseña al controlador. Esta codificación preserva las llaves literales y evita que los puntos y coma separen las opciones de conexión.

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

Ejecuta el programa con el mismo ejecutable PHP que has verificado:

php test-php-drivers.php

Resultado esperado:

SQLSRV query: 1
PDO_SQLSRV query: 1

Si la comprobación de extensión pasa pero este programa falla, utiliza el estado SQLSTATE y el error nativo para identificar la capa propietaria. No reinstales las extensiones PHP si se produce un error de red, certificado, autenticación o permiso de base de datos.

Elimina el script y las variables temporales tras las pruebas:

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

Síntoma Elementos que se deben comprobar Corregir
Could not open input file: .\pie.phar Directorio actual y ubicación de descarga Vuelve al directorio que contiene la PHAR verificada, o descárgala y verifica de nuevo
Unable to load dynamic library extension_dir, nombre exacto de DLL, versión menor de PHP, arquitectura y modo de seguridad de hilos Selecciona la DLL correspondiente o reejecuta el PIE con el ejecutable PHP previsto
The specified module could not be found Dependencias de las DLL de los controladores Confirma que existe la DLL de extensión, instala el Visual C++ Redistributable correspondiente e inspecciona cualquier dependencia DLL que falte
La CLI carga ambos controladores pero IIS no Ejecutable PHP diferente o php.ini Compare php --ini con phpinfo(), configure el entorno de ejecución de IIS y reinicie FastCGI
Module "sqlsrv" is already loaded Tanto entradas PIE como ZIP, o entradas repetidas Guarda una entrada SQLSRV y otra PDO_SQLSRV
Informes de PDO could not find driver Configuración de PDO_SQLSRV Corre php --ri pdo_sqlsrv y revisa PDO::getAvailableDrivers()
PIE informa de éxito, pero queda una versión antigua Entradas ZIP versionadas que siguen activas Sustituye las entradas antiguas por las entradas DLL sin versión de PIE y reinicia cada proceso PHP

Si ambas extensiones cargan, PHP puede llamar a sus APIs. Captura errores SQLSRV o la excepción PDO antes de cambiar los archivos del controlador. Los errores de red, autenticación, cifrado, certificados y permisos de base de datos no se solucionan reinstalando la extensión PHP.