PDO не выбрасывает исключение с несвязанными параметрами (и без переменных в запросе)
так что я понятия не имею, что здесь происходит
$link = new PDO('pgsql: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 s.*, d.invalid_column FROM students s ORDER BY s.student_id");
    $stmt->execute(array(1));
}
catch (PDOException $e) {
    print $e->getMessage();
}
когда я запускаю этот небольшой пример кода, я ожидаю, что будет создано исключение (как d.invalid_column не является реальным столбцом, и я передаю параметры, которые не могут быть связаны), но единственное, что происходит, - это то, что execute возвращает false и ничего больше. Кроме того,$stmt->errorInfo() пусто, а код 00000 что затрудняет добавление правильного исключения за пределы чего-то супер общего с ничем другим для журналов помогите мне в отслеживании ошибок, когда некоторые конечные пользователи сообщают об ошибке. 
если я добавлю один'?"где-то к запросу брошено правильное выполнение (это d.invalid_column не является допустимым столбцом), даже если я добавляю больше параметров, которые ни к чему не привязываются. 
Итак, способы заставить этот запрос правильно ошибиться:
1) Избавиться от всех параметров
2) Добавить '? на запрос
это просто ошибка в PDO или что?
изменить: Установки, которые будут бросать исключение (недопустимый столбец):
    $stmt = $link->prepare("SELECT s.*, d.invalid_column, ? FROM students s ORDER BY s.student_id");
    $stmt->execute(array(1));
    $stmt = $link->prepare("SELECT s.*, d.invalid_column, ? FROM students s ORDER BY s.student_id");
    $stmt->execute(array(1,2,3));
    $stmt = $link->prepare("SELECT s.*, d.invalid_column, ? FROM students s ORDER BY s.student_id");
    $stmt->execute();
    $stmt = $link->prepare("SELECT s.*, d.invalid_column FROM students s ORDER BY s.student_id");
    $stmt->execute();
это только тогда, когда у меня нет ? в моем запросе и передать что-то execute() что вещи просто терпят неудачу молча и без объяснения от PDO.
1 ответов
это поведение воспроизводимо с текущим PHP (5.6.13), и запрос даже не отправляется на сервер.
ваш случай описан в док as:
вы не можете связать больше значений, чем указано; если существует больше ключей в input_parameters, чем в SQL, указанном в PDO:: prepare (), затем оператор завершится ошибкой, и будет выдана ошибка.
ожидается значение 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 не ожидал none, запрос никогда не попадает в SQL engine, поэтому SQL engine никогда не имеет возможности сообщить об ошибке, сопровождаемой SQLSTATE
PDO сам по себе не создает подделку SQLSTATE самостоятельно, по крайней мере, нет в этом случае, так чтоstmt->error_code остается PDO_ERR_NONE что это "00000".
это понятно, что вы предпочли бы исключение, но тогда вы должны предложить это https://bugs.php.net
то же самое с MySQL ?
да, поведение корня такое же, за исключением того, что с драйвером MySQL prepare отправляется немедленно в SQL engine, поэтому, если это неверно из-за плохого столбца, он терпит неудачу раньше и с реальной ошибкой SQL. С другой стороны, драйвер PgSQL имеет другая реализация, которая заставляет его отложить серверную сторону prepare. Это конкретное поведение подробно обсуждается в драйвер PHP Postgres PDO не поддерживает подготовленный оператор?
во всяком случае, вот случай с MySQL, который демонстрирует мое объяснение, то есть:
- запрос ожидает 0 параметр, 1 задается
 - 
$stmt->executeвозвращает false - никаких исключений не возникает
 - PDO:: код ошибки 
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();
}
результат:
ошибка запроса, errorCode=00000
что происходит под капотом, что 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();
}
результат:
A PDOException has occurredSQLSTATE[42S22]: столбец не найден: 1054 Неизвестный столбец "несуществующий" в "списке полей"
обратите внимание, как шаг "выполнение запроса" никогда не происходит, потому что это prepare это не удается, на стороне сервера.
вывод
при отправке запроса сервер, будь то в prepare () или execute (), и это сервер, который генерирует ошибку, тогда мы можем ожидать, что будет вызвано исключение PDOException.
когда запрос не отправляется на сервер для выполнения шага, то PDO execute () может завершиться ошибкой (возвращает false), но исключение не создается и
errorCode()остается00000