I'm writing an API class to query data. I have a function in the class that uses a SELECT
statement to query data for a specific, hardcoded table name (ie eventLog).
The query is listed below, where :value
references a paremeter passed to the function:
// query
$sql = "SELECT :selectType
FROM `log` :clause
ORDER BY `:orderByColumn` :orderByClause
LIMIT :limitStart, :limitStep";
I'm trying to use PDO statements to prevent SQL injection. I have read several helpful documents regarding how to correctly write PDO statements, including bindValue / bindParam.
Below is the full class file:
<?php
// set requirements
require_once 'Database.php';
/* EventLogsAPI class
* This class is used to query data from the eventLog table, and handle other data processing
*/
class EventLogsAPI {
// set class member variables
private $connection; // database connection
private $records; // records from query
/* Constructor function
*/
public function __construct() {
// create DB object
$this->connection = new DBConnection();
}
/* Collect records function
* Get the records from this prep statement, and store them in $this->records
*
* @param object - database object
*/
public function collectRecords($prep) {
// clear records from previous query
$this->records = array();
// execute query
$prep->execute();
// for each record
while (false !== ($row = $prep->fetch(PDO::FETCH_ASSOC))) {
$this->records[] = $row;
}
}
/* getEventLogData function
* Get event log data with a optional (where) clause
*
* @param string - select state (*, distinct, etc...)
* @param string - conditional SQL clause (e.g. where ID = 2)
* @param string - order by column (e.g. user, ID, date, etc...)
* @param string - order by clause (e.g. asc, desc)
* @param integer - starting limit param (i.e. 0)
* @param integer - limit step param (i.e. 25)
* @param boolean - used to debug SQL
* @return JSON - json containing array of records
*/
public function getEventLogData($selectType, $clause, $orderByColumn, $orderByClause, $limitStart, $limitStep) {
// query
$sql = "SELECT :selectType
FROM `log` :clause
ORDER BY `:orderByColumn` :orderByClause
LIMIT :limitStart, :limitStep";
// prep the query
$prep = $this->connection->DB('log')->prepare($sql);
// for each function argument
foreach ($bind = func_get_args() as $key => $value) {
// prevent null values
if ($value == NULL) {
// set to empty strings
$bind[$key] = "";
}
// bind value
$prep->bindValue(":$bind[$key]", $bind[$key]);
// debug
echo ($key . " - " . $value . "\n");
}
// collect the records
$this->collectRecords($prep);
// return records
return json_encode($this->records);
}
}
?>
Returned network response in Chrome console:
0 - *
1 -
2 - date
3 - DESC
4 - 0
5 - 20
<br />
<b>Warning</b>: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: parameter was not defined in <b>EventLogsAPI.class.php</b> on line <b>32</b><br />
[]
So, based on this execution, the bound SQL query should be:
// query
$sql = "SELECT *
FROM `log`
ORDER BY `date` DESC
LIMIT 0, 20";
However, I'm getting the error: Invalid parameter number: parameter was not defined
.
I have checked the following:
I know there are several other questions regarding this, but I have yet to find a solution to this problem. Any help with debugging is much appreciated. Thank you for reading.
Placeholders can represent VALUES only. You cannot use them for SQL keywords/identifiers.
FROM `eventLog` :clause
^--keyword/identifier
ORDER BY `:orderByColumn` :orderByClause
^--------------^--- also wrong
You also can NOT quote placeholders. Once they're quoted, they're not placeholders anymore, they're literal strings.
If you want to insert that kind of thing dynmamically, you have to build the query string yourself:
$order_by = 'ASC':
$sql = "SELECT ... ORDER BY $order_by";
And yes, this leaves you open to potential sql injection attacks . Placeholders are perfect for data, but they're utterly useless for many other kinds of queries.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.