Instale os drivers PHP para SQL Server no Windows

Use este artigo para instalar o SQLSRV e PDO_SQLSRV drivers para PHP no Windows. Os drivers são extensões PHP que utilizam o Microsoft ODBC Driver for SQL Server.

Antes de começar, confirme que a sua versão PHP, arquitetura e modo de segurança de threads são suportados na matriz de suporte. O runtime PHP usado por um processo de linha de comandos e o runtime usado por um servidor web podem usar ficheiros php.ini diferentes. Configure e verifique cada runtime separadamente.

No final do procedimento, tanto sqlsrv_connect() como o controlador/driver PDO sqlsrv devem estar disponíveis para a CLI ou aplicação web pretendida, e cada API deve completar uma consulta de teste. Uma cópia bem-sucedida do ficheiro por si só não é uma instalação concluída.

Escolha um método de instalação

Method Use-o quando O que é instalado
Instalador PHP para Extensões (PIE) Pretende que o instalador selecione a build do driver para o executável PHP Não versionados php_sqlsrv.dll e php_pdo_sqlsrv.dll, com configuração automática tentada
Pacote ZIP disponibilizado Tens de escolher, inspecionar ou instalar ficheiros pré-construídos específicos tu mesmo DLLs versionadas selecionadas pela versão secundária do PHP, modo de segurança de threads e arquitetura

Utilize um método para ambas as extensões. Não mantenha as entradas de configuração PIE e ZIP ativas ao mesmo tempo.

Pré-requisitos de instalação

  1. Instala uma compilação PHP suportada a partir do site PHP para Windows. Adicione o diretório PHP a PATH.

  2. Instala o Visual C++ Redistributable exigido pela tua compilação do PHP. Adapte a sua arquitetura x64 ou x86 ao PHP, conforme descrito nos requisitos do PHP para Windows.

  3. Instale o mais recente driver Microsoft ODBC para SQL Server.

  4. Execute os seguintes comandos para confirmar o ambiente de execução e o ficheiro de configuração do PHP:

    php --version
    php --ini
    

    Se Ficheiro de Configuração Carregado for (none), copie php.ini-development para php.ini no diretório PHP.

  5. Em php.ini, defina o diretório de extensões e ative as extensões exigidas pelo PHP Installer for Extensions (PIE):

    extension_dir = "ext"
    extension=openssl
    extension=zip
    
  6. Confirme que o PHP consegue localizar as extensões pré-requisitas:

    php --ri openssl
    php --ri zip
    

    Corrija estes pré-requisitos antes de transferir o PIE.

Instalar com PIE

O PIE instala o driver pré-compilado correspondente para o runtime PHP. Não é necessário um compilador C no Windows.

  1. Mude para um diretório onde possas escrever e descarrega o arquivo PIE PHP mais recente (PHAR):

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

    Os restantes comandos PIE referem-se ao ficheiro como .\pie.phar, por isso execute-os a partir deste mesmo diretório.

    Antes de executares o PHAR, verifica-o com a interface de linha de comandos (CLI) do GitHub:

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

    Confirme o download antes de continuar:

    dir pie.phar
    php .\pie.phar --version
    
  2. Instale cada driver separadamente:

    php .\pie.phar install microsoft/sqlsrv
    php .\pie.phar install microsoft/pdo_sqlsrv
    
  3. Verifique o runtime da linha de comandos:

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

O PIE tenta ativar as extensões na configuração usada pelo executável de linha de comandos. Se o PIE reportar que não conseguiu ativar uma extensão, adicione as entradas de extensão específicas do PIE.

Se o seu servidor web usar outra instalação PHP, instale ambos os drivers para a versão PHP dessa instalação, arquitetura e modo de segurança de execução por threads antes de a configurar. Se a mesma instalação do PHP usar um ficheiro php.ini diferente para o servidor web, ative os controladores instalados nesse ficheiro. Verifique o runtime web separadamente e reinicie o servidor web após alterar a sua configuração.

O PIE altera a instalação PHP selecionada. Não configura o IIS, não seleciona um site IIS, nem reinicia processos PHP existentes.

Instalar manualmente um pacote ZIP lançado

Use este método quando precisar de selecionar os ficheiros do driver você próprio ou quando o PIE não for adequado.

  1. Descarregue o ZIP do Windows para a versão lançada do controlador na página Microsoft Drivers for PHP for SQL Server releases.

  2. Execute php -i | findstr /I "PHP Version Thread Safety Architecture extension_dir" e grave a versão PHP, o modo de segurança de threads, a arquitetura e o diretório de extensões.

  3. A partir do ZIP, copie ambas as bibliotecas de ligação dinâmica (DLLs) correspondentes para o diretório de extensão:

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

    Por exemplo, um tempo de execução PHP 8.5 x64 thread-safe utiliza php_sqlsrv_85_ts_x64.dll e php_pdo_sqlsrv_85_ts_x64.dll.

  4. Adicione os nomes correspondentes das extensões ao php.ini utilizado pelo runtime:

    extension=php_sqlsrv_85_ts_x64.dll
    extension=php_pdo_sqlsrv_85_ts_x64.dll
    

    Substitua 85, ts e x64 pelos valores do runtime do PHP. Não misture ficheiros thread-safe e non-thread-safe, ficheiros de 32 bits e 64 bits, ou ficheiros criados para outra versão secundária do PHP.

  5. Verifique o tempo de execução com php --ri sqlsrv, php --ri pdo_sqlsrv, e php -m. Para um servidor web, restrinja o acesso a páginas de diagnóstico antes de criar uma temporária phpinfo() página. Verifica o Ficheiro de Configuração Carregado e ambas as secções do driver, depois feche a página.

