Solucionar los controladores de Microsoft para PHP para SQL Server

Descargar controlador PHP

Diagnostica y resuelve problemas comunes cuando uses los controladores de Microsoft para PHP para SQL Server para conectarte a SQL Server, Azure SQL Database, Azure SQL Managed Instance y la base de datos SQL en Microsoft Fabric.

Para patrones generales de gestión de errores y advertencias, véase Gestión de errores y advertencias. Para la captura de diagnóstico en el lado del conductor, consulte Actividad de registro.

Problemas de instalación

Extensión no cargada

Síntomas:

  • phpinfo() No menciona la sección A sqlsrv o pdo_sqlsrv O.
  • PDOException: could not find driver al construir a PDO con la sqlsrv: DSN.
  • Fatal error: Uncaught Error: Call to undefined function sqlsrv_connect().

Posibles causas y soluciones:

  • Extensión no activada en php.ini. Verifica que tanto extension=sqlsrv estén extension=pdo_sqlsrv sin comentarios. En Windows, usa el nombre completo del archivo (extension=php_sqlsrv_84_ts_x64.dll). Para más detalles, véase Cargar los controladores.
  • Configuración de seguridad de rosca incorrecta. El binario del controlador debe coincidir con la seguridad de hilos de tu compilación PHP (ts para Thread-Safe, nts para no Thread-Safe). Ejecute php -i | grep "Thread Safety" para comprobarlo. Descarga el binario correspondiente desde la página de descarga.
  • Microsoft ODBC Driver falta. Los controladores PHP envuelve el controlador ODBC de Microsoft para SQL Server. En Linux y macOS, instala msodbcsql18 (o msodbcsql17) con tu gestor de paquetes antes de cargar las extensiones. En Windows, instala el controlador ODBC desde la página de descarga.

Verifica si la instalación es exitosa:

php -m | grep -i sqlsrv

Deberías ver ambos pdo_sqlsrv y sqlsrv en la salida.

Falla la instalación de PECL en Linux o macOS

Síntomas:

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

Corrección:

Instala los encabezados de desarrollo ODBC antes de ejecutar pecl install:

  • Ubuntu y Debian: sudo apt-get install unixodbc-dev
  • Red Hat, Fedora y CentOS: sudo dnf install unixODBC-devel
  • Alpino: apk add unixodbc-dev
  • macOS: brew install unixodbc

Luego vuelve a intentarlo:

sudo pecl install sqlsrv
sudo pecl install pdo_sqlsrv

Si pecl aún falla después de instalar los colectores, la cadena de herramientas de construcción puede estar incompleta. Instala phpize, re2c, y un compilador en C++ (build-essential en Debian y Ubuntu, gcc-c++ make en Red Hat y Fedora, en build-base Alpine).

Para la ruta completa de instalación, consulta el tutorial de instalación para Linux y macOS.

Varias versiones de PHP instaladas

Síntomas:

phpinfo() en tu servidor web muestra una versión de PHP, pero php -v en la línea de comandos aparece otra, y el controlador aparece cargado solo en una de ellas.

Corrección:

Cada versión de PHP tiene su propio php.ini directorio ext . Localiza el archivo de configuración correcto desde php --ini el entorno que no tenga el controlador, y añade las extension= líneas ahí. Reinicia el servidor web (Apache, Nginx + PHP-FPM o IIS) tras cualquier cambio php.ini.

Problemas de conexión

No se puede conectar al servidor

Síntomas:

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

Posibles causas y soluciones:

  • El servidor no es accesible. Comprueba que el nombre del servidor y el puerto sean correctos. Desde el host PHP, prueba la conectividad TCP en bruto.

    # Linux and macOS
    nc -vz <server>.database.windows.net 1433
    
    # Windows PowerShell
    Test-NetConnection -ComputerName <server>.database.windows.net -Port 1433
    
  • El cortafuegos bloquea la salida 1433. Los cortafuegos corporativos y los NSGs en la nube suelen bloquear el puerto saliente 1433. Añade una excepción o permite los rangos de IP de Azure SQL Database para tu región.

  • Azure SQL server firewall. Añade la IP pública de tu cliente a las reglas del firewall a nivel de servidor en el portal de Azure.

  • Instancia con nombre. Para una instancia nombrada, verifica que el servicio SQL Server Browser está funcionando en el servidor y que UDP 1434 está abierto. O bien, conecta por puerto en vez de por nombre de la instancia.

