Resolução de Problemas dos Controladores Microsoft para PHP para SQL Server

Descarregar o driver PHP

Diagnostice e resolva problemas comuns quando utiliza os Microsoft Drivers for PHP for SQL Server para se ligar ao SQL Server, Base de Dados SQL do Azure, Azure SQL Managed Instance e base de dados SQL em Microsoft Fabric.

Para padrões gerais de tratamento de erros e avisos, veja Gestão de erros e avisos. Para captura de diagnóstico do lado do condutor, veja Atividade de registo.

Problemas de instalação

Extensão não carregada

Sintomas:

  • phpinfo() Não lista a secção A sqlsrv OR pdo_sqlsrv .
  • PDOException: could not find driver ao construir a PDO com a sqlsrv: DSN.
  • Fatal error: Uncaught Error: Call to undefined function sqlsrv_connect().

Possíveis causas e soluções:

  • Extensão não ativada em php.ini. Confirma que tanto extension=sqlsrv o quanto extension=pdo_sqlsrv não são comentados. No Windows, use o nome completo do ficheiro (extension=php_sqlsrv_84_ts_x64.dll). Para mais detalhes, veja Carregar os drivers.
  • Configuração errada de segurança de rosca. O binário do driver deve corresponder à segurança de threads da sua build PHP (ts para thread-safe, nts para não-thread-safe). Executa php -i | grep "Thread Safety" para verificar. Descarregue o binário correspondente na página de download.
  • Driver Microsoft ODBC em falta. Os drivers PHP envolvem o Microsoft ODBC Driver for SQL Server. No Linux e macOS, instale msodbcsql18 (ou msodbcsql17) com o seu gestor de pacotes antes de carregar as extensões. No Windows, instala o driver ODBC a partir da página de download.

Verifique uma instalação bem-sucedida:

php -m | grep -i sqlsrv

Deves ver ambos pdo_sqlsrv e sqlsrv na saída.

Falha a instalação do PECL no Linux ou macOS

Sintomas:

error: ‘SQL_HANDLE_DBC’ undeclared (first use in this function)
fatal error: 'sql.h' file not found

Correção:

Instale os cabeçalhos de desenvolvimento ODBC antes de executar pecl install:

  • Ubuntu e Debian: sudo apt-get install unixodbc-dev
  • Chapéu Vermelho, Fedora e CentOS:sudo dnf install unixODBC-devel
  • Alpino: apk add unixodbc-dev
  • macOS:brew install unixodbc

Depois tenta:

sudo pecl install sqlsrv
sudo pecl install pdo_sqlsrv

Se pecl ainda assim falhar depois de instalar os cabeçalhos, a cadeia de ferramentas de construção pode estar incompleta. Instale phpize, re2c, e um compilador C++ (build-essential no Debian e Ubuntu, gcc-c++ make no Red Hat e Fedora, build-base no Alpine).

Para o caminho completo de instalação, veja o tutorial de instalação para Linux e macOS.

Múltiplas versões PHP instaladas

Sintomas:

phpinfo() no seu servidor web mostra uma versão do PHP, mas php -v na linha de comandos aparece outra, e o driver aparece carregado apenas numa delas.

Correção:

Cada versão do PHP tem o seu php.ini próprio diretório.ext Localiza o ficheiro php --ini de configuração correto dentro do ambiente que não tem o driver e adiciona as extension= linhas aí. Reinicie o servidor web (Apache, Nginx + PHP-FPM ou IIS) após qualquer alteração php.ini.

Problemas de ligação

Impossível ligar-se ao servidor

Sintomas:

SQLSTATE[08001]: [Microsoft][ODBC Driver 18 for SQL Server]TCP Provider: A connection attempt failed
SQLSTATE[HYT00]: [Microsoft][ODBC Driver 18 for SQL Server]Login timeout expired

