Toto chování je reprodukovatelné s aktuálním PHP (5.6.13) a dotaz není ani odeslán na server.
Váš případ je popsán v dokumentu jako:
Očekává se 0 hodnota, je zadána hodnota 1 a příkaz selže, false
vracení. Zatím funguje tak, jak je zdokumentováno.
Můžete namítnout, že „je generována chyba " by znamenalo, že když ERRMODE_EXCEPTION
je zapnutá, bude vyvolána výjimka. To je argument, ale není zřejmé, že by s ním vývojáři PDO souhlasili.
Aktualizace:
Proč je SQLCode
není nastaveno?
Podívejte se na zdrojový kód PDO, konkrétně static PHP_METHOD(PDOStatement, execute)
který zpracovává PDO::execute(), můžete vidět, že všechny chyby zpracovává 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); }
Jde o to, že při předávání vázaného parametru, když PDO neočekává žádné, se dotaz nikdy nedostane k enginu SQL, takže stroj SQL nikdy nemá příležitost ohlásit chybu spolu s SQLSTATE
PDO samo o sobě nevytváří falešný SQLSTATE
sám o sobě, alespoň ne v tomto případě, takžestmt->error_code
zůstává na PDO_ERR_NONE
což je "00000"
.
Je pochopitelné, že byste preferovali vznesení výjimky, ale pak byste měli navrhnout, aby https://bugs.php. síť
Je to stejné s MySQL?
Ano, kořenové chování je stejné až na to, že s ovladačem MySQL prepare
je okamžitě odeslána do SQL motoru, takže pokud je nesprávná kvůli špatnému sloupci, selže dříve a se skutečnou chybou SQL. Na druhou stranu má ovladač PgSQL jinou implementaci, díky které odkládá prepare
na straně serveru . Toto konkrétní chování je podrobně diskutováno na stránce PHP Postgres PDO ovladač nepodporuje připravené prohlášení?
Každopádně zde je případ s MySQL, který demonstruje mé vysvětlení, tedy:
- dotaz očekává parametr 0, je uvedena 1
$stmt->execute
vrací false- nebude vznesena žádná výjimka
- PDO::errorCode je
00000
Kód:
$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();
}
Výsledek:
Co se děje pod kapotou, je to, že se prepare
je odeslána na server a uspěje, ale execute
krok je zrušen PDO z důvodu neshody v parametrech.
Zde je případ, který se liší tím, že dotaz odkazuje na neexistující sloupec. Přidávám tisk, abych ukázal, že $stmt->execute
se ani nezavolá, protože výjimku vyvolá $stmt->prepare
Kód:
$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();
}
Výsledek:
Všimněte si, že krok „Provádění dotazu“ nikdy nenastane, protože je to prepare
který selže na straně serveru.
Závěr
-
když je dotaz odeslán na server, ať už je to v Prepare() nebo execute(), a je to server, který generuje chybu, pak můžeme očekávat vyvolání výjimky PDOException.
-
když dotaz není odeslán na server pro provedení kroku, pak PDO execute() může selhat (vrací hodnotu false), ale není vyvolána žádná výjimka a
errorCode()
zůstane na00000