How to add variable values inside pdo->query - php

I want to upgrade my current code which is constantly sql injected with PDO.
Currently I'm stuck with using a variable inside a PDO query.
If I have two arguments like this
$rowsPerPage = 3;
// by default we show first page
$pageNum = 1;
if (isset($_GET['page'])) {
$pageNum = mysql_real_escape_string($_GET['page']);
}
$offset = ($pageNum - 1) * $rowsPerPage;
And I have query like this
$STH = $DBH->query("SELECT News.ID, LEFT(NewsText,650), Title, AID, Date, imgID," .
"DATE_FORMAT(Date, '%d.%m.%Y.') as formated_date " .
"FROM News, Categories, NewsCheck WHERE Name LIKE '%News - Block%' AND CID=Categories.ID AND JID=News.ID ".
"ORDER BY `Date` DESC LIMIT $offset, $rowsPerPage");
PDO reports an error in last line of the query ORDER BY
When I replace these line with
"ORDER BY Date DESC LIMIT3,3"); everything work.
So how to add variable values inside PDO::query ?
Updated:
Thanks to answer bellow I have updated my code like this
$STH = $DBH->prepare("SELECT News.ID, LEFT(NewsText,650), Title, AID, Date, imgID," .
"DATE_FORMAT(Date, '%d.%m.%Y.') as formated_date " .
"FROM News, Categories, NewsCheck WHERE Name LIKE '%News - Block%' AND CID=Categories.ID AND JID=News.ID ".
"ORDER BY `Date` DESC LIMIT :offset, :rowsPerPage;");
$STH->bindParam(':offset', $offset, PDO::PARAM_STR);
$STH->bindParam(':rowsPerPage', $rowsPerPage, PDO::PARAM_STR);
$STH->execute();
But error occured:
Fatal error: Uncaught exception 'PDOException' with message
'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 ''-3', '3'' at
line 1' in /pdo/test.php:42 Stack trace: #0
/pdo/test.php(42): PDOStatement->execute() #1 {main} thrown in
/pdo/test..
Second Update
Changed from PARAM_STR TO PARAM_INT like this
$STH->bindParam(':offset', $offset, PDO::PARAM_INT);
$STH->bindParam(':rowsPerPage', $rowsPerPage, PDO::PARAM_INT);
Everything works.

You want to use prepared statements and query parameters like the following:
$sth = $dbh->prepare('SELECT your_column FROM your_table WHERE column < :parameter');
$sth->bindParam(':parameter', $your_variable, PDO::PARAM_STR);
$sth->execute();
Using variables directly in your query will not protect you from SQL injections, even if you are using PDO. Parameters are the only good way to prevent them.

Related

Syntax error while executing a sql request with parameters in symfony?

I have a just simple problem I guess, I followed Symfony 4.3 documentation, and tried to do do exactly what they have done to execute a SQL request, but I get an error when passing parameters in the execute method, but I get no error while executing the same code but without passing parameters to the request.
I tried this and it worked:
$conn = $this->getDoctrine()->getManager()->getConnection();
$sql = '
SELECT * FROM question_comment WHERE question=2 LIMIT 0, 3';
$stmt = $conn->prepare($sql);
$stmt->execute();
var_dump($stmt->fetchAll());
But this does not work, I get a syntax error:
$question = $request->query->get('question');
$row = $request->query->get('row');
$question = intval($question);
$beggining = intval($row*3);
$conn = $this->getDoctrine()->getManager()->getConnection();
$sql = '
SELECT * FROM question_comment WHERE question=:question LIMIT :beggining , 3';
$stmt = $conn->prepare($sql);
$stmt->execute(['question' => $question, 'beggining' => $beggining]);
var_dump($stmt->fetchAll());
This is the error:
An exception occurred while executing ' SELECT * FROM question_comment
WHERE question= :question LIMIT :beggining , 3' with params [2, 0]:
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 ''0' , 3' at
line 1
Here is what I have followed, I did exactly what was there, but its not working.
I tried this solution to bind my parameters but it did not work too :
$sql = '
SELECT * FROM question_comment WHERE question=:question LIMIT :beggining , 3';
$stmt = $conn->prepare($sql);
$stmt->bindParam(':question', $question, \PDO::PARAM_INT);
$stmt->bindParam(':beginning', $beginning, \PDO::PARAM_INT);
$stmt->execute();
And I got this :
An exception occurred while executing ' SELECT * FROM question_comment
WHERE question=:question LIMIT :beggining , 3' with params [2, null]:
SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
alternative way to bind parameters is using this.
$stmt->bindParam(':question', $question, PDO::PARAM_STR);
$stmt->bindParam(':beginning', $beginning, PDO::PARAM_INT);
or to make it sure you binded the $beginning parameter, cast it to int.
$stmt->bindValue(':beginning', (int)trim($beginning), PDO::PARAM_INT);
or if you want to stick on your existing code.
$stmt->execute(['question' => $question, 'beggining' => (int)trim($beggining)]);