Error de inicio de sesión

Síntomas:

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

Posibles causas y soluciones:

  • Modo de autenticación SQL desactivado. Las instancias locales de SQL Server solo usan autenticación de Windows por defecto. Activa la autenticación en modo mixto en SQL Server Management Studio bajo Propiedades>del servidor Seguridad y luego reinicia el servicio SQL Server.
  • Azure SQL credentials format. Azure SQL requiere el nombre de usuario totalmente cualificado (user@servername) al conectarse desde herramientas que no lo añaden automáticamente.
  • El usuario no está asignado a la base de datos. Verifica que el inicio de sesión tenga un mapa de usuario en la base de datos de destino y que el usuario tenga los permisos requeridos.
  • Prefiero Microsoft Entra ID. Para Azure SQL, Azure SQL Managed Instance y la base de datos SQL en Fabric, utiliza autenticación Microsoft Entra (Authentication=ActiveDirectoryMsi, Authentication=ActiveDirectoryServicePrincipal, o un token de acceso) en lugar de inicios de sesión SQL. Consulte Conexión mediante la autenticación de Microsoft Entra.

Valor inválido especificado para el atributo de cadena de conexión 'Authentication'

Síntomas:

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

Causa:

El controlador ODBC informa del error, pero el verdadero problema es a cuál controlador PDO_SQLSRV vinculado. Si la DSN no incluye una Driver= palabra clave y el host tiene ODBC 17 y ODBC 18 instalados, PDO_SQLSRV puede vincular a la versión anterior. Las versiones antiguas de ODBC 17.x no conocen valores más recientes Authentication como ActiveDirectoryServicePrincipal o ActiveDirectoryDefault, e incluso ActiveDirectoryMsi requieren ODBC 17.3.1.1 o una versión posterior.

Corrección:

Fija el controlador en la 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]);

La forma entre corchetes ({ODBC Driver 18 for SQL Server}) escapa de los espacios en el nombre del conductor. El mensaje de error siempre nombra al controlador que lo reportó, así que el prefijo [Microsoft][ODBC Driver 17 for SQL Server] en el error es la forma más rápida de confirmar el driver asignado incorrectamente.

La palabra clave inválida 'UID' se especificó en la cadena DSN

Síntomas:

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

Causa:

PDO_SQLSRV impone una lista de permisos de palabras clave DSN y no acepta UID ni PWD está en la DSN. PDO reserva los argumentos del segundo y tercer constructor para esos, y PDO_SQLSRV los traduce internamente a ODBC UID/PWD .

Corrección:

Mueve el nombre de usuario (y la contraseña, para autenticación SQL) al constructor 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);

El controlador procedural SQLSRV, en cambio, acepta UID y PWD en el array de opciones de conexión pasados a sqlsrv_connect().

PDO_SQLSRV ignora silenciosamente AccessToken en el array de opciones

Síntoma:

Tienes un token de acceso Microsoft Entra (por ejemplo, de az account get-access-token --resource https://database.windows.net/, , o ClientSecretCredential), y se lo pasas a PDO_SQLSRV como ['AccessToken' => $token] en el cuarto argumento ManagedIdentityCredentialdel constructor. El intento de conexión falla con un error confuso como Windows logins are not supported in this version of SQL Server o Login failed for user '', como si no se hubieran proporcionado credenciales.

Causa:

El cuarto argumento constructor de PDO está reservado para constantes de atributos específicas del controlador (claves enteras como PDO::ATTR_ERRMODE). PDO elimina silenciosamente entradas con clave de cadena como AccessToken, por lo que nunca PDO_SQLSRV ve el token. La conexión entonces vuelve a la autenticación integrada de Windows, que el servidor rechaza.

Corrección:

Pasa AccessToken a la cadena DSN. Reserva el array de opciones 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 ejemplos adicionales de autenticación Microsoft Entra, incluido el formulario DSN para PDO_SQLSRV, véase Conectar usando autenticación Microsoft Entra.

Para el procedimiento SQLSRV, AccessToken pertenece al array de conexión-info que pasa a sqlsrv_connect(), que envuelve el JWT SQL_COPT_SS_ACCESS_TOKEN en bruto 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);
}

