Почему мой оператор PDO -> execute возвращает false? - PullRequest
3 голосов
/ 21 июня 2011

После почти бесконечных циклов тестирования различных аспектов этого я определил, что соединение PDO работает (я могу выполнить простой запрос и отобразить результаты), я определил, что оператор успешно готовится, и что значения являются обязательными. По какой-то причине инструкция не будет выполнена. Просто чтобы быть милым, я попытался удалить все связанные переменные и выполнить статический запрос, но это тоже не сработает.

Код:

$dbh = new PDO( "mysql:host=localhost;dbname=".$GLOBALS['data_name'], $GLOBALS['data_user'], $GLOBALS['data_pass'] );
$dbh->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);

$sth = $dbh->prepare( "SELECT * FROM :table WHERE :field = :value" );
if( $sth != false ) TCDebug( 'prepared' );
if( $sth->bindValue( ":table", $table ) ) TCDebug( "table true" );
if( $sth->bindValue( ":field", $field ) ) TCDebug( "field true" );
if( $sth->bindValue( ":value", $value ) ) TCDebug( "value true" );
$flag = $sth->execute();

if( $flag === true ) {
    TCDebug( 'flag = true' );
} else if( $flag === false ) {
    TCDebug( 'flag = false' );
}
$result = $sth->fetchAll();

foreach( $result as $c ) TCDebugArr( $c );
TCDebug( count( $result ) );
if( count( $result ) > 0 ) {
    return $result;
} else {
    return null;
}

Последовательно выводит отладочный текст «подготовленного», «таблицы истинного», «поля истинного», «значения истинного», «флага = ложного», который говорит мне, что подготовка и связывание работают, но при выполнении этого нет, $ result пуст и функция возвращает ноль.

Я, вероятно, упустил из виду нечто ужасно очевидное, и я полностью готов повесить голову в полном неловком позоре. Заранее спасибо ...

UPDATE

Ааа, конкатенация - мой друг сегодня. Рабочий код выглядит следующим образом:

$dbh = new PDO( "mysql:host=localhost;dbname=".$GLOBALS['data_name'], $GLOBALS['data_user'], $GLOBALS['data_pass'] );
$dbh->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);

$prepare_str = "SELECT * FROM ". $table ." WHERE ". $field ." = :value";

$sth = $dbh->prepare( $prepare_str );
if( $sth != false ) TCDebug( 'prepared' );
if( $sth->bindValue( ":value", $value ) ) TCDebug( "value true" );
$flag = $sth->execute();

if( $flag === true ) {
    TCDebug( 'flag = true' );
} else if( $flag === false ) {
    TCDebug( 'flag = false' );
}
$result = $sth->fetchAll();

foreach( $result as $c ) TCDebugArr( $c );
TCDebug( count( $result ) );
if( count( $result ) > 0 ) {
    return $result;
} else {
    return null;
}

В этом случае это безопасно, поскольку $table и $field генерируются системой и никоим образом не доступны через пользовательский ввод; выставляется только значение $.

Спасибо, StackOverflow! Ты мой самый любимый! :)

1 Ответ

8 голосов
/ 21 июня 2011

Если у вас есть параметризованный запрос, который выглядит следующим образом:

SELECT * FROM :table WHERE :field = :value

и вы подставляете значения для :table, :field и :value, вы получаете что-то подобное к следующему (на самом деле это чрезмерное упрощение, но иллюстрирует смысл):

SELECT * FROM 'sometable' WHERE 'somefield' = 'somevalue'

, потому что :table и :field получают ту же семантическую обработку, что и :value, т.е.они рассматриваются как строки.Как правило, вы не можете параметризовать имена таблиц и столбцов с помощью параметризованных запросов.Вам придется немного переосмыслить свой подход.Вы можете подумать о динамическом построении подготовленной строки оператора, чтобы части имени таблицы и столбца запроса были простыми объединениями, а не связывали их с PDO.Но вы должны быть очень осторожны при проверке / дезинфекции имен таблиц и столбцов, поскольку PDO не защитит вас от внедрения SQL на этом уровне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...