PDO Can't bind two attributes - php

I'm trying to bind a search term and a limit value to a PDO execute query, but I get error messages no matter which way I do it
public static function searchUsersByName($searchTerm, $results = null) {
//getDBConnection
if($results == null) {
$results = 5;
}
$searchTerm = '%'.$searchTerm.'%';
$query = $database->prepare("SELECT user_id, user_firstname, user_lastname
FROM users_details
WHERE user_firstname LIKE :searchTerm
OR user_lastname LIKE :searchTerm
LIMIT :results");
$query->bindParam(':searchTerm', $searchTerm, PDO::PARAM_STR);
$query->bindParam(':results', $results, PDO::PARAM_INT);
$query->execute();
$search_results = array();
foreach ($query->fetchAll() as $user) {
$search_results[$user->user_id] = new stdClass();
$search_results[$user->user_id]->user_id = $user->user_id;
$search_results[$user->user_id]->user_firstname = $user->user_firstname;
$search_results[$user->user_id]->user_lastname = $user->user_lastname;
}
return $search_results;
}
This is the error I get from this:
PDOStatement::execute(): SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near "5"
It works fine if I take out the bind for LIMIT and just hardcode 5 into the SQL query, but I want to be able to change it if possible
$query->execute(array(':searchTerm' => '%'.$searchTerm.'%', ':results' => $results));
I've tried doing it this way, but of course PDO automatically puts quotes around the values its inserting via this method, and as far as I know you can't put a PDO::PARAM_INT in while using this method.
What am I doing wrong?

Could it be that $results is not an integer? The error seems like your PHP code is posting a string into the query, which would explain the error.
I am guessing this is the issue because of the following piece of code
if($results == null) {
$results = 5;
}
How is $results set in the first place? Via GET/POST? Then it might have been converted to a string.
I've tried your piece of code myself and casting it to an int fixed it for me.
$query->bindParam(':results', intval($results), PDO::PARAM_INT);

Related

Mistake in SQL syntax.. (bindValue?)

I am trying to create an update query and I am looping in some set stuff to a var called $str and I cant seem to get it to work.
if (is_numeric($id)) {
if (!empty($values) && !empty($table_name)) {
$str = '';
$sql = "UPDATE `$table_name` SET :update_values WHERE `$column_name` = :id";
// Its one because we dont use ID like that
$i = 1;
foreach ($values as $key => $value) {
if ($key != $column_name) {
// Exclude the last one from having a comma at the end
if ($i == count($values) - 1) {
$str .= "$key='" . $value . "'";
} else {
$str .= "$key='" . $value . "', ";
$i++;
}
}
}
$query = $this->dbh->prepare($sql);
$query->bindValue('update_values', $str, PDO::PARAM_STR);
$query->bindValue(':id', $id, PDO::PARAM_INT);
$query->execute();
return true;
} else {
return false;
}
} else{
return false;
}
}
Output:
Fatal error: Uncaught PDOException: SQLSTATE[42000]: Syntax error or
access violation: 1064 You have an error in your SQL syntax; check the
manual that corresponds to your MariaDB server version for the right
syntax to use near ''note_name=\'yeet\', note_date=\'2020-02-20\',
note_desc=\'asdasdasdasdadsasdads' at line 1
Am I making any obvious mistakes?
Also for the life of me I don't know what the backslashes in front of the values mean.
In MySQL, identifiers cannot be provided as values.
References to columns must appear in the text of the SQL statement, they cannot be provided through bind parameters. This holds true for table names, column names, function names.
There is no workaround; this is a by-design restriction. There's several reasons for this. One of the most straightforward reasons is understanding how a SQL statement gets prepared, the information that is needed to come up with an execution plan, the tables and columns have to be known at prepare time (for the semantic check and privilege check. The actual values can be deferred to execution time.
Bind placeholders are for providing values, not identifiers.
With the code given, what MySQL is seeing something along the lines of
UPDATE `mytable` SET 'a string value' WHERE `id_col` = 42
And MySQL is balking at the 'a string value'.
We can (and should) use bind parameters for values.
We could dynamically generate SQL text that looks like this:
UPDATE `mytable`
SET `col_one` = :val1
, `col_two` = :val2
WHERE `id_col` = :id
and after the SQL text is prepared into statement, we can bind values:
$sth->bindValue(':val1', $value_one , PDO::PARAM_STR );
$sth->bindValue(':val2', $value_two , PDO::PARAM_STR );
$sth->bindValue(':id' , $id , PDO::PARAM_INT );
and then execute

SQLSTATE[42000] when using bindParam