Errores en el certificado TLS

Síntomas:

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

Soluciones:

Prefiero un certificado de confianza. Úsalo TrustServerCertificate=true solo para desarrollo local contra un servidor que controlas.

Para el desarrollo contra un certificado autofirmado:

<?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 Desactiva la validación del certificado del servidor. Nunca lleves ese escenario a la producción, la puesta en escena o en entornos compartidos.

Para un nombre de host de producción que no coincide con el Nombre Común del certificado (por ejemplo, al conectarse a través de un oyente), especifica el sujeto real del 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,
]);

Tiempo de espera de conexión

Síntomas:

SQLSTATE[HYT00]: Login timeout expired

Posibles causas y soluciones:

  • LoginTimeout No se configura o se ajusta demasiado bajo para el conmutador en frío. Establece un explícito LoginTimeout (en segundos) en el DSN al conectarte a Azure SQL. Las conmutaciones por error en grupos de conmutación y las bases de datos de arranque en frío pueden tardar más de lo que permite un corto tiempo de espera en el lado del cliente. Consulta Opciones de conexión para la referencia de opciones.
  • Presupuesto de reconexión de reconexión en reposo truncado. Si configuras ConnectRetryCount y ConnectRetryInterval, asegúrate LoginTimeout >= ConnectRetryCount * ConnectRetryIntervalde . De lo contrario, el tiempo de espera de inicio de sesión termina el bucle de reconexión antes de tiempo. Consulta resiliencia a la conexión en reposo.
<?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 ejecución de consultas

Fallos silenciosos con PDO

Síntoma:

Una PDO::exec() llamada de A PDOStatement::execute() o vuelve false pero no hace una excepción.

Corrección:

Con PHP 8.0 y versiones posteriores, el modo de error PDO por defecto es PDO::ERRMODE_EXCEPTION. Si una llamada regresa false sin lanzarla, la aplicación cambia el modo a PDO::ERRMODE_SILENT o PDO::ERRMODE_WARNING. Vuelve a ponerlo en modo excepción para que los fallos generen excepciones:

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

Si no puedes cambiar el modo globalmente, comprueba $conn->errorInfo() (o $stmt->errorInfo()) después de cada llamada. El array contiene [SQLSTATE, driver code, driver message].

Nombre de objeto no válido.

Síntomas:

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

Posibles causas y soluciones:

  • Contexto incorrecto de la base de datos. Verifica con una consulta rápida:

    <?php
    $stmt = $conn->query("SELECT DB_NAME()");
    echo $stmt->fetchColumn();
    
  • Faltan los requisitos de esquema. Utiliza nombres totalmente calificados para evitar depender del esquema predeterminado del llamante:

    SELECT * FROM dbo.Products;
    
  • Distinción entre mayúsculas y minúsculas. Las bases de datos creadas con una colación sensible a mayúsculas y minúsculas tratan products y Products como objetos diferentes. Coincide exactamente con el caso de la definición de la tabla.

Número incorrecto de parámetros

Síntomas:

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

Corrección:

Por PDO_SQLSRV, el número de ? marcadores debe coincidir con el número de valores que pasas a execute(), y cada uno ? une un único escalar (no un array). Para parámetros nombrados, cada :name en el SQL debe aparecer en el array y viceversa.

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

Para SQLSRV, pasa el array de parámetros a sqlsrv_query() o 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 una introducción más amplia a la vinculación de parámetros, véase Realizar consultas parametrizadas.

PDO emulado prepara errores de máscara

Síntomas:

Una instrucción se ejecuta correctamente en una conexión pero genera un error de sintaxis en otra conexión que utiliza el mismo texto de consulta.

Causa:

