Това поведение може да се възпроизведе с текущия PHP (5.6.13) и заявката дори не се изпраща до сървъра.
Вашият случай е описан в документа като:
Очаква се стойност 0, дадена е стойност 1 и изразът е неуспешен, false
се връща. Досега работи както е документирано.
Може да възразите, че „емитирана е грешка " би означавало, че когато ERRMODE_EXCEPTION
е включено, ще бъде хвърлено изключение. Това е аргумент, но не е очевидно, че разработчиците на PDO биха се съгласили с него.
Актуализация:
Защо е SQLCode
не е зададено?
Разглеждане на изходния код на PDO, по-специално static PHP_METHOD(PDOStatement, execute)
който обработва PDO::execute(), можете да видите, че всички грешки се обработват от макрос: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); }
Въпросът е, че при предаване на обвързан параметър, когато PDO не очаква нищо, заявката никога не достига до SQL машината, така че SQL машината никога няма възможност да докладва грешка, придружена от SQLSTATE
Самото PDO не създава фалшив SQLSTATE
сама по себе си, поне не в този случай, така чеstmt->error_code
остава на PDO_ERR_NONE
което е "00000"
.
Разбираемо е, че бихте предпочели да бъде повдигнато изключение, но тогава трябва да предложите това на https://bugs.php. мрежа
Същото ли е и с MySQL?
Да, поведението на root е същото, с изключение на това, че с MySQL драйвера prepare
се изпраща незабавно до SQL двигателя, така че ако е неправилен поради лоша колона, той се проваля по-рано и с истинска SQL грешка. От друга страна, PgSQL драйверът има различна реализация, която го кара да отлага prepare
от страната на сървъра . Това конкретно поведение е обсъдено подробно в PHP Postgres PDO драйверът не поддържа подготвен оператор?
Както и да е, ето един случай с MySQL, който демонстрира моето обяснение, а именно:
- заявката очаква параметър 0, даден е 1
$stmt->execute
връща невярно- не се повдига изключение
- PDO::errorCode е
00000
Код:
$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();
}
Резултат:
Това, което се случва под капака е, че prepare
се изпраща до сървъра и е успешен, но execute
стъпката е отменена от PDO поради несъответствие в параметрите.
Ето един случай, който се различава по това, че заявката препраща към несъществуваща колона. Добавям разпечатка, за да покажа, че $stmt->execute
дори не се извиква, тъй като изключението се предизвиква от $stmt->prepare
Код:
$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();
}
Резултат:
Обърнете внимание, че стъпката „Изпълняваща заявка“ никога не се случва, защото това е prepare
това се проваля от страна на сървъра.
Заключение
-
когато заявката е изпратена до сървъра, било то в подготви() или изпълни(), и сървърът е този, който генерира грешка, тогава можем да очакваме да бъде повдигнато PDOException.
-
когато заявката не е изпратена до сървъра за стъпка на изпълнение, тогава PDO execute() може да се провали (връща false), но не се хвърля изключение и
errorCode()
остава на00000