PDO mysql error - php

I am currently working on a project for a client but because I am new to pdo I have no clue how to hand the error it keeps spitting out. The code I am working with is not mine either, so that adds a bit of confusion to the mix. It keeps telling me:
Query failed: 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 '' at line 1
I have narrowed down the error to these lines:
$regid = $dbh->lastInsertId('');
$dupsid = true;
while ($dupsid){
srand((double)microtime()*1000000);
$maxrand = 100000000;
$rand_sid = rand();
$check_sid = "select reguniqid from v_events_registrants where reguniqid = :RAND_SID";
$stmt = $dbh->prepare($check_sid);
$stmt->bindValue(':RAND_SID', $rand_sid);
$stmt->execute();
$num_result = $stmt->rowCount();
if ($num_result == 0) $dupsid = false;
}
$uniqid_upd = "update v_events_registrants set reguniqid = :RAND_SID where registrant_id = :REGID";
$stmt = $dbh->prepare($uniqid_upd);
$stmt->bindValue(':RAND_SID', $rand_sid);
$stmt->bindValue(':REGID', $regid);
$stmt->execute();
in this case here $reg is the primary key of the table in which the last few items were added. Initially I thought that was the issue but when I cleared it of ', and " I get an invalid id error, which I am guessing is from the next execution of the pdo. Please help as this error is really starting to hold me back from completing this project for my client.

Your first line defines $reg, then you try to use the undefined $regid

Nearly positive $regid is not defined, at least not within the scope of the code you included.
Trace that variable back or define at as something and you should be fixed.

Most likely your error lies somewhere else.
So, first of all get rid ov any try..catch blocks in your code
Then turn error reporting on
Then run your code again and find the real place where error occurs from the stack trace.
Then you get to erroneous query, write it this way
select
reguniqid
from
v_events_registrants
where
reguniqid
=
:RAND_SID
and watch the line number - it will help you locate the problem spot.

As your $rand_sid is of type integer, both times you use bindValue for $rand_sid you should add the datatype PDO::PARAM_INT (it takes PDO::PARAM_STR as default), like this:
$stmt->bindValue(':RAND_SID', $rand_sid, PDO::PARAM_INT);

Related

PDOException SQLSTATE[HY093] after upgrading to PHP 8.1

