Я знаю: это было сделано до смерти.
Но, поверьте, я довольно долго изучал, как это исправить. То, что я пытаюсь достичь, – это оболочка базы данных PDO MySQL для использования с PDO, которую я могу просто включить в свой код. Моя главная проблема связана, в частности, с двумя функциями, а также с фактической привязкой параметров, которые я пытаюсь достичь. Причина, по которой я заявляю две функции, а не одну, – несмотря на мои усилия, я не смог определить, кто пытается эту проблему. Я имею переменную var_dump
ed, которая подтвердила, что это не переменная, это что-то другое. Тем не менее, тот факт, что я получаю эту ошибку на первом месте, означает, что с кодом что- то должно быть не так.
Приложение A: fetch( $table, $columns, $whereArgs )
Цель этой функции – просто получить строку. Это достигается путем принятия таблицы строки для извлечения, а также любых столбцов и предложений where-clauses для выполнения конкретной задачи. Как только параметры были отправлены, вызывается одна или две петли, которые динамически формируют запрос.
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 ); }
Приложение B: doQuery( $query, $sqlParams, $return = FALSE, $queryType = QueryType::None )
Эта функция относительно проста: все, что она делает, – это значения привязки и выполнение оператора, а также оперативную проверку того, какой тип возвращается (типы возврата, которые являются либо «строка», «столбец», либо «все»), определяются class 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 );
Другие комментарии
Я узнал, что с моим кодом что-то не так, я просто потерял то, что именно может быть. Что касается моих навыков отладки, я изучил этот вопрос совсем немного, и кажется, что эта ошибка очень распространена. Моя главная цель – заставить эту оболочку работать, и если кто-нибудь увидит какие-либо ошибки внутри самого кода (в том числе те, которые не входят в объем этой проблемы в частности), сообщите мне.
Каждому, кто предлагает руку в этом: большое спасибо.
Я думаю, вы прогоняете некоторые места там:
$where .= sprintf( "`%s`= %s", $key, $paramKey );
В следующий раз, когда вы использовали переменную $wher
вы добавили ее в $select
.
Если больше того, где arg где:
WHERE `%s`= %s`%s`= %s`%s`= %s`%s`= %s`%s`= %s
Вы не сделали ошибку с мыслью о SELECT. Кстати, у вас есть две одинаковые петли и тесты для вашего поколения выбора, if ( $iQuery <= $columnCount )
. Один в петле где и снаружи. Какая польза?
Edit: И, конечно, я забыл указать, почему у вас эта ошибка:
$sqlParams[ "{$paramKey}" ] = sprintf( "%s", $value );
Вы создаете таблицу, которая будет выглядеть так: array ( "{:akey}" => "avalue")
(я считал значение как строку. Почему вы использовали фигурные скобки ({}), это полностью изменит имя ключа ( должно быть :keyname
not {: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 ); }
,/* * $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
Предпочтительный (`) используется для включения специального символа в имени столбца, поэтому, как и раньше, имя столбца не соответствует ни одному существующему.
Редактирование 5: Вместо того, чтобы удалять свой ключ, чтобы создать аргументы и массив аргументов. Вы можете безопасно использовать то, что предотвращает появление ошибочных халахов, используя опцию $ whereIt:
$where .= " $key= :arg_$whereIt"; $sqlParams[ ":arg_$whereIt" ] = "$value";
С уважением
Проблема была связана с тем, что каждый столбец, который я имел в своем тестовом db, имел «.». между «пользователем» и именем столбца. Я решил проблему, просто заменив каждый период знаком подчеркивания и избавился от этой ошибки. Хотя запрос по-прежнему не работает по какой-то причине, я уверен, что все будет хорошо.
Так, например:
user.email
= user_email
.