SQLSTATE[HY093]: недопустимый номер параметра: параметр не был определен (PDO)
Я знаю: это было сделано до смерти.
Но, поверьте мне, я довольно долго изучал, как это исправить. То, чего я пытаюсь добиться, - это оболочка базы данных MySQL PDO для использования с PDO, которую я могу просто включить в свой код. Моя главная проблема связана, в частности, с двумя функциями, а также с фактической привязкой параметров, которые я пытаюсь достичь. Причина, по которой я заявляю две функции в отличие от одной, заключается в том, что, несмотря на все мои усилия, я не смог определить, какая из них пытается решить проблему. У меня есть переменная var_dump
Эд подтвердил, что это не переменная, это что-то еще. Тем не менее, тот факт, что я получаю эту ошибку, означает, что с кодом что-то не так.
Выставка:fetch( $table, $columns, $whereArgs )
Цель этой функции - просто извлечь строку. Это достигается путем принятия таблицы строки для выборки вместе со всеми столбцами и выражениями where, которые необходимы для конкретного выполнения задачи. После того как параметры переданы, вызываются один или два цикла, которые динамически формируют запрос.
public function fetch( $table, $columns, $whereArgs )
{
if ( $whereArgs === NULL && $columns === NULL ) return false;
$select = "SELECT ";
$where = " WHERE ";
$iQuery = 0;
$sqlParams = array();
$columnCount = count( $columns ) - 1;
foreach( $whereArgs as $key => $value )
{
$paramKey = sprintf( ':%s', $key );
$where .= sprintf( "`%s`= %s", $key, $paramKey );
$sqlParams[ "{$paramKey}" ] = sprintf( "%s", $value );
if ( $iQuery <= $columnCount )
{
$select .= sprintf( '`%s`', $columns[ $iQuery ] );
$select .= ', ';
}
else
{
$select .= ' ';
}
++$iQuery;
}
if ( $iQuery <= $columnCount )
{
for( ; $iQuery < $columnCount; ++$iQuery )
{
if ( $iQuery < $columnCount )
{
$select .= sprintf( '`%s`', $columns[ $iQuery ] );
$select .= ', ';
}
else
{
$select .= ' ';
}
}
}
$select .= sprintf( "FROM `%s`", $table );
$query = $select . $where;
return $this->doQuery( $query, $sqlParams, TRUE, QueryType::Row );
}
Приложение Б:doQuery( $query, $sqlParams, $return = FALSE, $queryType = QueryType::None )
Эта функция относительно проста: все, что она делает, - это связывает значения и выполняет оператор, одновременно проверяя, какой тип возвращать (возвращаемые типы, которые являются 'row', 'column' или 'all', определяются учебный классQueryType
класс, который выходит за рамки этой проблемы), а затем возвращает то, о чем просят.
protected function doQuery( $query, $sqlParams, $return = FALSE, $queryType = QueryType::None )
{
$statement = $this->mConnection->prepare( $query );
foreach( $sqlParams as $param => $value )
{
$statement->bindValue( $param, $value );
}
$statement->execute( );
if ( $return )
{
switch( $queryType )
{
case QueryType::Row:
return $statement->fetch( );
case QueryType::Column:
return $statement->fetchColumn( );
case QueryType::All:
return $statement->fetchAll( );
case QueryType::None:
return $statement;
default:
return false;
}
}
}
Приложение C:test.php
Это просто небольшой тестовый скрипт, который я написал для проверки базы данных.
$database = new Database( 'evolve_admin' );
$res = $database->fetch(
'evol_users',
array( 'user.id', 'user.email', 'user.firstname' ),
array( 'user.email' => 'test1234@test.com' )
);
var_dump( $res );
Другие комментарии
Я узнал, что с моим кодом что-то не так, я просто растерялся относительно того, что именно это может быть. Что касается моих навыков отладки, я довольно много исследовал эту проблему, и кажется, что эта ошибка очень распространена. Моя главная цель - заставить эту оболочку работать, и если кто-то увидит какие-либо ошибки в самом коде (включая те, которые выходят за рамки данной проблемы, в частности), пожалуйста, дайте мне знать.
Всем, кто предлагает руку в этом: большое спасибо.
2 ответа
Я думаю, что вы подделываете там пробелы:
$where .= sprintf( "`%s`= %s", $key, $paramKey );
В следующий раз вы использовали $wher
переменная была, когда вы добавляете его к $select
один.
Если больше, то где где arg то где:
WHERE `%s`= %s`%s`= %s`%s`= %s`%s`= %s`%s`= %s
Вы не сделали ошибку с вашей мыслью поколения SELECT. Кстати, у вас есть два одинаковых цикла и тест для выбранного поколения if ( $iQuery <= $columnCount )
, Один в цикле где, а другой снаружи. Какая польза?
Редактировать: И, конечно, я забыл указать, почему у вас есть эта ужасная ошибка: это в
$sqlParams[ "{$paramKey}" ] = sprintf( "%s", $value );
Вы создаете таблицу, которая будет выглядеть так: array ( "{:akey}" => "avalue")
(я рассматривал значение как строку. Почему вы использовали фигурные скобки ({}), это полностью меняет имя ключа (должно быть :keyname
не {:keyname
}
Редактировать 2: Был в хорошем настроении, так что вот упрощенная версия вашего метода извлечения (не проверено, но должно работать нормально)
/*
* $whereArgs default value is an array, so you can call a select
* without an empty array supplied if you does not have some where clause arguments
* The separator is how the element will be binded alltogether in the where clause
*/
public function fetch( $table, $columns, $whereArgs = array(), $separator= 'AND' )
{
/* We return false, if the columns variable is not set, or is not an array,
* or (if it is an array) does not contain anything
* or the $whereArgs is not and array (it would mean something bad have been given)
*/
if ( false == isset($columns) || false == is_array($columns)
|| 0 == count($columns) || false == is_array($whereArgs) )
{
return false;
}
$select = "SELECT";
$from = " FROM `$table`";
$where = " WHERE ";
/* SELECT generation */
for ( $columIt = 0; $columIt < count($columns); $columIt++)
{
$select .= " " . $columns[$columIt];
// We check if we need to add a ','
if ( $columIt+1 < count($columns) )
{
$select .= ",";
}
}
/* WHERE clause generation */
$sqlParams = array();
$whereIt = 0;
foreach( $whereArgs as $key => $value )
{
$stripedKey = preg_replace('/\\./', '_', $key);
$where .= " $key= :$stripedKey";
$sqlParams[ ":$stripedKey" ] = "$value";
// We check if we need to add a where separator
if ( $whereIt +1 < count($whereArgs ) )
{
$select .= " $separator";
}
$whereIt++;
}
/* the generated where clause is only printed if $whereArgs
* is not an empty array
*/
$query = $select . $from . ((0<count($whereArgs))?$where:"");
return $this->doQuery( $query, $sqlParams, TRUE, QueryType::Row );
}
Изменить 3: BTW не видел ваш тестовый образец, но имя параметра не может содержать "." голец
Изменить 4: не видел, как вы решили это, я добавил pre_replace вместо "." в вашем подмножестве. Также избавьтесь от символа `` 'при отображении ключа, иначе запрос не будет выполнен
`user.email`=:arg
Не понравилось =)
user.email=:arg or user.`email`=:arg
Prefered (`) используется для включения специального символа в имя столбца, поэтому, как и раньше, имя столбца не соответствует ни одному из существующих.
Изменить 5: вместо того, чтобы раздеть ключ, чтобы создать аргументы и массив аргументов. Вы можете использовать безопасный способ предотвращения появления вводящих в заблуждение символов, воспользовавшись счетчиком $whereIt:
$where .= " $key= :arg_$whereIt";
$sqlParams[ ":arg_$whereIt" ] = "$value";
С уважением
Проблема была в том, что в каждом столбце, который был у меня в моей тестовой базе данных, было "." между "пользователем" и именем столбца. Я решил проблему, просто заменив каждый период подчеркиванием, и это избавило от ошибки. Хотя по какой-то причине запрос все еще не работает, я уверен, что все будет хорошо.
Так, например:
user.email
знак равно user_email
,