I'm trying to implement a backend RESTful API in PHP from this video https://www.youtube.com/watch?v=DHUxnUX7Y2Y.
$app->get('/api/customers/{id}', function (Request $request, Response $response) {
$id = $request->getAttribute('id');
$sql = "SELECT * FROM customers WHERE id = :id";
try {
// Get DB Object
$db = new db();
// Connect
$db = $db->connect();
$stmt = $db->query($sql);
$stmt->bindParam(':id', $id);
$customers = $stmt->fetch(PDO::FETCH_OBJ);
$db = null;
echo json_encode($customers);
} catch (PDOException $e) {
echo '{"error": {"text": '.$e->getMessage().'}';
}
});
when I want to use bindParam I always get an error:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':id' at line 1
The server uses MySql "Server Version: 5.6.36-log - Source distribution"
If this is using PDO, use a prepared statement instead of a query. This means calling prepare and execute rather than query.
I have updated your code below as an example:
$stmt = $db->prepare($sql);
$stmt->bindParam(':id', $id);
$stmt=>execute();
$customers = $stmt->fetch(PDO::FETCH_OBJ);
You may also want to consider using bindValue instead of bindParam to simplify your code in this case. bindParam evaluates the value of $id when the statement is executed by passing it by reference, which seems unnecessary if the id won't change, so bindValue may suffice.
Reference manual:
http://php.net/manual/en/pdo.prepared-statements.php

using form variables for mysql query

I'm trying to fetch a result from a mysql table using two form variables namely $sessionID and $semesterID. I used the following code and it seems to have an error in the sql syntax
<?php
...
mysql_select_db($database_connChePortal, $connChePortal);
$query_rsRegcourses =sprintf("SELECT * FROM VW_reg vwr WHERE vwr.sessionID=%s AND vwr.semesterID=%s",$sessionID,$semesterID);
$rsRegcourses = mysql_query($query_rsRegcourses, $connChePortal) or die(mysql_error());
$row_rsRegcourses = mysql_fetch_assoc($rsRegcourses);
$totalRows_rsRegcourses = mysql_num_rows($rsRegcourses);
print_r($query_rsRegcourses); die;
...
?>
I tried running the query and I have the following error report
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AND vwr.semesterID=' at line 1
thanks
I think you should surround your variable with single quotes '' please change as follow
"SELECT * FROM VW_reg vwr WHERE vwr.sessionID='%s' AND vwr.semesterID='%s'"
Put the %s in single quotes like this
"SELECT * FROM VW_reg vwr WHERE vwr.sessionID='%s' AND vwr.semesterID='%s'",$sessionID,$semesterID);
To insert a variable into query, you have to properly format it.
Two other answers contains improper formatting - so, you shouldn't follow them.
To make formatting more handy, you have to encapsulate sprintf() into function like this:
function paraQuery()
{
$args = func_get_args();
$query = array_shift($args);
$query = str_replace("%s","'%s'",$query);
foreach ($args as $key => $val)
{
$args[$key] = mysql_real_escape_string($val);
}
$query = vsprintf($query, $args);
$result = mysql_query($query);
if (!$result)
{
throw new Exception(mysql_error()." [$query]");
}
return $result;
}
which would apply proper formatting and also will handle errors
Also note that your way of counting records is extremely inefficient and may cause server to hang. You have to query the only data you need. So, if you need only count - request the count only
so, the code would be
mysql_select_db($database_connChePortal, $connChePortal);
$sql = "SELECT count(*) FROM VW_reg vwr WHERE vwr.sessionID=%s AND vwr.semesterID=%s";
$res = paraQuery($sql,$sessionID,$semesterID);
$row = mysql_fetch_row($res);
print_r($row[0]); die;
it will make your query properly formatted and thus invulnerable to SQL injection
also, it seems that $semesterID is not set which may cause some problem too

Why is this MySQL INSERT not working in CI?