PDO_SQLSRV soporta tanto declaraciones preparadas emuladas como nativas. Los prepares emulados (PDO::ATTR_EMULATE_PREPARES = true) interpolan parámetros en el lado del cliente. Los preparadores nativos (false) envían la consulta y los parámetros por separado al servidor. El comportamiento varía para TOP (?), parámetros de tabla y algunos casos límite en la coerción de tipos.

Corrección:

Prefiero preparaciones nativas en producción. Configura PDO::ATTR_EMULATE_PREPARES => false en tiempo de conexión para que el comportamiento sea consistente entre los entornos:

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

Para más detalles sobre cuándo usar cada modo, véase PDO::p repare.

Problemas con tipos de datos

Los caracteres Unicode aparecen como ? o distorsionados

Síntomas:

Las filas que escribe PHP contienen signos de interrogación o caracteres de reemplazo en lugar de los caracteres originales no ASCII. Las lecturas devuelven texto distorsionado.

Posibles causas y soluciones:

  • El tipo de columna es VARCHAR, no NVARCHAR. Las columnas varchar usan una página de códigos, no Unicode. Usa nvarchar para textos internacionalizados.

  • Falta la pista de codificación UTF-8 en PDO_SQLSRV. Cuando tu columna de SQL Server sea nvarchar y tus datos PHP sean UTF-8, dile al controlador que convierta entre UTF-8 (cliente) y 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,
        ]
    );
    
  • Controlador SQLSRV: solicitar UTF-8 explícitamente. SQLSRV_ENC_CHAR es la página de códigos del sistema predeterminada de 8 bits, no UTF-8. Para UTF-8 con SQLSRV, pon "CharacterSet" => "UTF-8" en la conexión y pasa el literal 'UTF-8' a SQLSRV_PHPTYPE_STRING al buscar o bind. Consulta Enviar y recuperar datos UTF-8.

Errores de conversión de fecha y hora

Síntomas:

SQLSTATE[22007]: Invalid character value for cast specification

Corrección:

En PDO_SQLSRV, no encuantes un objeto en bruto DateTime . PDO stringe valores limitados antes de vincular, y PHP DateTime no __toString() tiene método, por lo que execute([new DateTime(...)]) eleva Object of class DateTime could not be converted to string. Formatea primero el valor o pasa una cadena ISO 8601 (YYYY-MM-DD HH:MM:SS[.fff]), no una cadena formateada por localidad.

<?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 obtener las columnas de fecha y hora como DateTime objetos en lugar de cadenas en PDO_SQLSRV, establece el atributo de la sentencia:

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

Para más detalles, véase Recuperar objetos de fecha y hora (PDO_SQLSRV).

Problemas de formato decimal

Síntomas:

Los valores entre -1 y 1 carecen de un cero inicial, o los valores de dinero y dinero pequeño muestran un número inesperado de decimales.

Corrección:

PDO_SQLSRV siempre obtiene valores decimales y numéricos como cadenas con su precisión y escala exactas. Establece PDO::SQLSRV_ATTR_FORMAT_DECIMALS para añadir un cero inicial a los valores entre -1 y 1:

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

PDO::SQLSRV_ATTR_DECIMAL_PLACES Se aplica solo al dinero y a los valores de dinero pequeño . Establece la escala mostrada del 0 al 4 y puede redondear el valor mostrado. No afecta a los valores decimales ni numéricos .

Para más detalles, véase Formatear decimales y dinero (PDO_SQLSRV) o Formatear decimales y dinero (SQLSRV).

Problemas de transacción

Los cambios en los datos no persisten

Síntomas:

Las filas que insertas o actualizas en PHP no aparecen cuando consultas desde otra sesión.

Causa:

PDO::beginTransaction()abre una transacción explícita que requiere un .commit() Si el script PHP termina sin llamar commit(), PDO revierte la transacción durante la limpieza de conexión.

Corrección:

Siempre empareja beginTransaction() con commit(), y úsalo try/catch para revertir en caso de error:

<?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, y sqlsrv_rollback.

Errores de interbloqueo

Síntomas:

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

Corrección:

Gestiona errores de bloqueo transitorio con lógica de reintentos. Envuelve toda la transacción (no solo el extracto que falla) para que los extractos anteriores se repitan en la transacción nueva. Para un patrón de reintentos orientado a producción, consulta el ejemplo en la página de inicio del controlador PHP.