SELECT from and DELETE the same row in one query

At the moment, I have two queries. The first selects a column from a row. The second then deletes that row. As both queries deal with the same row, I was wondering if it was possible to execute both queries in one (to reduce the amount of code).
I had a look at SELECT then immediately DELETE mysql record and tried Whatever Kitchen's answer
This was my code beforehand (which works fine):
$stmt = $con->prepare("SELECT number FROM viewings WHERE username=:user");
$stmt->bindParam(':user', $user);
$stmt->execute();
$row = $stmt->fetch();
$result = $row['number'];
$stmt = $con->prepare("DELETE FROM viewings WHERE username=:user");
$stmt->bindParam(':user', $user);
$stmt->execute();
echo $result;
This was my code after trying the answer:
$stmt = $con->prepare("DELETE FROM viewings WHERE username=:user IN (SELECT number FROM viewings WHERE username=:user LIMIT 1)");
$stmt->bindParam(':user', $user);
$stmt->execute();
$row = $stmt->fetch();
$result = $row['number'];
echo $result;
However, I receive these errors:
Fatal error: Uncaught exception 'PDOException' with message
'SQLSTATE[42000]: Syntax error or access violation: 1235 This version
of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery''
in /home//public_html/page.php:47
Stack trace:
0 /home//public_html/page.php(47): PDOStatement->execute()
1 {main} thrown in /home//public_html/page.php on line 4
You can try using the EXISTS condition:
DELETE FROM viewings WHERE EXISTS (SELECT * FROM viewings WHERE username=:user LIMIT 1)
Source: SQL EXISTS condition

pdo pagination limit error

I have a pagination script and I am trying to change the mysql database into pdo database but I get this 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 'DESCLIMIT -2,2' at line 1
The part of code what gives me troubles is;
$limit = "LIMIT ".($page-1)*$perPage.",$perPage";
//$offset = ($page - 1) * $perPage;
$query = $db->prepare('SELECT image_id FROM images WHERE album_id= ? ORDER BY image_id DESC'.$limit);
$query->bindValue(1, $album_id);
//$query->bindParam(':limit', $limit, PDO::PARAM_INT);
try{
$query->execute();
}catch (PDOException $e){
die($e->getMessage());
}
I searched on google for solutions but my pdo knowledge is not good enough to use it right. I got errors like; SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens, because of $query->bindParam(':limit', $limit, PDO::PARAM_INT);
I don't know how to solve this, can anybody help me?
Thanks...
It seems mysql don't like negative offsets. You can make it this way
$limit = ($page-1)*$perPage;
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
$sql = 'SELECT image_id FROM images WHERE album_id=? ORDER BY image_id DESC LIMIT ?,?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$album_id,$limit,$perPage]);
$ids = $stmt->fetchAll(PDO::FETCH_COLUMN);
In the tutorial the first query was $count_query = $db->prepare('SELECT NULL FROM images where album_id= ?');
That worked in the tutorial but not here, I think that gave the negative value.
I changed this into $count_query = $db->prepare('SELECT * FROM images where album_id= ?');
and the error is gone. Other errors is showing up now, hopefully I can solve that.
Thanks for helping me solve this error.

PDO order by throws error

