I open a connection to my database using php and mysqli and make a few queries using prepared statements where everything works dandy but in this query where I attempt to only select rides that are in the future I am inexplicably failing as soon as I add the comparison to GETDATE()
date_default_timezone_set('America/Denver');
if(!($stmt = $con->prepare("SELECT r.destination, r.startDepartureTime, r.seats, r.priceperseat FROM ride r WHERE r.startZipCode = ? AND r.startDepartureTime > GETDATE()"))) echo "Prepare failed: (" . $stmt->errno . ") " . $stmt->error;
if(!$stmt->bind_param("i", $userZipCode)) echo "Binding parameters failed: (" . $stmt->errno . ") " . $stmt->error;
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($destination,$departure,$seats,$price);
while($stmt->fetch()){
echo "Destination : $destination Departure Time : $departure Seats Available : $seats Price Per Seat : $price <br>";
}
$stmt->close();
The php error log reports that on the prepare statement line
PHP Notice: Trying to get property of non-object
and that therefore on the bind_param line we get
PHP Fatal error: Call to a member function bind_param() on a non-object
I originally was trying to use NOW() but tried all of the solutions in this thread SQL NOW() function not working properly and have had no luck.
When I run the statement without the r.startDepartureTime > GETDATE() comparison everything works fine.
And I have ensured that the startDepartureTime column in my database is of type datetime. Here is an example entry : 2016-05-21 10:24:00 that I've made sure is indeed greater than the current time and in the same zipcode to ensure that Im not just receiving an empty set.
GETDATE() is not a MYSQL Function, NOW() should be what you need
Maybe what you mean to do is use less than rather than greater than in the query r.startDepartureTime < NOW()
If the prepare fails then you need to do something more positive that just report an error. So this kind of code will work better.
Also if the prepare fails, $stmt is set to false and therefore using $stmt->errno etc will not work, and will in fact generate even more confusing error messages. So in this case you have to use the connection $con to get the errors from
$sql = "SELECT r.destination, r.startDepartureTime,
r.seats, r.priceperseat
FROM ride r
WHERE r.startZipCode = ?
AND r.startDepartureTime < NOW()";
$stmt = $con->prepare($sql);
if($stmt === false) {
echo "Prepare failed: {$con->errno} : {$con->error}";
exit;
}
Related
I'm relatively new to mysql/php rewind. I am execuring a query, and after I mark the current data set and re-wind it, I need to run the same set to run shell scripts that take a really long time. I'm going to run the same script as a cron in a few minutes, so I can mark another set and know I'm fetching a different data set to run the slow shell scripts on. For some reason, the rewind isn't working, so it's not using the data set twice:
if(!($stmt = $mysqli->prepare("SELECT node, model FROM Table WHERE vendor = 'Calix' AND model in ('C7','E7') AND ((update_status NOT in ('u') OR (update_time IS NULL) OR ((DATEDIFF(NOW(),SW_ver_update_time)>14)) )) LIMIT 100"))) //AND ping_reply IS NULL AND software_version IS NULL
{
echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}
if(!$stmt->bind_result($ip, $model))
{
echo "Binding results failed: (" . $stmt->errno . ") " . $stmt->error;
}
if(!$stmt->execute())
{
$tempErr = "Error select node, model c7,e7 status: " . $stmt->error;
printf($tempErr . "\n"); //show mysql execute error if exists
$err->logThis($tempErr);
}
$stmt1 = $mysqli1->prepare("UPDATE Table SET update_status = 'u' , update_time = UTC_TIMESTAMP() WHERE node = ?");
while($stmt->fetch()) {
print "current ip: " . $ip . "\n";
$stmt1->bind_param("s", $ip);
$stmt1->execute(); //write time stamp and 'u' on ones 'in process of Updating'
}
//rewind db pointer
mysql_data_seek($stmt, 0);
//Circulate through 100 dslams fetched that we marked as in process.
//This takes a long time to execuate and will be running this script concurrently in 5 minutes
//so we need to know what we're working on so we don't fetch them again.
while($stmt->fetch()) {
print "hello current ip: " . $ip . "\n";
//will execute shell script here
//I never see hello print statement
}
I looked at mysql_data_seek but I don't see an example that uses fetch(). Can I not use fetch() after a rewind? What's the issue here? Thanks!
*Update:
I tried
$stmt->data_seek(0);
But it's still not letting me re-use that query. If anyone has a suggestion of how to get rewind to work, or a way to get around it, like storing the query results so I can re-use them without re-running the query later, that's ok too.
You can't use mysql_data_seek() with mysqli functions. Each PHP extension for MySQL is separate, and you can't use the functions from one extension with query results from another extension.
You'd want to use the equivalent function in the mysqli extension: mysqli_stmt::data_seek().
Re your comments:
You can use get_result() and then call fetch_all() on the result. This will return an array of rows, in which each row is an array of columns returned by the MySQL query.
if(!($stmt = $mysqli->prepare("SELECT node, model FROM Table WHERE vendor = 'Calix' AND model in ('C7','E7') AND ((update_status NOT in ('u') OR (update_time IS NULL) OR ((DATEDIFF(NOW(),SW_ver_update_time)>14)) )) LIMIT 100"))) //AND ping_reply IS NULL AND software_version IS NULL
{
error_log("Prepare failed: ({$mysqli->errno}) {$mysqli->error}");
die();
}
if(!$stmt->execute())
{
error_log("Error select node, model c7,e7 status: {$stmt->error}");
die();
}
if (!($result = $stmt->get_result()))
{
error_log("Error get result of select node, model c7,e7: {$stmt->error}");
die();
}
$rows = $result->fetch_all(MYSQLI_ASSOC);
I also show use of error_log() which automatically logs to your http error log. If there's an error, I call die() so the code doesn't attempt to go on to the next step. In your script, you might structure it differently, like use return instead, if there's other code to run.
Or else you can fully embrace exceptions.
I've just learning to use prepared statement in mysqli & php. Here's the snippet of the code in question.
$stmt = $mysqli->prepare ("UPDATE courses set id=?, title=?, description=?, videourl=?, article=?, colcount=?, questiondisplayed=?, onfield=? WHERE id = ?");
if ($stmt == false) { die ('prepare() failed: ' . htmlspecialchars($mysqli->error)); }
$res = $stmt->bind_param("sssssiiis", $id, $title, $description2, $videourl, $article2, $colcount, $questiondisplayed, $onfield, $oldid);
if ($res == false) { die ('bind_param() failed: ' . htmlspecialchars($mysqli->error)); }
$res = $stmt->execute();
if ($res == false) die ('execute() failed: ' . htmlspecialchars($mysqli->error));
The problem is, even after these codes run successfully (the die function never gets called), the database is not updated at all. But it's updated successfully if I'm not using prepared statement (construct the SQL query string manually). I want to convert from using manually constructed SQL query string into prepared statement. But I'm stuck in this area. Btw, the variables supplied in bind param have been set right before these codes run. I've run a print_r ($_POST); and it shows that my POST values are contain the right data. Where's the problem? Thanks.
When I am running this query it is not returning any results. I believe there must be a syntax error as it is stopping the code from running later down the page. Anyway, I can't see where I am going wrong.
If nothing seems to be the problem with the syntax I can post my database structure, if necessary.
$tag = $_GET['tag'];
$stmt = $mysqli->prepare('SELECT trips.trip_id FROM tags JOIN trips ON trips.post_id = tags.post_id WHERE tag = ?');
$stmt->bind_param('s', $tag);
$stmt->execute();
$stmt->bind_result($trip_id); ?>
<div id="map_canvas<?php echo $trip_id ?>" style="height:400px;"></div><?php
Update: I have ran the error reporting script and this is what is comes out with...
Fatal error: Call to a member function bind_param() on a non-object in /Users/.../server/inc/feed-algorithm.php on line 37
Look at PHP manual http://php.net/manual/en/mysqli.quickstart.prepared-statements.php and set up your error statements properly. Your prepare statement should look like this:
if(!$stmt = $mysqli->prepare('SELECT trips.trip_id FROM tags JOIN trips ON trips.post_id = tags.post_id WHERE tag = ?')){
echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}
Of course, alternatively, throw and handle exceptions if you would like to be a little more elegant and keep your errors from users.
Also follow error checking in the Example 2 section. It appears your problem is going to be in the prepare statement though because if it was successful, it would not return a 'non-object'.
i need help with my function thet i build , i trying to use MYSQLI prepare but i am not so good .
this is my function :
function insertToDb($table,$rowsarray,$valuequestionmarks,$lenstrings,$valarray){
$this->mysqli->set_charset("utf8");
if ($insert_stmt = $this->mysqli->prepare(
"INSERT INTO $table ($rowsarray)
VALUES
($valuequestionmarks)"
))
{
$insert_stmt->bind_param("$lenstrings",$valarray);
// Execute the prepared query.
if(!$insert_stmt->execute())
{
die("Execute failed: (" . $insert_stmt->errno . ") " . $insert_stmt->error);
}
}
}
And this is how i call :
$img = "something.jpg";
$uip = ulUtils::GetRemoteIP(false);
$table='forgotpassqm';
$rowsarray = 'email,text,img,ip';
$valuequestionmarks ='?,?,?,?';
$lenstrings ='ssss';
$valarray ='$email,$text,$img,$uip';
$func->insertToDb($table,$rowsarray,$valuequestionmarks,$lenstrings,$valarray);
And i keep get this error :
Warning: mysqli_stmt::bind_param(): Number of elements in type definition string doesn't match number of bind variables
And the execute error :
Execute failed: (2031) No data supplied for parameters in prepared statement
i tryed allot of combination none work , i read other question none as my , and none worked or help either.
And i know this is about the ssss , but i using 4 and its seem to be alright so where i wrong here ?
Thanks allot.
EDIT :
$table output : forgotpassqm .
$rowsaray output: email,text,img,ip .
$valuequestionmarks output : ?,?,?,? .
$lenstrings output: ssss.
$valarray output: $email,$text,$img,$uip.
I think the problem is at $valarray.
Judging by the looks of it you are attempting to send a comma-delimited list of variables as an array (not how an array works) and you are using single quotes so variables aren't being interpolated to their values.
bind_param() expects a list of arguments after the type definitions. You aren't sending a list, you are sending the string '$email,$text,$img,$uip'.
Your call to that function should look like this:
$stmt->bind_param("ssss", $email, $text, $img, $uip);
According to the php manual you can retrieve errors in any prepared statement method by interrogating $stmt->error and $stmt->errno however the bind_param method never seems to set these on an error, can anyone else confirm this? or tell me what I am missing please?
For example:
echo "Start\n";
$db = new mysqli('localhost','test','xxxxxx','test');
$val = 1;
$st = $db->prepare('insert into tblTest set field1=?');
if($st == false)
{
printf("prepare: %s %d\n",$db->error,$st->errno);
}
$rs = $st->bind_param('is', $val);
if($rs == false)
{
printf("bind_param: %s %d\n",$st->error,$st->errno);
}
$rs = $st->execute();
if($rs == false)
{
printf("execute: %s %d\n",$st->error,$st->errno);
}
$rs = $st->close();
if($rs == false)
{
printf("close: %s %d\n",$st->error,$st->errno);
}
echo "Finish\n";
Running the above from the command line displays:
Start
PHP Warning: mysqli_stmt::bind_param(): Number of elements in type definition string doesn't match number of bind variables in test.php on line 14
bind_param: 0
execute: No data supplied for parameters in prepared statement 2031
Finish
So php is seeing this as a Warning, bind_param is returning false, but error & errno are not set. execute is also failing and has correctly set error & errno
Is this a bug?
MySQLi::error and MySQLi::errno are containers for error codes and messages returned by the RDBMS to PHP, not for errors encountered in the PHP code when setting up the statement. An incorrect call to bind_param() (with insufficient parameters) does apparently not communicate with the RDBMS, and thus won't receive its error from the RDBMS.
According to the docs, bind_param() returns a boolean FALSE on failure. So you will need to verify that it was called successfully.
$rs = $st->bind_param('is', $val);
if ($rs) {
$st->execute();
}