Possíveis causas e soluções:

  • O servidor não está acessível. Verifica se o nome do servidor e a porta estão corretos. A partir do host PHP, testar a conectividade TCP bruta.

    # Linux and macOS
    nc -vz <server>.database.windows.net 1433
    
    # Windows PowerShell
    Test-NetConnection -ComputerName <server>.database.windows.net -Port 1433
    
  • Firewall bloqueia a saída do 1433. Firewalls corporativos e NSGs cloud frequentemente bloqueiam a porta de saída 1433. Adicione uma exceção, ou permita os intervalos de IP do Base de Dados SQL do Azure para a sua região.

  • SQL do Azure server firewall. Adicione o IP público do seu cliente às regras do firewall ao nível do servidor no portal Azure.

  • Instância nomeada. Para uma instância nomeada, verifique se o serviço SQL Server Browser está a correr no servidor e se o UDP 1434 está aberto. Ou, liga-te por porta em vez de pelo nome da instância.

Início de sessão falhado

Sintomas:

SQLSTATE[28000]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Login failed for user '<user_id>'.

Possíveis causas e soluções:

  • Modo de autenticação SQL desativado. As instâncias do SQL Server Local têm por defeito apenas autenticação Windows. Ative a autenticação em modo misto no SQL Server Management Studio em propriedades>do servidor Segurança e depois reinicie o serviço SQL Server.
  • SQL do Azure credentials format. O SQL do Azure requer o nome de utilizador totalmente qualificado (user@servername) ao ligar a ferramentas que não o adicionam automaticamente.
  • Utilizador não mapeado para a base de dados. Verifique se o login tem um mapeamento de utilizador na base de dados de destino e se o utilizador tem as permissões necessárias.
  • Prefiro o Microsoft Entra ID. Para SQL do Azure, Azure SQL Managed Instance e base de dados SQL no Fabric, utilize autenticação Microsoft Entra (Authentication=ActiveDirectoryMsi, Authentication=ActiveDirectoryServicePrincipal, ou um token de acesso) em vez de logins SQL. Veja Ligar usando a autenticação do Microsoft Entra.

Valor inválido especificado para o atributo de cadeia de ligação 'Authentication'

Sintomas:

SQLSTATE[08001]: [Microsoft][ODBC Driver 17 for SQL Server]Invalid value specified for connection string attribute 'Authentication'

Motivo:

O driver ODBC reporta o erro, mas o verdadeiro problema é a qual driver PDO_SQLSRV vinculado. Se a DSN não incluir uma Driver= palavra-chave e o host tiver ODBC 17 e ODBC 18 instalados, PDO_SQLSRV pode associar à versão mais antiga. As versões antigas ODBC 17.x não conhecem valores mais recentes Authentication como ActiveDirectoryServicePrincipal ou ActiveDirectoryDefault, e até ActiveDirectoryMsi requerem ODBC 17.3.1.1 ou uma versão posterior.

Correção:

Fixe o driver no DSN:

<?php
$dsn = "sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=$server;Database=$db;" .
       "Encrypt=true;Authentication=ActiveDirectoryMsi";
