Det beteendet är reproducerbart med nuvarande PHP (5.6.13), och frågan skickas inte ens till servern.
Ditt fall beskrivs i dokumentet som:
0 värde förväntas, 1 värde ges och satsen misslyckas, false
återlämnas. Hittills fungerar som dokumenterat.
Du kan hävda att "ett fel avges " skulle antyda att när ERRMODE_EXCEPTION
är på, skulle ett undantag kastas. Det är ett argument, men det är inte självklart att PDO-utvecklarna skulle hålla med om det.
Uppdatering:
Varför är SQLCode
inte inställt?
Tittar på PDO-källkoden, specifikt static PHP_METHOD(PDOStatement, execute)
som hanterar PDO::execute(), kan du se att alla fel hanteras av ett 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); }
Poängen är att när en bunden parameter skickas när PDO förväntade sig ingen, kommer frågan aldrig till SQL-motorn, så SQL-motorn har aldrig möjlighet att rapportera ett fel tillsammans med en SQLSTATE
PDO skapar inte i sig en falsk SQLSTATE
på egen hand, åtminstone inte i så fall, såstmt->error_code
stannar vid PDO_ERR_NONE
vilket är "00000"
.
Det är förståeligt att du föredrar att ett undantag tas upp, men då bör du föreslå det till https://bugs.php. nät
Är det samma sak med MySQL?
Ja, rotbeteendet är detsamma förutom att med MySQL-drivrutinen, prepare
skickas omedelbart till SQL-motorn så om den är felaktig på grund av en dålig kolumn, misslyckas den tidigare och med ett riktigt SQL-fel. Å andra sidan har PgSQL-drivrutinen en annan implementering som gör att den skjuter upp prepare
på serversidan . Detta specifika beteende diskuteras i detalj på PHP Postgres PDO-drivrutin stöder inte förberedda uttalanden?
Hur som helst, här är ett fall med MySQL som visar min förklaring, det vill säga:
- frågan förväntar sig 0 parameter, 1 ges
$stmt->execute
returnerar falskt- inga undantag tas upp
- PDO::errorCode är
00000
Kod:
$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 som händer under huven är att prepare
skickas till servern och lyckas, men execute
steget avbryts av PDO på grund av att parametrarna inte matchar.
Här är ett fall som skiljer sig i det faktum att frågan hänvisar till en icke-existerande kolumn. Jag lägger till en utskrift för att visa att $stmt->execute
anropas inte ens, eftersom undantaget höjs av $stmt->prepare
Kod:
$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:
Observera hur steget "Köra fråga" aldrig händer, eftersom det är prepare
som misslyckas på serversidan.
Slutsats
-
när frågan skickas till servern, oavsett om det är i prepare() eller execute(), och det är servern som genererar ett fel, då kan vi förvänta oss att ett PDOException kommer att höjas.
-
när frågan inte skickas till servern för ett exekveringssteg, då kan PDO execute() misslyckas (returerar false) men inget undantag kastas och
errorCode()
stannar på00000