Ese comportamiento es reproducible con el PHP actual (5.6.13) y la consulta ni siquiera se envía al servidor.
Su caso se describe en el documento como:
Se espera un valor de 0, se da un valor de 1 y la declaración falla, false
siendo devuelto. Hasta ahora, funciona según lo documentado.
Puede argumentar que "se emite un error " implicaría que cuando ERRMODE_EXCEPTION
está activado, se lanzará una excepción. Ese es un argumento, pero no es obvio que los desarrolladores de PDO estarían de acuerdo con él.
Actualización:
¿Por qué SQLCode
no configurado?
Mirando el código fuente de PDO, específicamente static PHP_METHOD(PDOStatement, execute)
que maneja PDO::execute(), puede ver que todos los errores son manejados por una macro:PDO_HANDLE_STMT_ERR()
#define PDO_HANDLE_STMT_ERR() if (strcmp(stmt->error_code, PDO_ERR_NONE)) { pdo_handle_error(stmt->dbh, stmt TSRMLS_CC); }
El punto es que, al pasar un parámetro vinculado cuando PDO no esperaba ninguno, la consulta nunca llega al motor SQL, por lo que el motor SQL nunca tiene la oportunidad de informar un error acompañado de un SQLSTATE
PDO en sí mismo no crea un SQLSTATE
falso por sí solo, al menos no en ese caso, entonces stmt->error_code
permanece en PDO_ERR_NONE
que es "00000"
.
Es comprensible que prefiera que se genere una excepción, pero entonces debería sugerirlo a https://bugs.php. red
¿Es lo mismo con MySQL?
Sí, el comportamiento de root es el mismo excepto que con el controlador MySQL, el prepare
se envía inmediatamente al motor de SQL, por lo que si es incorrecto debido a una columna incorrecta, falla antes y con un error de SQL real. Por otro lado, el controlador PgSQL tiene una implementación diferente que lo hace aplazar el prepare
del lado del servidor . Este comportamiento particular se analiza en detalle en ¿El controlador PHP Postgres PDO no es compatible con declaraciones preparadas?
De todos modos, aquí hay un caso con MySQL que demuestra mi explicación, es decir:
- la consulta espera 0 parámetros, se da 1
$stmt->execute
devuelve falso- no se genera ninguna excepción
- PDO::errorCode es
00000
Código:
$link = new PDO('mysql:dbname=' . $name . ';host=' . $host, $user, $password);
$link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$stmt = $link->prepare("SELECT 1");
$rc=$stmt->execute(array(1));
if ($rc===false)
echo "query failed, errorCode=", $link->errorCode(), "\n";
else
echo "query succeeded, errorCode=", $link->errorCode(), "\n";
}
catch (PDOException $e) {
print "A PDOException has occurred";
print $e->getMessage();
}
Resultado:
Lo que sucede debajo del capó es que el prepare
se envía al servidor y tiene éxito, pero el execute
el paso es cancelado por PDO debido a la falta de coincidencia en los parámetros.
Aquí hay un caso que difiere en el hecho de que la consulta se refiere a una columna que no existe. Estoy agregando una impresión para mostrar que $stmt->execute
ni siquiera se llama, ya que la excepción la genera $stmt->prepare
Código:
$link = new PDO('mysql:dbname=' . $name . ';host=' . $host, $user, $password);
$link->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$stmt = $link->prepare("SELECT nonexisting");
echo "Executing query\n";
$rc=$stmt->execute(array(1));
if ($rc===false)
echo "query failed, errorCode=", $link->errorCode(), "\n";
else
echo "query succeeded, errorCode=", $link->errorCode(), "\n";
}
catch (PDOException $e) {
print "A PDOException has occurred";
print $e->getMessage();
}
Resultado:
Tenga en cuenta que el paso "Ejecutar consulta" nunca ocurre, porque es el prepare
eso falla, del lado del servidor.
Conclusión
-
cuando la consulta se envía al servidor, ya sea en preparar() o ejecutar(), y es el servidor el que genera un error, podemos esperar que se genere una excepción PDO.
-
cuando la consulta no se envía al servidor para un paso de ejecución, entonces la ejecución de PDO () puede fallar (devuelve falso) pero no se lanza ninguna excepción y
errorCode()
permanece en00000