For some reason this SQL statement is not working. Can anyone tell me why? (This is a Codeigniter site, if that matters)
Here is my Model (where my error is pointing me to)
public function edit_profile($ID, $field, $new_info)
{
$sql = "UPDATE users SET ?=? WHERE id=?";
$query = $this->db->query($sql, array($field, $new_info, $ID)); // <<<< LINE 42
return $query;
}
And this is the error I'm getting
Error Number: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''first_name'='oooo' WHERE id='151'' at line 1
UPDATE users SET 'first_name'='oooo' WHERE id='151'
Filename: /Applications/MAMP/htdocs/MY_SITE/models/member_model.php
Line Number: 42
My table is called 'users', and I have a 'first_name' and 'id' column.
Ideas?
EDIT
Just because it seems to come up a bit I want to clarify that the variables I am passing in here have NO QUOTES OR BACKTICKS. They are being added somewhere (and it seems like the ->query method, but I cant imagine that's true? .. dunno though, cause it's my first CI project)
Here is the controller that is passing to the model...
public function profileEdit()
{
$ID = $this->the_user->id;
$field = $this->input->post('edit_field')
$field = strstr($field,'_edit', true);
$new_info = $this->input->post('new_info');
$this->load->model('Member_model');
if( $this->Member_model->edit_profile( $ID, $field, $new_info )){
echo 'success';
}
else
{
echo 'error';
}
}
i suggest use like this :
public function edit_profile($ID, $field, $new_info)
{
$sql = "UPDATE users SET $field =? WHERE id=?"; # UPDATED (remove $this->db->escape())
$query = $this->db->query($sql, array($new_info, $ID)); // <<<< LINE 42
return $query;
}
if $field is not secured you can use escape functions .
EDIT :
$this->db->escape() will add quotes around variable so you will get an error again .

PHP PDO: how to return integer

I think it might be a flaw in my pdo fetching data method,
public function fetch_all($query, $params = array())
{
try
{
# prepare the query
$stmt = $this->connection->prepare($query);
# if $params is not an array, let's make it array with one value of former $params
if (!is_array($params)) $params = array($params);
# execute the query
$stmt->execute($params);
# return the result
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
catch (PDOException $e)
{
# call the get_error function
$this->get_error($e);
}
}
All the parameters that have been passed into this method will become strings, but I need integers for sql LIMIT query, such as below
$sql = "
SELECT *
FROM root_pages
ORDER BY root_pages.pg_created DESC
LIMIT ?,?";
items = $connection->fetch_all($sql,array('0','6'));
It returns this error,
2SQLSTATE[42000]: Syntax error or
access violation: 1064 You have an
error in your SQL syntax; check the
manual that corresponds to your MySQL
server version for the right syntax to
use near ''0','6'' at line 32
How can I fix it?
EDIT:
As suggested, I changed the code in my method to this below,
# fetch a multiple rows of result as a nested array ( = multi-dimensional array)
public function fetch_all($query, $params = array())
{
try
{
# prepare the query
$stmt = $this->connection->prepare($query);
# if $params is not an array, let's make it array with one value of former $params
//if (!is_array($params)) $params = array($params);
foreach($params as $k=>$p){
if(is_numeric($p)){
$stmt->bindParam($k+1, $p, PDO::PARAM_INT);
}
else{
$stmt->bindParam($k+1, $p, PDO::PARAM_STR);
}
}
$stmt->execute();
# execute the query
//$stmt->execute($params);
# return the result
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
catch (PDOException $e)
{
# call the get_error function
$this->get_error($e);
}
}
$items = $connection->fetch_all($sql,array(0,6));
then I get a different error,
2SQLSTATE[42000]: Syntax error or
access violation: 1064 You have an
error in your SQL syntax; check the
manual that corresponds to your MySQL
server version for the right syntax to
use near ''6'' at line 32
EDIT:
I just changed it to,
if(is_int($p)){..}
but still getting the same error... sigh...
you should pass your parameter with type PDO::PARAM_INT, like:
$sth->bindParam(':limit', $limit, PDO::PARAM_INT);
You can't do this via placeholders.
PDO always quotes params that aren't null, even when they're integers. Normally this isn't such a bad thing, but LIMIT clauses can not handle quoted integers.
You're going to need to fall back to good old fashioned concatenation. Because you know that these are going to be integers, you can treat them safely in your code by calling intval or casting them prior to concatenation.
$limit = intval($thing_that_provides_limit);
$offset = intval($thing_that_provides_offset);
$sql = "
SELECT *
FROM root_pages
ORDER BY root_pages.pg_created DESC
LIMIT {$offset}, {$limit}";
Try removing the quotes around the 0 and the 6:
$connection->fetch_all($sql,array(0,6));
This should make the query:
LIMIT 0,6
With quotes on the 0 and the 6, the query is:
LIMIT '0','6'
EDIT: Call bindParam before you call execute.
foreach($params as $k=>$p){
if(is_int($p)){
$stmt->bindParam($k+1, $p, PDO::PARAM_INT);
}
else{
$stmt->bindParam($k+1, $p, PDO::PARAM_STR);
}
}
$stmt->execute();
And then call fetch_all like so:
$connection->fetch_all($sql,array(0,6));
Try:
$items = $connection->fetch_all($sql,array(0,6));
Note the lack of quotes around the 0 and 6 - this makes PHP treat them as the integers they are, and not the strings you had.

Categories