Denne adfærd er reproducerbar med den aktuelle PHP (5.6.13), og forespørgslen sendes ikke engang til serveren.
Din sag er beskrevet i dokumentet som:
0 værdi forventes, 1 værdi er givet, og sætningen mislykkes, false
bliver returneret. Indtil videre fungerer det som dokumenteret.
Du kan hævde, at "en fejl udsendes " ville antyde, at når ERRMODE_EXCEPTION
er tændt, ville en undtagelse blive kastet. Det er et argument, men det er ikke indlysende, at PDO-udviklerne ville være enige i det.
Opdatering:
Hvorfor er SQLCode
ikke indstillet?
Ser på PDO-kildekoden, specifikt static PHP_METHOD(PDOStatement, execute)
der håndterer PDO::execute(), kan du se, at alle fejl håndteres af en makro: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); }
Pointen er, at når en bundet parameter sendes, når PDO forventede ingen, kommer forespørgslen aldrig til SQL-motoren, så SQL-motoren har aldrig mulighed for at rapportere en fejl ledsaget af en SQLSTATE
PDO i sig selv skaber ikke en falsk SQLSTATE
alene, i hvert fald ikke i det tilfælde, såstmt->error_code
bliver ved PDO_ERR_NONE
som er "00000"
.
Det er forståeligt, at du foretrækker, at der rejses en undtagelse, men så bør du foreslå det til https://bugs.php. net
Er det det samme med MySQL?
Ja, rodadfærden er den samme, bortset fra at med MySQL-driveren er prepare
sendes med det samme til SQL-motoren, så hvis den er forkert på grund af en dårlig kolonne, fejler den tidligere og med en rigtig SQL-fejl. På den anden side har PgSQL-driveren en anden implementering, der gør, at den udskyder prepare
på serversiden. . Denne særlige adfærd diskuteres i detaljer på PHP Postgres PDO-driver understøtter ikke forberedt erklæring?
Uanset hvad, her er en sag med MySQL, der demonstrerer min forklaring, det vil sige:
- forespørgslen forventer 0 parameter, 1 er givet
$stmt->execute
returnerer falsk- ingen undtagelse bliver rejst
- PDO::errorCode er
00000
Kode:
$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();
}
Resultat:
Det, der sker under emhætten, er, at prepare
sendes til serveren og lykkes, men execute
trin er annulleret af PDO på grund af uoverensstemmelse i parametre.
Her er et tilfælde, der adskiller sig ved, at forespørgslen refererer til en ikke-eksisterende kolonne. Jeg tilføjer en print for at vise, at $stmt->execute
kaldes ikke engang, da undtagelsen er rejst af $stmt->prepare
Kode:
$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();
}
Resultat:
Bemærk, hvordan trinnet "Udførelse af forespørgsel" aldrig sker, fordi det er prepare
der fejler, server-side.
Konklusion
-
når forespørgslen sendes til serveren, det være sig i prepare() eller execute(), og det er serveren, der genererer en fejl, så kan vi forvente, at en PDOException vil blive rejst.
-
når forespørgslen ikke sendes til serveren for et eksekveringstrin, så kan PDO execute() mislykkes (returnerer false), men der er ingen undtagelse, og
errorCode()
forbliver på00000