today I encounter an issue after upgrading from PHP 7.4 to PHP 8.1.
All the time I was using this code to establish an MySQL connection:
<?php
$kundencode=$_SESSION['kdnr'];
$i=0;
$q = $pdo->prepare("SELECT * FROM qi_rechnungen WHERE kdnr='$kundencode' ORDER BY rgnr DESC");
$q->execute([$_SESSION['id']]);
$res = $q->fetchAll();
foreach ($res as $row) {
$i++;
?>
This worked fine, but when using PHP 8.1 my system throws:
Fatal error: Uncaught PDOException: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in /home/clients-de/public_html/rechnungen2.php:60 Stack trace: #0 /home/clients-de/public_html/rechnungen2.php(60): PDOStatement->execute(Array) #1 {main} thrown in...
I can't see any mistake!?
What's the difference here between PHP 7.4 and 8.1?
Thank you for help...
The change that you encountered is that before PHP 8, PDO's error mode was set to silent by default. If it encountered any errors, it would just ignore them. This has now changed to the exception mode; every time an error is encountered, an exception will be thrown. So the issue was there before, it just remained unreported.
About the actual issue: you should really read up about prepared statements, they will make your code a lot safer. You're not providing any placeholders for prepared variables in your query, but you are passing them in the following line (which results in the exception):
$q->execute([$_SESSION['id']]);
As far as I see, the session ID is completely unnecessary for your query, but you could pass your customer number as a variable. The following should fix your issue:
$q = $pdo->prepare("SELECT * FROM qi_rechnungen WHERE kdnr=? ORDER BY rgnr DESC");
$q->execute([$kundencode]);
First of all, you shouldn't inline raw variables in query, use param binding.
Invalid parameter number: number of bound variables does not match number of tokens
This means that count of array passed into PDO::execute() method is different with count of params in query.
For your case, maybe this solution helps you:
// let's assume there is '5'
$kundencode=$_SESSION['kdnr'];
$q = $pdo->prepare("SELECT * FROM qi_rechnungen WHERE kdnr=:kundencode ORDER BY rgnr DESC");
// pass $kundencode into query
$q->bindValue('kundencode', $kundencode);
// SELECT * FROM qi_rechnungen WHERE kdnr='5' ORDER BY rgnr DESC
$q->execute();
If you want to pass $_SESSION['id'] into query, you must specify it in query template explicitly
#vixducis : That's exactly what I finally did yesterday - and got it to work as desired:
$q = $pdo->prepare("SELECT * FROM qi_domains WHERE kdnr = ? AND aktiv = ? ORDER BY id DESC");
$q->execute([$_SESSION['kdnr'], 0]);
So let me thank you all for your kind support!

Syntax error or access violation: 1064 ' brandname

I'm getting this error in my Magento script:
Product not added exception: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 's Secret'' at
line 1'
Some background info:
I have a PHP script running on a cron job to add and update products. It runs a while now, but I got just now this error. I think it's because the manufacturers name got an apostrophe in it. But I have no clue how to fix it.
Changing the manufacturer's name is not a option.
function addManufacture($pid,$men){
$resource = Mage::getSingleton('core/resource');
$readConnection = $resource->getConnection('core_read');
$query = "SELECT manufacturers_id FROM p1_manufacturers WHERE m_name='".$men."'";
$lastid = $readConnection->fetchOne($query);
$write = Mage::getSingleton("core/resource")->getConnection("core_write");
if($lastid){}else{
$url = createUrl($men);
$query = "insert into p1_manufacturers (m_name,identifier,status) values ('".$men."','".$url."',1)";
$write->query($query);
$lastid = $write->lastInsertId();
}
$query1 = "insert into p1_manufacturers_products (manufacturers_id,product_id) values ('".$lastid."','".$pid."')";
$write->query($query1);
$query3 = "SELECT manufacturers_id FROM p1_manufacturers_store WHERE manufacturers_id='".$lastid."'";
$mid = $readConnection->fetchOne($query3);
if($mid){} else {
$query2 = "insert into p1_manufacturers_store (manufacturers_id,store_id) values ('".$lastid."',0)";
$write->query($query2);
}
}
Here is the problem:
$query = "SELECT manufacturers_id FROM p1_manufacturers WHERE m_name='".$men."'";
Replace that with:
$menEscaped = mysql_real_escape_string($men);
$query = "SELECT manufacturers_id FROM p1_manufacturers WHERE m_name='".$menEscaped."'";
For readability, I might be inclined to reformat it thus:
$menEscaped = mysql_real_escape_string($men);
$query = "
SELECT
manufacturers_id
FROM
p1_manufacturers
WHERE
m_name='{$menEscaped}'
";
The problem is you are not escaping your input variables, and if this comes from user input, you may find people injecting SQL of their own choice into your database. And that's generally not good!
Addendum: the above may work, but I've just spotted you are using a library called Mage. This being the case, you will need to find out how to escape strings using that library - it will be something like $write->escapeString($men).
As has been noted in the comments, it is even better if you can switch to paramerisation. You'll need to check if your library supports that.
Your problem is being caused by an unescaped single-quote appearing in your data, and creating a syntax error in the queries you are submitting to your database.
Unfortunately, your database access code is hidden in some class, so it's not immediately obvious what changes are required. However...
As an absolute minimum you should escape any user data before applying it to the database. For this function this means
$men = mysql_real_escape_string($men);
$pid = mysql_real_escape_string($pid);
added at the top of the function. I have assume you are using 'mysql()` in this code.
Watch the line $url = createUrl($men); as this will be affected by this change. You may need further modifications here, and createUrl() may need to be changed too.
You will need to make similar changes in every function that accesses your database.
If you are using mysqli() more work will be required as the arguments are different and this 'easy' fix won't work.
Ultimately you should look to rewrite your code to use prepared statements.
Your code is seriously vulnerable to attack. There is a lot of work here. Get to it!
Edit
Thanks to #halfer for spotting the use of Mage. Magento uses the Zend framework which in turn uses PDO objects. Delving into the code you can rewrite the functions to use prepared statements which will deal with your problem effectively. This answer has a fuller description. This is a better fix than I suggested above, but you still have a great deal of work to do.

Getting a basic PDO statement to execute

I am attempting to get the following PDO statement to work and running into issues. When I am trying to get the number of rows, I keep getting 0, yet I know there should be 1 row. When I ran it as a mysqli statement( before trying to change it to PDO) it worked perfectly.
Here is the code:
require_once ('pdo.php');
$isbn = $_POST['isbn'];
// check to see if the isbn is a "problem" isbn or not
$problem = $conn->prepare("select isbn, note from problem where isbn = :isbn");
$problem->bindParam(":isbn", $isbn);
$problem->execute();
print_r($problem);
$num_rows = $problem->rowCount();
print_r($num_rows); die;
EDIT: Here is pdo.php:
<?php
function db_connect()
{
$db = new PDO("mysql:host=localhost; db=bookcell_BCOS_final", "xxxxx", "xxxxx");
return($db);
}
?>
I know that my connection works, but I get 0 for $num_rows. What mistakes am I making here?
Besides a little quirk and a optimalisation your code looks fine to me. The posted value isbn could be the reasong that you are getting no data:
$problem = $conn->prepare("select isbn, note from problem where isbn = :isbn");
$problem->bindParam(":isbn", $_POST['isbn'], PDO::PARAM_STR); // <-- thats what parameter binding is for
$problem->execute();
print_r($problem);
$num_rows = $problem->rowCount(); // <-- gives the number of rows, not columnCOunt
print_r($num_rows); die;
The Syntax for $num_rows = $problem->columnCount(); is totally correct. You may try,
$problem->execute(array("isbn" => $isbn));
instead of bindParam.
for getting the no. of rows, you need to use pdo::rowCount() -- manual here
In PDO to verfiy if your execute statement did work, check the return value (bool):
$success = $problem->execute();
if (!$success) {
$arr = $problem->errorInfo();
print_r($arr);
}
Also you might be looking for rowCount() instead of columnCount() but I think the error handling is your furthermost issue.
Additionally you can make PDO throw an exception each time an error appears, compare:
Switching from PHP's mysql extension to PDO. Extend class to reduce lines of code
How do I raise PDOException?
Depending on the database driver and the mode it's running, PDO may not be able to give you a row count. Look carefully at the documentation for PDOStatement::rowCount():
If the last SQL statement executed by the associated PDOStatement was a SELECT statement, some databases may return the number of rows returned by that statement. However, this behaviour is not guaranteed for all databases and should not be relied on for portable applications.
This is because in many cases the database uses a cursor rather than fetching the full results and buffering them (which is how the old mysql_* functions behave). In this case the database doesn't know how many rows there are until you have looked at all the rows. Think of a cursor as something like a filesystem pointer--you can't know the filesize until you seek to the end of the file.

Error with mysql_fetch_assoc [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
php warning mysql_fetch_assoc
i am just implementing a simple part of my website that just takes a variable from the header(subid) checks it with the database and then outputs the other fields related to the variable.
However i am getting this error -
Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource in /home/admin/public_html/report.php on line 14
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 ''/home/admin/public_html/log/log_274b43e6ad_New Text Document (7).txt.txt' at line 1
Here is the code for my page that does it all
include 'connect_to_mysql.php';
$sql_header = mysql_query("SELECT * FROM system");
$header_array = mysql_fetch_assoc($sql_header);
$total_scans = $header_array['total_scans'];
$malware_detected = $header_array['malware_detected'];
$total_users = $header_array['total_users'];
$report_id = $_GET['log'];
var_dump($report_id);
$sql_report = mysql_query("SELECT * FROM logs WHERE log_name='$report_id");
var_dump($sql_report);
$report_array = mysql_fetch_assoc($sql_report) or die(mysql_error());
$file_name = $report_array['file_name'];
$file_size = $report_array['file_size'];
$submission_date = $report_array['submission_date'];
$result = $report_array['result'];
$status = $report_array['status'];
Any ideas on what could be wrong? I have tried everything and checked my database, all the names are correct and everything, i even checked the $report_id variable in the database and it matches, so i am not sure why it is getting an error.
Thanks for the help
Your code it not doing any error checking, so it's no surprise the query breaks silently when it fails. Check for errors and it will tell you what is going wrong - how to do it is outlined in the manual on mysql_query() or in this reference question.. Example:
$sql_report = mysql_query("SELECT * FROM logs WHERE log_name='$report_id");
// Bail out on error
if (!$sql_report)
{
trigger_error("Database error: ".mysql_error(), E_USER_ERROR);
die();
}
In your specific case, you are missing a closing ' in
WHERE log_name='$report_id")
Also, the code you show is vulnerable to SQL injection. You need to escape every value you use like so:
$report_id = mysql_real_escape_string($_GET['log']);
for this to work, you need to put every value in your query into quotes.
You forgot a quote '$report_id' .
Here there are two things you have to notice :
1) the warning with mysql_fetch_assoc() .
This warning will occur when the argument passed to it is not an vaide mysql resource ,ie,
the mysql_connect() returned null object(failed to return conection object) . This inturn is caused due to fact that arguments passed to mysql_connect() are bad database credentials.
this case is usualy traped by using
is_resource($con)
call which returns true if $con is an valid resource.
2) The error as described in the error discription is due to bad syntax of query.
"SELECT * FROM logs WHERE log_name='$report_id"
here you ommited closing brace for $report_id
"SELECT * FROM logs WHERE log_name='$report_id'"
3) data base access :
An generel method of accesing database is by using an class , that access the database credentials through Accessor methods like setUname() , SetPasswd() etc , where the method itself will trim , escape and sanitize the credentials before it is passed to database.
this will prevent sql injection attack