Los bloqueos recurrentes indican un problema de diseño. Captura el gráfico de bloqueo y analiza qué sentencias y tipos de bloqueo están implicados. Las soluciones comunes incluyen reordenar operaciones para que las transacciones competidoras adquieran bloqueos en la misma secuencia, reducir el alcance de la transacción y añadir índices para disminuir la duración del bloqueo. Para una guía completa, consulta la guía de Deadlocks.

Problemas de resiliencia de conexión

No se reconecta

Síntomas:

Una conexión inactiva permanece rota tras un conmutador por error de Azure SQL Database, aunque se active ConnectRetryCount y ConnectRetryInterval.

Posibles causas y soluciones:

  • Cursor activo en el lado del servidor. La resiliencia de las conexiones inactivas solo reconecta conexiones inactivas . Un cursor abierto en el lado del servidor o una transacción pendiente mantiene la conexión activa. Liberar cursores del lado del servidor usando sqlsrv_free_stmt() o $stmt = null; (PDO) antes de la ventana de conmutación por error, o cambiar a un cursor búfer en el lado del cliente. Consulta resiliencia a la conexión en reposo.
  • Estado de sesión no recuperable. Algunos estados de sesión no pueden restablecerse, incluyendo tablas temporales, cursores globales y locales, contexto de transacción, bloqueos de aplicación, EXECUTE AS/REVERTmanejadores de automatización OLE, manejadores XML preparados y flags de trazo. Cualquiera de estos estados de sesión impide la reconexión automática.
  • LoginTimeout Demasiado pequeña. Si ConnectRetryCount * ConnectRetryInterval > LoginTimeout, el conductor deja de intentarlo de nuevo cuando LoginTimeout se alcanza. Sube LoginTimeout para cubrir todo el presupuesto de reintentos.

Problemas de rendimiento

Para el diagnóstico y la remediación de consultas lentas, arranques en frío, grandes conjuntos de resultados e insertos a granel, véase Ajuste de rendimiento.

Habilitar diagnósticos de controladores

Cuando las llamadas a nivel error_log() de aplicación no proporcionan suficiente información, activa el registro por parte del conductor. Informa de cada llamada ODBC que hace el conductor.

PDO_SQLSRV

Instala pdo_sqlsrv.log_severityphp.ini y reinicia el servidor web. Esta configuración solo es legible al inicializar:

[pdo_sqlsrv]
pdo_sqlsrv.log_severity = 1

Los valores son 0 (desactivado, el predeterminado), -1 (errores, advertencias y avisos), 1 (errores), 2 (advertencias) y 4 (avisos).

SQLSRV

Activar el registro en tiempo de ejecución con 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);

Las entradas de registro van al archivo configurado por error_log en php.ini. Para la lista completa de subsistemas y severidades, véase Actividad de registro.

Problemas de contenedores y CI

Bibliotecas del sistema ausentes en Linux

Síntomas:

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

Corrección:

Instala las dependencias de ejecución antes de instalar el controlador PHP:

Distribution Comando Install
Ubuntu y Debian sudo apt-get install unixodbc libgssapi-krb5-2
Red Hat y Fedora sudo dnf install unixODBC krb5-libs
Alpino apk add unixodbc gcompat

Luego instala msodbcsql18 desde el repositorio de paquetes de Microsoft. Para repositorios y versiones de paquetes específicos de distribución, consulte la guía de instalación de controladores ODBC.

Las compilaciones de imágenes Docker tienen éxito, pero las conexiones fallan en tiempo de ejecución

Síntomas:

La imagen se construye y PHP arranca, pero PDO::__construct() muestra un error ODBC de driver-in-found.

Corrección:

Verifica que el controlador ODBC esté instalado en la imagen de tiempo de ejecución, no solo en la fase de compilación. Instala msodbcsql18 y unixodbc-dev en la misma fase que se envía a producción. En una construcción de varias etapas, instálalos en la fase final. Una instalación basada en Debian de una sola etapa se ve así:

# 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/*