$conn = new PDO($dsn, null, null, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

A forma entre parênteses ({ODBC Driver 18 for SQL Server}) escapa dos espaços no nome do driver. A própria mensagem de erro nomeia sempre o driver que a reportou, por isso o prefixo [Microsoft][ODBC Driver 17 for SQL Server] no erro é a forma mais rápida de confirmar o driver incorreto.

A palavra-chave inválida 'UID' foi especificada na cadeia DSN

Sintomas:

SQLSTATE[IMSSP]: An invalid keyword 'UID' was specified in the DSN string.

Motivo:

PDO_SQLSRV impõe uma lista de permitir palavras-chave DSN e não aceita UID nem PWD está na DSN. O PDO reserva o segundo e terceiro argumentos do construtor para esses argumentos, e PDO_SQLSRV traduz-os internamente para ODBC UID/PWD .

Correção:

Mova o nome de utilizador (e a palavra-passe, para autenticação SQL) para o construtor PDO:

<?php
// SQL authentication.
$dsn = "sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=$server;Database=$db;Encrypt=true";
$conn = new PDO($dsn, $user, $password);

// User-assigned managed identity. Pass the identity's client ID as $username.
$dsn = "sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=$server;Database=$db;" .
       "Encrypt=true;Authentication=ActiveDirectoryMsi";
$conn = new PDO($dsn, $clientId, null);

O controlador procedural SQLSRV, por contraste, aceita UID e PWD no array de opções de ligação é passado para sqlsrv_connect().

PDO_SQLSRV ignora silenciosamente o AccessToken no array de opções

Sintoma:

Tem um token de acesso Microsoft Entra (por exemplo, de az account get-access-token --resource https://database.windows.net/, , ou ClientSecretCredential), e passa-o para PDO_SQLSRV como ['AccessToken' => $token] no quarto argumento ManagedIdentityCredentialdo construtor. A tentativa de ligação falha com um erro confuso como Windows logins are not supported in this version of SQL Server ou Login failed for user '', como se não tivessem sido fornecidas credenciais.

Motivo:

O quarto argumento construtor do PDO é reservado para constantes de atributo específicas do driver (chaves inteiras como PDO::ATTR_ERRMODE). O PDO deixa cair silenciosamente entradas com chaves de string, como AccessToken, por isso PDO_SQLSRV nunca vê o token. A ligação volta então à autenticação integrada do Windows, que o servidor rejeita.

Correção:

Passa AccessToken para a cadeia DSN. Reserve o array de opções para PDO::ATTR_* constantes.

<?php
$server = '<server>.database.windows.net';
$token  = getenv('SQL_ACCESS_TOKEN');   // raw JWT, no "Bearer " prefix

$dsn = "sqlsrv:Server=$server;Database=<database>;Encrypt=true;AccessToken=$token";
$conn = new PDO($dsn, null, null, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);

Para exemplos adicionais de autenticação Microsoft Entra, incluindo o formulário DSN para PDO_SQLSRV, veja Conectar usando autenticação Microsoft Entra.

Para procedurais SQLSRV, AccessToken pertence ao array connection-info passado para sqlsrv_connect(), que de facto envolve o JWT bruto em SQL_COPT_SS_ACCESS_TOKEN para ti:

<?php
$server = '<server>.database.windows.net';
$token  = getenv('SQL_ACCESS_TOKEN');   // raw JWT, no "Bearer " prefix

$connectionInfo = [
    'Database'               => '<database>',
    'AccessToken'            => $token,
    'Encrypt'                => true,
    'TrustServerCertificate' => false,
    'Driver'                 => '{ODBC Driver 18 for SQL Server}',
];

$conn = sqlsrv_connect($server, $connectionInfo);
if ($conn === false) {
    print_r(sqlsrv_errors());
    exit(1);
}

Erros no certificado TLS

Sintomas:

SQLSTATE[08001]: SSL Provider: The certificate chain was issued by an authority that is not trusted
SQLSTATE[08001]: SSL Provider: The target principal name is incorrect

Soluções:

Prefira um certificado de confiança. Usa TrustServerCertificate=true apenas para desenvolvimento local contra um servidor que controlas.

Para desenvolvimento contra um certificado auto-assinado:

<?php
$server   = 'localhost';
$database = '<database>';
$user     = '<user_id>';
$password = '<password>';

$dsn = "sqlsrv:Server=$server;Database=$database;Encrypt=true;TrustServerCertificate=true";
$conn = new PDO($dsn, $user, $password, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);

Caution

TrustServerCertificate=true Desativa a validação do certificado do servidor. Nunca leves esse cenário para produção, encenação ou ambientes partilhados.

Para um nome de host de produção que não corresponde ao Nome Comum do certificado (por exemplo, ao ligar-se através de um ouvinte), especifique o sujeito real do certificado:

<?php
$dsn = "sqlsrv:Server=<listener>;Database=<database>;Encrypt=true;HostNameInCertificate=*.database.windows.net;Authentication=ActiveDirectoryMsi";
$conn = new PDO($dsn, null, null, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);

Tempo limite de ligação

Sintomas:

SQLSTATE[HYT00]: Login timeout expired

Possíveis causas e soluções:

  • LoginTimeout Não definir ou definir demasiado baixo para o failover a frio. Defina um explicit LoginTimeout (em segundos) no DSN ao ligar-se ao SQL do Azure. Os failovers em grupos de failover e bases de dados de arranque a frio podem demorar mais do que um curto timeout do lado do cliente permite. Consulte Opções de Ligação para a referência de opções.
  • Orçamento de reconexão de relição truncado. Se definires ConnectRetryCount e ConnectRetryInterval, certifica-te LoginTimeout >= ConnectRetryCount * ConnectRetryIntervalde . Caso contrário, o tempo limite de login termina o ciclo de reconexão mais cedo. Ver resiliência da ligação ociosa.
<?php
$dsn = "sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=<server>.database.windows.net;Database=<database>;" .
       "Encrypt=true;LoginTimeout=90;ConnectRetryCount=5;ConnectRetryInterval=15;" .
       "Authentication=ActiveDirectoryMsi";
$conn = new PDO($dsn, null, null, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);

Problemas de execução de consultas

Falhas silenciosas com PDO

Sintoma:

A PDO::exec() OR PDOStatement::execute() chama false mas não abre exceção.

Correção:

Com o PHP 8.0 e versões posteriores, o modo de erro PDO predefinido é PDO::ERRMODE_EXCEPTION. Se uma chamada for retornada false sem ser lançada, a aplicação alterou o modo para PDO::ERRMODE_SILENT ou PDO::ERRMODE_WARNING. Volte a colocar o modo de exceção para que as falhas gerem exceções:

<?php
$conn = new PDO($dsn, $user, $password, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);

Se não conseguires mudar o modo globalmente, verifica $conn->errorInfo() (ou $stmt->errorInfo()) após cada chamada. O array contém [SQLSTATE, driver code, driver message].

Nome do objeto inválido

Sintomas:

SQLSTATE[42S02]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Invalid object name 'Products'.

Possíveis causas e soluções:

  • Contexto errado na base de dados. Confirme com uma pergunta rápida:

    <?php
    $stmt = $conn->query("SELECT DB_NAME()");
    echo $stmt->fetchColumn();
    
  • Falta-lhe o qualificador de esquema. Use nomes totalmente qualificados para evitar depender do esquema padrão do chamador:

    SELECT * FROM dbo.Products;
    
  • Sensibilidade a maiúsculas e minúsculas. As bases de dados criadas com uma colação sensível a maiúsculos de caso tratam products e Products como objetos diferentes. Corresponde exatamente ao caso na definição da tabela.

Número errado de parâmetros

Sintomas:

SQLSTATE[HY093]: Invalid parameter number
SQLSTATE[07002]: COUNT field incorrect or syntax error

Correção:

Para PDO_SQLSRV, o número de ? marcadores deve coincidir com o número de valores que passa para execute(), e cada um ? liga um único escalar (não um array). Para parâmetros nomeados, cada :name um no SQL deve aparecer no array e vice-versa.

<?php
$stmt = $conn->prepare(
    "SELECT * FROM dbo.Products WHERE CategoryID = ? AND ListPrice > ?"
);
$stmt->execute([1, 50.0]);
foreach ($stmt as $row) {
    // ...
}

Para SQLSRV, passe o array de parâmetros para sqlsrv_query() ou sqlsrv_prepare():

<?php
$stmt = sqlsrv_query(
    $conn,
    "SELECT * FROM dbo.Products WHERE CategoryID = ? AND ListPrice > ?",
    [1, 50.0]
);
if ($stmt === false) {
    die(print_r(sqlsrv_errors(), true));
}

Para uma introdução mais abrangente à ligação de parâmetros, veja Executar consultas parametrizadas.

PDO emulado prepara erros de máscara

Sintomas:

Uma instrução corre com sucesso numa ligação, mas gera um erro de sintaxe noutra ligação que utiliza o mesmo texto de consulta.

Motivo:

PDO_SQLSRV suporta tanto declarações preparadas emuladas como nativas. Prepara emulado (PDO::ATTR_EMULATE_PREPARES = true) interpolam parâmetros do lado do cliente. As preparações nativas (false) enviam a consulta e os parâmetros separadamente para o servidor. O comportamento difere para TOP (?), parâmetros de tabela e alguns casos extremos na coerção do tipo.

Correção:

Prefiro preparações nativas em produção. Defina PDO::ATTR_EMULATE_PREPARES => false no momento da ligação para que o comportamento seja consistente entre os ambientes:

<?php
$conn = new PDO($dsn, null, null, [
    PDO::ATTR_ERRMODE          => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false,
]);

Para detalhes sobre quando usar cada modo, veja PDO::p repare.

Problemas de tipos de dados

Os caracteres Unicode aparecem como ? ou distorcidos

Sintomas:

As linhas que o PHP escreve contêm pontos de interrogação ou caracteres de substituição em vez dos caracteres originais não ASCII. As leituras devolvem texto distorcido.

Possíveis causas e soluções:

  • O tipo de coluna é VARCHAR, não NVARCHAR. As colunas varchar usam uma página de códigos, não Unicode. Use nvarchar para texto internacionalizado.

  • Falta uma dica de codificação UTF-8 no PDO_SQLSRV. Quando a tua coluna do SQL Server for nvarchar e os teus dados PHP forem UTF-8, diz ao driver para converter entre UTF-8 (cliente) e UTF-16 (servidor):

    <?php
    $conn = new PDO(
        "sqlsrv:Server=<server>;Database=<database>;Encrypt=true",
        $user,
        $password,
        [
            PDO::ATTR_ERRMODE                    => PDO::ERRMODE_EXCEPTION,
            PDO::SQLSRV_ATTR_ENCODING            => PDO::SQLSRV_ENCODING_UTF8,
        ]
    );
    
  • Driver SQLSRV: solicitar UTF-8 explicitamente. SQLSRV_ENC_CHAR é a página de código do sistema padrão de 8 bits, não UTF-8. Para UTF-8 com SQLSRV, define "CharacterSet" => "UTF-8" a ligação e passa o literal 'UTF-8' para SQLSRV_PHPTYPE_STRING on fetch ou bind. Veja Enviar e recuperar dados UTF-8.

Erros de conversão de data e hora

Sintomas:

SQLSTATE[22007]: Invalid character value for cast specification

Correção:

Em PDO_SQLSRV, não prendas um objeto bruto DateTime . O PDO stringifica valores limitados antes de ligar, e o DateTime PHP não __toString() tem método, pelo que execute([new DateTime(...)]) eleva Object of class DateTime could not be converted to string. Formate primeiro o valor, ou passe uma cadeia ISO 8601 (YYYY-MM-DD HH:MM:SS[.fff]), que não seja uma cadeia formatada localmente.

<?php
$stmt = $conn->prepare("INSERT INTO dbo.Events (EventDate) VALUES (?)");
$stmt->execute([(new DateTime("2026-03-15 10:00:00"))->format("Y-m-d H:i:s.u")]);

Para obter as colunas de data-hora como DateTime objetos em vez de cadeias no PDO_SQLSRV, defina o atributo da instrução:

<?php
$stmt = $conn->prepare("SELECT EventDate FROM dbo.Events");
$stmt->setAttribute(PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE, true);
$stmt->execute();

Para mais detalhes, veja Recuperar objetos de data-hora (PDO_SQLSRV).

Problemas de formatação decimal

Sintomas:

Os valores entre -1 e 1 não têm um zero à frente, ou os valores de dinheiro e dinheiro pequeno mostram um número inesperado de casas decimais.

Correção:

PDO_SQLSRV obtém sempre valores decimais e numéricos como cadeias com a sua precisão e escala exatas. Defina PDO::SQLSRV_ATTR_FORMAT_DECIMALS para adicionar um zero à esquerda aos valores entre -1 e 1:

<?php
$conn->setAttribute(PDO::SQLSRV_ATTR_FORMAT_DECIMALS, true);

PDO::SQLSRV_ATTR_DECIMAL_PLACES Aplica-se apenas ao dinheiro e aos valores de dinheiro pequeno . Define a escala apresentada de 0 a 4 e pode arredondar o valor apresentado. Não afeta valores decimais ou numéricos .

Para mais detalhes, veja Formatar decimais e dinheiro (PDO_SQLSRV) ou Formatar decimais e dinheiro (SQLSRV).

Problemas de transação

As alterações nos dados não persistem

Sintomas:

As linhas que inseres ou atualizas no PHP não aparecem quando consultas a partir de outra sessão.

Motivo:

PDO::beginTransaction()abre uma transação explícita que requer um .commit() Se o script PHP terminar sem chamar commit(), o PDO reverte a transação durante a limpeza da ligação.

Correção:

Emparelhe beginTransaction() sempre com commit(), e use try/catch para reverter em caso de erro:

<?php
try {
    $conn->beginTransaction();
    $conn->exec("INSERT INTO dbo.Orders (CustomerID, Total) VALUES (1, 100)");
    $conn->exec("UPDATE dbo.Inventory SET Stock = Stock - 1 WHERE ProductID = 5");
    $conn->commit();
} catch (PDOException $e) {
    $conn->rollBack();
    throw $e;
}

Para SQLSRV, use sqlsrv_begin_transaction, sqlsrv_commit, e sqlsrv_rollback.

Erros de bloqueio

Sintomas:

SQLSTATE[40001]: [Microsoft][ODBC Driver 18 for SQL Server][SQL Server]Transaction (Process ID 62) was deadlocked

Correção:

Lidar com erros de deadlock transitórios com lógica de retentativa. Envolve toda a transação (não apenas a extração falhada) para que extratos anteriores se repitam na transação nova. Para um padrão de retentativas orientado para produção, consulte o exemplo na página inicial do driver PHP.

Bloqueios recorrentes indicam um problema de design. Capture o gráfico de deadlock e analise quais as instruções e tipos de bloqueio envolvidos. Correções comuns incluem reordenação das operações para que transações concorrentes adquiram bloqueios na mesma sequência, redução do âmbito das transações e adição de índices para diminuir a duração dos bloqueios. Para um guia completo, consulte o guia Deadlocks.

Problemas de resiliência da ligação

A reconexão não acontece

Sintomas:

Uma ligação idle mantém-se quebrada após um failover do Base de Dados SQL do Azure, mesmo que tenhas definido ConnectRetryCount e ConnectRetryInterval.

Possíveis causas e soluções:

  • Cursor ativo do lado do servidor. A resiliência das ligações inativas apenas reconecta ligações ociosas . Um cursor aberto do lado do servidor ou uma transação pendente mantém a ligação ativa. Libertar cursores do lado do servidor usando sqlsrv_free_stmt() ou $stmt = null; (PDO) antes da janela de failover, ou mudar para um cursor bufferizado do lado do cliente. Ver resiliência da ligação ociosa.
  • Estado de sessão não recuperável. Alguns estados de sessão não podem ser restabelecidos, incluindo tabelas temporárias, cursores globais e locais, contexto de transação, bloqueios de aplicação, EXECUTE AS/REVERThandles de automação OLE, handles XML preparados e flags de traço. Qualquer um destes estados de sessão impede a reconexão automática.
  • LoginTimeout demasiado pequeno. Se ConnectRetryCount * ConnectRetryInterval > LoginTimeout, o condutor para de tentar novamente quando LoginTimeout é alcançado. Aumento LoginTimeout para cobrir todo o orçamento de retentativas.

Problemas de desempenho

Para diagnóstico e remediação de consultas lentas, arranques a frio, grandes conjuntos de resultados e inserções em massa, consulte Performance tuning.

Ativar diagnósticos de drivers

Quando as chamadas ao nível error_log() da aplicação não fornecem informação suficiente, ative o registo do lado do condutor. Reporta todas as chamadas ODBC feitas pelo motorista.

PDO_SQLSRV

Configura pdo_sqlsrv.log_severityphp.ini e reinicia o servidor web. Esta configuração só é legível na inicialização:

[pdo_sqlsrv]
pdo_sqlsrv.log_severity = 1

Os valores são 0 (desligado, o padrão), -1 (erros, avisos e avisos), 1 (erros), 2 (avisos) e 4 (avisos).

SQLSRV

Ativar o registo em tempo de execução com sqlsrv_configure():

<?php
sqlsrv_configure("LogSubsystems", SQLSRV_LOG_SYSTEM_CONN | SQLSRV_LOG_SYSTEM_STMT);
sqlsrv_configure("LogSeverity", SQLSRV_LOG_SEVERITY_ERROR | SQLSRV_LOG_SEVERITY_WARNING);

As entradas de registo vão para o ficheiro configurado por error_log em php.ini. Para a lista completa de subsistemas e severidades, veja Atividade de registo.

Problemas de contentores e CI

Bibliotecas de sistema em falta no Linux

Sintomas:

error while loading shared libraries: libodbc.so.2: cannot open shared object file
error while loading shared libraries: libssl.so.1.1: cannot open shared object file

Correção:

Instale as dependências em tempo de execução antes de instalar o driver PHP:

Distribution Comando de Instalação
Ubuntu e Debian sudo apt-get install unixodbc libgssapi-krb5-2
Chapéu Vermelho e Fedora sudo dnf install unixODBC krb5-libs
Alpine apk add unixodbc gcompat

Depois instala msodbcsql18 a partir do repositório de pacotes da Microsoft. Para repositórios e versões de pacotes específicos de distribuição, consulte o guia de instalação de drivers ODBC.

As builds de imagem Docker têm sucesso, mas as ligações falham em tempo de execução

Sintomas:

A imagem é construída e o PHP inicia, mas PDO::__construct() gera um erro ODBC de driver-in-found.

Correção:

Verifique se o driver ODBC está instalado na imagem de runtime, não apenas na fase de compilação. Instalar msodbcsql18 e unixodbc-dev na mesma fase de entrega para produção. Numa construção em várias etapas, instale-as na fase final. Uma instalação baseada em Debian de estágio único é a seguinte:

# Pin to a specific PHP minor version in production, for example php:8.4.11-cli.
FROM php:8.4-cli
RUN apt-get update && apt-get install -y --no-install-recommends \
        curl gnupg2 apt-transport-https ca-certificates \
    && curl -sSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /usr/share/keyrings/microsoft.gpg \
    && echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft.gpg] https://packages.microsoft.com/debian/12/prod bookworm main" > /etc/apt/sources.list.d/mssql-release.list \
    && apt-get update \
    && ACCEPT_EULA=Y apt-get install -y --no-install-recommends msodbcsql18 unixodbc-dev \
    # $PHPIZE_DEPS ships in the official php image and includes gcc, make, autoconf, and re2c.
    && apt-get install -y --no-install-recommends $PHPIZE_DEPS \
    && pecl install sqlsrv pdo_sqlsrv \
    && docker-php-ext-enable sqlsrv pdo_sqlsrv \
    && apt-get purge -y --auto-remove $PHPIZE_DEPS \
    && rm -rf /var/lib/apt/lists/*