Configurar um servidor web

Para o IIS, configure o php-cgi.exe pretendido como uma aplicação FastCGI seguindo as orientações para a instalação do PHP no IIS. Confirma que a aplicação FastCGI usa o mesmo diretório PHP e arquitetura que usaste para instalar os drivers.

Para qualquer servidor web Windows:

  1. Restringa o acesso à página de diagnóstico antes de criar uma página temporária phpinfo() . Identifique o executável PHP do servidor web e o executável PHP ativo php.ini.

  2. Certifique-se de que ambos os controladores estão instalados para o runtime Web. Para uma instalação PHP separada, use PIE com o executável PHP dessa instalação, ou copie ambas as DLLs correspondentes do ZIP lançado para o seu diretório de extensão. Adicione as entradas do driver à configuração do runtime web, incluindo quando apenas o seu php.ini difere da CLI.

  3. Reinicie o servidor web ou os processos do FastCGI.

  4. Confirme que a página contém secções separadas sqlsrv e pdo_sqlsrv separadas.

  5. Remova a phpinfo() página.

Testar ambas as APIs PHP

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

Executa primeiro a partir da linha de comandos:

php verify-php-drivers.php

Produção esperada:

SQLSRV and PDO_SQLSRV are available.

Se precisares de verificar um runtime web, coloca temporariamente o ficheiro na raiz do documento do site e solicita-o num navegador. Remova-o depois do teste. Este programa verifica as APIs PHP sem exigir ou expor credenciais de base de dados.

Testar uma ligação a uma base de dados

O carregamento da extensão é apenas a primeira verificação de instalação. Teste ambas as APIs contra o destino da base de dados que a aplicação utiliza, de modo que o teste também cubra o driver ODBC, o caminho de rede, a encriptação, a autenticação, a execução da consulta, os valores devolvidos e a limpeza.

Defina variáveis temporárias de ambiente no PowerShell respondendo a prompts. Insira os nomes do servidor e da base de dados como valores brutos, sem aspas ou codificação do controlador. Use a caixa de diálogo de credenciais ou o prompt de credenciais para uma conta de teste que possa ligar-se à base de dados. Não inclua credenciais numa linha de comandos ou numa sessão de terminal gravada:

$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

O pedido de credenciais oculta a palavra-passe. O ambiente contém a palavra-passe em texto simples para que o PHP a possa ler. Utilize estas variáveis apenas na sessão de teste, não as imprima e elimine-as depois do teste.

Guarde este programa como test-php-drivers.php. Mantenha os valores de ambiente inalterados. O programa duplica as chaves de fecho e adiciona as chaves exteriores antes de passar o nome da base de dados, nome de utilizador e palavra-passe ao driver. Esta codificação preserva as chavetas literais e impede que os pontos e vírgulas separem as opções de ligação.

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

Executa o programa com o mesmo executável PHP que verificaste:

php test-php-drivers.php

Produção esperada:

SQLSRV query: 1
PDO_SQLSRV query: 1

Se a verificação da extensão passar mas este programa falhar, use o SQLSTATE e o erro nativo para identificar a camada responsável. Não reinstale as extensões PHP em caso de erro de rede, de certificado, de autenticação ou de permissão da base de dados.

Remover o script e as variáveis temporárias após testar:

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

Symptom O que deve verificar Corrigir
Could not open input file: .\pie.phar Diretório atual e localização de download Volte ao diretório que contém o PHAR verificado, ou descarregue e verifique novamente
Unable to load dynamic library extension_dir, nome exato da DLL, versão secundária do PHP, arquitetura e modo de segurança de threads Selecione a DLL correspondente ou reexecute o PIE com o executável PHP pretendido
The specified module could not be found Dependências das DLLs do driver Confirme a existência da DLL de extensão, instale o Visual C++ Redistributable correspondente e inspecione qualquer dependência DLL em falta remanescente
O CLI carrega ambos os drivers, mas o IIS não Executável PHP diferente ou php.ini Compare php --ini com phpinfo(), configure o tempo de execução do IIS e reinicie o FastCGI
Module "sqlsrv" is already loaded Tanto entradas PIE como ZIP, ou entradas repetidas Mantém uma entrada SQLSRV e uma PDO_SQLSRV entrada
O PDO comunica could not find driver configuração do PDO_SQLSRV Execute php --ri pdo_sqlsrv e verifique PDO::getAvailableDrivers()
O PIE reporta sucesso, mas uma versão antiga permanece Entradas ZIP versionadas ainda ativas Substitua entradas antigas pelas entradas DLL não versionadas do PIE e reinicie todos os processos PHP

Se ambas as extensões carregarem, o PHP pode chamar as suas APIs. Capturar erros SQLSRV ou a exceção PDO antes de mudar os ficheiros do driver. Erros de rede, autenticação, encriptação, certificado e permissões de base de dados não são corrigidos ao reinstalar a extensão PHP.