MySQL query results are not a resource

I am having trouble with the query in this code. The problem is one I have had before, the $num = mysql_num_rows($result); part gives me a MySQL error saying it expected a resource. Usually when I have this error it is because I misplaced a single quote some where, but after looking I cannot find any problem, though this query is a bit more complex than what I usually have to deal with.
//connect to the database and stuff
$last_year = idate("Y")-1;
$month = date("m");
$day = date("d");
$query = "SELECT bills.b_id, bills.c_id, bills.grand_total, bills.void, bills.date_added,
customers.b_name, customers.l_name, customers.f_name, customers.phone
FROM bills, customers
WHERE bills.c_id = customers.c_id
AND bills.void = '0'
AND date_added BETWEEN '".$last_year."-".$month."-".$day."' AND CURDATE()";
$result = mysql_query($query);
mysql_close($link);
$num = mysql_num_rows($result);
EDIT:
Although I already know the mysql_close() function is not the problem I went ahead and removed it and my code still does not work. This EXACT same code (other than the query) works in nearly a dozen other pages. The problem is in the query, the MySQL error (as stated before) is mysql_num_rows() expects parameter 1 to be resource. I am working on getting the specific error now.
Add some error handling to your code.
$result = mysql_query($query);
if ( !$result ) {
echo 'the query failed: ', mysql_error();
die;
}
(in "real" production code you might not want to display the actual query and error message to just any arbitrary user though).
see also: http://docs.php.net/mysql_error
Check to see if there were mysql errors. If you don't already have error reporting turned on, turn it on for development (error_reporting(E_ALL);).
Try waiting to close your mysql connection until after you're done with the result sets.
Try with the mysql_close() function at the end. If you close the mysql connection, mysql_num_rows() is not going to work
$num = mysql_num_rows($result);
.
.
//Any others mysql operations
.
.
mysql_close($link);
You close link to mysql before retrieving query results. That's the problem. Just don't use mysql_close() as PHP can automatically handle it.
"not a resource" error means your query failed.
change your mysql_query call in that manner
$result = mysql_query($query) or trigger_error(mysql_error().$query);
and see what's wrong with your query.
always do it this way to keep in touch with every error may occur

Categories