Dat gedrag is reproduceerbaar met de huidige PHP (5.6.13) en de query wordt niet eens naar de server gestuurd.
Uw geval wordt beschreven in het document als:
0 waarde wordt verwacht, 1 waarde wordt gegeven, en de instructie mislukt, false
wordt teruggestuurd. Werkt tot nu toe zoals gedocumenteerd.
Je zou kunnen beweren dat "er een fout is verzonden " zou impliceren dat wanneer ERRMODE_EXCEPTION
is ingeschakeld, zou er een uitzondering worden gegenereerd. Dat is een argument, maar het ligt niet voor de hand dat de PDO-ontwikkelaars het daarmee eens zijn.
Bijwerken:
Waarom is SQLCode
niet ingesteld?
Kijken naar de PDO-broncode, met name static PHP_METHOD(PDOStatement, execute)
die PDO::execute() afhandelt, kunt u zien dat alle fouten worden afgehandeld door een 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); }
Het punt is dat, wanneer een gebonden parameter wordt doorgegeven terwijl PDO er geen verwachtte, de query nooit de SQL-engine bereikt, dus de SQL-engine heeft nooit de mogelijkheid om een fout te rapporteren die vergezeld gaat van een SQLSTATE
PDO maakt zelf geen nep SQLSTATE
op zichzelf, althans niet in dat geval, dusstmt->error_code
blijft bij PDO_ERR_NONE
dat is "00000"
.
Het is begrijpelijk dat u er de voorkeur aan geeft dat er een uitzondering wordt gemaakt, maar dan moet u voorstellen aan https://bugs.php. netto
Is het hetzelfde met MySQL?
Ja, het rootgedrag is hetzelfde, behalve dat met het MySQL-stuurprogramma de prepare
wordt onmiddellijk naar de SQL-engine gestuurd, dus als het onjuist is vanwege een slechte kolom, mislukt het eerder en met een echte SQL-fout. Aan de andere kant heeft het PgSQL-stuurprogramma een andere implementatie waardoor het de server-side prepare
uitstelt . Dit specifieke gedrag wordt in detail besproken op PHP Postgres PDO-stuurprogramma ondersteunt geen voorbereide verklaring?
Hoe dan ook, hier is een geval met MySQL dat mijn uitleg demonstreert, namelijk:
- de query verwacht parameter 0, 1 wordt gegeven
$stmt->execute
geeft false terug- er wordt geen uitzondering gemaakt
- PDO::errorCode is
00000
Code:
$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();
}
Resultaat:
Wat er onder de motorkap gebeurt, is dat de prepare
wordt naar de server gestuurd en slaagt, maar de execute
stap is geannuleerd door PDO vanwege de mismatch in parameters.
Hier is een geval dat verschilt in het feit dat de query verwijst naar een niet-bestaande kolom. Ik voeg een afdruk toe om te laten zien dat $stmt->execute
wordt niet eens aangeroepen, omdat de uitzondering wordt gemaakt door $stmt->prepare
Code:
$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();
}
Resultaat:
Merk op dat de stap "query uitvoeren" nooit gebeurt, omdat het de prepare
is dat mislukt, server-side.
Conclusie
-
wanneer de query naar de server wordt verzonden, hetzij in prepare() of execute(), en het is de server die een fout genereert, dan kunnen we verwachten dat een PDOException wordt gegenereerd.
-
wanneer de query niet naar de server wordt verzonden voor een uitvoeringsstap, kan PDO execute() mislukken (retourneert false) maar er wordt geen uitzondering gegenereerd en
errorCode()
blijft bij00000