Questo comportamento è riproducibile con l'attuale PHP (5.6.13) e la query non viene nemmeno inviata al server.
Il tuo caso è descritto in il documento come:
È previsto un valore 0, viene fornito un valore 1 e l'istruzione non riesce, false
essere restituito. Finora, funziona come documentato.
Potresti obiettare che "viene emesso un errore " implicherebbe che quando ERRMODE_EXCEPTION
è attivo, verrebbe generata un'eccezione. Questo è un argomento, ma non è ovvio che gli sviluppatori PDO sarebbero d'accordo con esso.
Aggiornamento:
Perché SQLCode
non è impostato?
Osservando il codice sorgente PDO, in particolare static PHP_METHOD(PDOStatement, execute)
che gestisce PDO::execute(), puoi vedere che tutti gli errori sono gestiti da 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); }
Il punto è che, quando si passa un parametro legato quando PDO non ne prevedeva nessuno, la query non arriva mai al motore SQL, quindi il motore SQL non ha mai l'opportunità di segnalare un errore accompagnato da un SQLSTATE
PDO stesso non crea un falso SQLSTATE
da solo, almeno no in quel caso, quindistmt->error_code
rimane a PDO_ERR_NONE
che è "00000"
.
È comprensibile che tu preferisca che venga sollevata un'eccezione, ma dovresti suggerirlo a https://bugs.php. netto
È lo stesso con MySQL?
Sì, il comportamento di root è lo stesso tranne che con il driver MySQL, il prepare
viene inviato immediatamente al motore SQL, quindi se non è corretto a causa di una colonna danneggiata, fallisce prima e con un vero errore SQL. D'altra parte, il driver PgSQL ha una diversa implementazione che fa rinviare la prepare
lato server . Questo comportamento particolare è discusso in dettaglio in Il driver PHP Postgres PDO non supporta l'istruzione preparata?
Ad ogni modo, ecco un caso con MySQL che dimostra la mia spiegazione, ovvero:
- la query prevede 0 parametro, viene fornito 1
$stmt->execute
restituisce falso- nessuna eccezione viene sollevata
- PDO::errorCode è
00000
Codice:
$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();
}
Risultato:
Quello che succede sotto il cofano è che il prepare
viene inviato al server e riesce, ma execute
il passaggio viene annullato da PDO a causa della mancata corrispondenza dei parametri.
Ecco un caso che si differenzia per il fatto che la query fa riferimento a una colonna inesistente. Sto aggiungendo una stampa per mostrare che $stmt->execute
non viene nemmeno chiamato, poiché l'eccezione viene sollevata da $stmt->prepare
Codice:
$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();
}
Risultato:
Nota come il passaggio "Esecuzione della query" non si verifica mai, perché è il prepare
che non riesce, lato server.
Conclusione
-
quando la query viene inviata al server, sia in prepare() che in execute(), ed è il server che genera un errore, allora possiamo aspettarci che venga sollevata una PDOException.
-
quando la query non viene inviata al server per un passaggio di esecuzione, PDO execute() può fallire (restituisce false) ma non viene generata alcuna eccezione e
errorCode()
rimane a00000