I am confused.
This is working:
$sql = 'SELECT * FROM TABLE ORDER BY DATEOFUPLOAD DESC';
$stmt = $conn->prepare($sql);
$stmt->execute();
This is not:
$sql = 'SELECT * FROM TABLE ORDER BY DATEOFUPLOAD :orderbydateofupload';
$stmt = $conn->prepare($sql);
$stmt->bindValue(':orderbydateofupload', $orderbydateofupload, PDO::PARAM_STR);
$stmt->execute();
I have checked and set $orderbydateofupload by $orderbydateofupload='DESC', so it's definitely not null.
I get an error to the last line ($stmt->execute()):
Fatal error: Uncaught exception 'PDOException' with message '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 ''DESC'' at line 1' in /home/gh6534/public_html/query.php:77 Stack trace: #0 /home/gh6534/public_html/query.php(77): PDOStatement->execute() #1 {main} thrown in /home/gh6534/public_html/query.php on line 77
I also tried to use the column as parameter:
$sort = 'DATEOFUPLOAD';
$sql = 'SELECT * FROM TABLE ORDER BY :sort :orderbydateofupload';
$stmt = $conn->prepare($sql);
$stmt->bindParam(':sort', $sort);
$stmt->bindParam(':orderbydateofupload', $orderbydateofupload);
$stmt->execute();
This does not throw an exception, but all items are queried without any sorting. What's wrong?
Try this
$orderbydateofupload = 'ASC'; //Or DESC
if($orderbydateofupload == 'DESC')
$sql = 'SELECT * FROM TABLE ORDER BY DATEOFUPLOAD DESC';
else
$sql = 'SELECT * FROM TABLE'
You can't bind identifiers with PDO because prepared statements can be used only with data, but not with identifiers or syntax keywords.
So, you have to use whitelisting, as shown in the example I posted before
That's why in my own class I use identifier placeholder, which makes whole code into one line (when you need to set the order by field only):
$data = $db->getAll('SELECT * FROM TABLE ORDER BY ?n',$sort);
but with keywords whitelisting is the only choice:
$order = $db->whiteList($_GET['order'],array('ASC','DESC'),'ASC');
$data = $db->getAll("SELECT * FROM table ORDER BY ?n ?p", $sort, $order);

Why is my PDO query using LIKE & LIMIT not working?

I am making a search box feature that has this query:
$query="SELECT * FROM article WHERE title LIKE ? OR description LIKE ?";
Then in a foreach loop, I make this array:
$params[]= "%".$keyword."%";
$params[]= "%".$keyword."%";
Then I execute:
$stmt=$cxn->prepare($query);
$stmt->execute($params);
This WORKS, but...
If, after the foreach loop, I want to add " LIMIT ?,?", I do this:
$query.=" LIMIT ?, ?";
$params[]=$row_number;
$params[]=$items_per_page;
Then I execute the script, and it throws this Fatal Error:
PHP Fatal error: Uncaught exception 'PDOException' with message
'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 ''0', '2'' at line 1' in ..../index.php:247
Stack trace:
#0 .../index.php(247): PDOStatement->execute(Array)
#1 {main}
thrown in ..../index.php on line 247
I tried to do add apostrophes around the keywords: $params= "'%".$keyword."%'";
But this didn't work.
Also, I tried the exact same query inside PHPMyAdmin and it worked.
Does anyone know why this is throwing an error?
Thanks a lot in advance.
Update:
$query="SELECT * FROM article WHERE title LIKE ? OR description LIKE ?";
$query.=" LIMIT ?, ?";
$stmt=$cxn->prepare($query);
$stmt->bindValue(1, "%".$keyword."%");
$stmt->bindValue(2, "%".$keyword."%");
$stmt->bindValue(3, $row_number, PDO::PARAM_INT);
$stmt->bindValue(4, $items_per_page, PDO::PARAM_INT);
$stmt->execute();
The reason LIKE isn't working, is because when you use bind parameters with LIKE it's treating '%value%' as a string.
You're going to have to use:
$query="SELECT * FROM article WHERE title LIKE CONCAT('%',?,'%') OR description LIKE CONCAT('%',?,'%')";
I think you need to convert the variable you have passed in your limit clause. see this ...to use near ''0', '2'' there are single quotes on the values in the LIMIT clause
try
$query.=" LIMIT ?, ?";
$params[] = intval($row_number);
$params[] = intval($items_per_page);

Categories