To zachowanie można odtworzyć w bieżącym PHP (5.6.13), a zapytanie nie jest nawet wysyłane do serwera.
Twoja sprawa jest opisana w dokumentacji jako:
Oczekiwana jest wartość 0, podana jest 1 wartość, a instrukcja nie powiedzie się, false
zostanie zwrócony. Jak dotąd działa zgodnie z dokumentacją.
Możesz argumentować, że „wyświetlany jest błąd " oznaczałoby, że gdy ERRMODE_EXCEPTION
jest włączony, zostanie zgłoszony wyjątek. To argument, ale nie jest oczywiste, że twórcy PDO się z tym zgodzą.
Aktualizacja:
Dlaczego SQLCode
nie ustawiono?
Patrząc na kod źródłowy PDO, w szczególności static PHP_METHOD(PDOStatement, execute)
który obsługuje PDO::execute(), widać, że wszystkie błędy są obsługiwane przez 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); }
Chodzi o to, że podczas przekazywania powiązanego parametru, gdy PDO nie oczekiwało żadnego, zapytanie nigdy nie trafia do silnika SQL, więc silnik SQL nigdy nie ma możliwości zgłoszenia błędu wraz ze stanem SQLSTATE
Samo PDO nie tworzy fałszywego SQLSTATE
na własną rękę, przynajmniej nie w tym przypadku, więcstmt->error_code
zostaje w PDO_ERR_NONE
czyli "00000"
.
Zrozumiałe jest, że wolisz, aby został zgłoszony wyjątek, ale powinieneś zasugerować to https://bugs.php. sieć
Czy tak samo jest z MySQL?
Tak, zachowanie roota jest takie samo, z wyjątkiem sterownika MySQL, prepare
jest natychmiast wysyłana do silnika SQL, więc jeśli jest niepoprawna z powodu złej kolumny, kończy się wcześniej i z prawdziwym błędem SQL. Z drugiej strony sterownik PgSQL ma inną implementację, która sprawia, że odracza prepare
po stronie serwera . To szczególne zachowanie jest szczegółowo omówione w Sterownik PHP Postgres PDO nie obsługuje przygotowanego oświadczenia?
W każdym razie, oto przypadek z MySQL, który demonstruje moje wyjaśnienie, czyli:
- zapytanie oczekuje parametru 0, podano 1
$stmt->execute
zwraca fałsz- nie zgłasza się żadnego wyjątku
- PDO::errorCode to
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();
}
Wynik:
To, co dzieje się pod maską, polega na tym, że prepare
jest wysyłany na serwer i kończy się powodzeniem, ale execute
krok jest anulowany przez PDO z powodu niezgodności parametrów.
Oto przypadek, który różni się tym, że zapytanie odnosi się do nieistniejącej kolumny. Dodaję wydruk, aby pokazać, że $stmt->execute
nie jest nawet wywoływana, ponieważ wyjątek jest zgłaszany przez $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();
}
Wynik:
Zwróć uwagę, że krok „Wykonywanie zapytania” nigdy się nie dzieje, ponieważ jest to prepare
to się nie powiedzie, po stronie serwera.
Wniosek
-
kiedy zapytanie jest wysyłane do serwera, czy to w przygotowaniu(), czy w wykonywaniu(), i to serwer generuje błąd, możemy spodziewać się zgłoszenia wyjątku PDO.
-
gdy zapytanie nie jest wysyłane do serwera w celu wykonania kroku, wykonanie PDO() może zakończyć się niepowodzeniem (zwraca wartość false), ale nie zostanie zgłoszony żaden wyjątek i
errorCode()
zostaje w00000