if have a piece of code that is to hard for me to solve.. And i don't know how i can find the error more than this.
while($this->_pathLus != $this->hoofdMap) { //loop works fine, tested and confirmd
echo $this->_pathLus . 0; //$this->_pathLus = <data4>
if ($stmtToegang = $db->prepare("SELECT <data>, <data2> FROM `<data3>` WHERE <data> = ? LIMIT 5")) {
$stmtToegang->bind_param("s",$this->_pathLus);
$stmtToegang->execute();
$stmtToegang->bind_result($<data>, $<data2>);
while ($stmtToegang->fetch()) {
echo $<data> . 1;
echo $stmtToegang->error . 2;
}
} else { //to be sure if-stmt-prep is FALSE
echo $stmtToegang->error . 3;
}
$this->_pathLus = preg_replace("/(.*)\/(.*)\/(.*)\//", "$1/$2/", $this->_pathLus); // part of Loop and works
}
What i did to find solution:
check if $stmtToegang is correct everywhere
check if the sql-select is correct
Check if _pathLus is correct
add else on if-stmt-prep to make sure is failed
Results:
<data4>03<data4>03<data4>03<data4>03<data4>03
<data4>03<data4>03<data4>03
<data4>03<data4>03<data4>03<data4>03
<data4>03<data4>03
<data4>03
<data4>03<data4>03
Note: <data>, <data2>, <data3> are replacements for this example
Thanks in advance
Edit: Correction
Edit:
mysqli_prepare() returns a statement object or FALSE if an error
occurred.
But how get the error that Happens ?
How i did find the problem:
i altered echo $stmtToegang->error . 3; into echo $db->error . 3;
This way i found the following error:
Commands out of sync; you can't run this command now
Where i found a solution:
Answer here on SO
Problems was that this stmt-query (select type) was a part of another stmt-query (select type) because:
mysqli uses unbuffered queries by default (for prepared statements;)
So my code to debug a nested prepared statement (select-type) is as followed :
if($stmt = $mysqli->prepare($sql)) {
<$stmt->bind_param()->execute()->bind_result() code>
$stmt->store_result(); // store them !important
while ($stmt->fetch()) {
//code
if($stmt2 = $mysqli->prepare($sql)) {
<$stmt2->bind_param()->execute()->bind_result() code>
$stmt2->store_result(); // store them !important
while ($stmt2->fetch()) {
//code
}
$stmt2->free_result(); // free them
$stmt2->close(); // close them
echo $stmt2->error; // report error
} else {
echo $mysqli->error; // report error
}
}
$stmt->free_result(); // free them
$stmt->close(); // close them
echo $stmt->error; // report error
} else {
echo $mysqli->error; // report error
}
//edit: <$stmt->bind_param()->execute()->bind_result() code> for an better view
Hope it can help somone
Related
I need to show website visitor that something went wrong should him making queries to my database fails technically.
Want to get the php code to echo "Sorry! Something went wrong!" if for some reason data fetching failed.
Following are some ways I am trying to accomplish this.
3 samples.
They result in neverending loops thus crashing my browser.
(NOTE the IFs on each sample. That is where the 3 samples differ).
I ranked them according to favourite ....
How to fix this to bare minimum to achieve my purpose ? Would appreciate codes samples. I know how to achieve this with mysqli_stmt_get_result() but need to learn with the mysqli_stmt_bind_result() in procedural style programming. Not into oop yet. Nor pdo.
1.
<?php
//LOOPS NEVERENDING
$server = 'localhost';
$user = 'root';
$password = '';
$database = 'brute';
$conn = mysqli_connect("$server","$user","$password","$database");
$keywords = 'keyword';
$query = 'SELECT id,domain from links WHERE keywords = ?';
$stmt = mysqli_stmt_init($conn);
if(mysqli_stmt_prepare($stmt,$query))
{
mysqli_stmt_bind_param($stmt,'s',$keywords);
if(mysqli_stmt_execute($stmt))
{
while($result = mysqli_stmt_bind_result($stmt,$id,$domain))
{
mysqli_stmt_fetch($stmt);
echo 'Id: ' .$id; echo '<br>';
echo 'Domain: ' .$domain; echo '<br>';
if(!$result)
{
echo 'Sorry! Something went wrong. Try again later.';
}
}
}
mysqli_stmt_close($stmt);
mysqli_close($conn);
}
?>
<?php
//LOOPS NEVERENDING
$server = 'localhost';
$user = 'root';
$password = '';
$database = 'brute';
$conn = mysqli_connect("$server","$user","$password","$database");
$keywords = 'keyword';
$query = 'SELECT id,domain from links WHERE keywords = ?';
$stmt = mysqli_stmt_init($conn);
if(mysqli_stmt_prepare($stmt,$query))
{
mysqli_stmt_bind_param($stmt,'s',$keywords);
mysqli_stmt_execute($stmt);
while(mysqli_stmt_bind_result($stmt,$id,$domain))
{
if(mysqli_stmt_fetch($stmt)) //If 'Rows Fetching' were successful.
{
echo 'Id: ' .$id; echo '<br>';
echo 'Domain: ' .$domain; echo '<br>';
}
else //If 'Rows Fetching' failed.
{
echo 'Sorry! Something went wrong. Try again later.';
}
}
mysqli_stmt_close($stmt);
mysqli_close($conn);
}
?>
<?php
//LOOPS NEVERENDING
$server = 'localhost';
$user = 'root';
$password = '';
$database = 'brute';
$conn = mysqli_connect("$server","$user","$password","$database");
$keywords = 'keyword';
$query = 'SELECT id,domain from links WHERE keywords = ?';
$stmt = mysqli_stmt_init($conn);
if(mysqli_stmt_prepare($stmt,$query))
{
mysqli_stmt_bind_param($stmt,'s',$keywords);
if(mysqli_stmt_execute($stmt)) //If 'Query Execution' was successful.
{
while(mysqli_stmt_bind_result($stmt,$id,$domain))
{
mysqli_stmt_fetch($stmt);
echo 'Id: ' .$id; echo '<br>';
echo 'Domain: ' .$domain; echo '<br>';
}
}
else //If 'Query Execution' failed.
{
echo 'Sorry! Something went wrong. Try again later.';
}
mysqli_stmt_close($stmt);
mysqli_close($conn);
}
?>
Basically, all of the approaches are wrong. If the query fails then there will be an error triggered automatically by PHP as long as you have error reporting enabled, see How to get the error message in MySQLi?. You should not be checking for it manually. Your code is way longer than it needs to be. Consider how it should be done properly:
<?php
$server = 'localhost';
$user = 'root';
$password = '';
$database = 'brute';
// enable error reporting
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$conn = mysqli_connect($server, $user, $password, $database);
mysqli_set_charset($conn, 'utf8mb4');
$keywords = 'keyword';
$query = 'SELECT id,domain from links WHERE keywords = ?';
$stmt = mysqli_prepare($conn, $query);
mysqli_stmt_bind_param($stmt, 's', $keywords);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $id, $domain);
// This loop will keep on going as long as fetch() returns true.
// It will return false when it reaches the end
while (mysqli_stmt_fetch($stmt)) {
echo 'Id: ' .$id;
echo '<br>';
echo 'Domain: ' .$domain;
echo '<br>';
}
When you enable mysqli error reporting, your code becomes much simpler. There's no need for any special message to the user. When a query fails then an error will be triggered just like any other PHP error and handled the same way. If you want you can then customize the error page, but that is a completely separate topic.
The loop on mysqli_stmt_fetch() is used to fetch the data from the server. The data will be read row by row, and when there are no more rows mysqli_stmt_fetch() will return false.
mysqli_stmt_bind_result() needs to be called only once. Its purpose is to provide variable placeholders into which the data will be populated.
Their is a mistake in your code that make your code loop forever. In such cases, a while loop in your code is one of the most common cause of this kind of problem.
When you are using any function you should consider to read the documentation of this function and check what kind of errors and what kind of results (returns) it can give you. Functions can throw errors, warning, Exceptions, or return error codes. Also dont underestimate examples on the PHP documentation of each function. It give you a good idea of how things works.
When you are calling a function it's generally good to check the result returned. I will not rewrite all the documentation here but here is an example for mysqli_stmt_bind_result :
https://www.php.net/manual/en/mysqli-stmt.bind-result.php
This part of the procedural example is important for you :
/* bind variables to prepared statement */
mysqli_stmt_bind_result($stmt, $col1, $col2);
/* fetch values */
while (mysqli_stmt_fetch($stmt)) {
printf("%s %s\n", $col1, $col2);
}
Here you can see how mysqli_stmt_bind_result and mysqli_stmt_fetch can be used together to loop through your results.
But this is not perfect for error checking.
The documentation of mysqli_stmt_bind_result says in section Return values :
Returns true on success or false on failure.
So in case of failure of this function you can check for errors this way :
if (!mysqli_stmt_bind_result($stmt, $id, $domain)) {
die("mysqli_stmt_bind_result has failed !"); // of course you can use something more sophisticated than dying...
}
In case of success, and the source of your infinite loop is here, it returns true. So doing while(mysqli_stmt_bind_result($stmt, $id, $domain)) is a mistake, first because you dont have to loop on this function (it's a job for mysqli_stmt_fetch), secondly because mysqli_stmt_bind_result will ever returns true in your case and your while loop will never end.
For mysqli_stmt_fetch now, there is a subtle difference. Check the return values : https://www.php.net/manual/en/mysqli-stmt.fetch.php
Return Value
Description
true
Success. Data has been fetched
false
Error occurred
null
No more rows/data exists or data truncation occurred
Here you have to check for 3 different values and dont forget that null and false can both be evaluated as falsy if you dont take care.
This doesnt allow to display an error :
while (mysqli_stmt_fetch($stmt)) { // is result false or null ? we dont know
printf ("%s (%s)\n", $id, $domain);
}
This is more complete :
$fetchResult = null;
while ($fetchResult = mysqli_stmt_fetch($stmt)) {
printf ("%s (%s)\n", $id, $domain);
}
/* dont forget to use 3 equal signs to also compare variable type */
/* null == false values are considered the same */
/* null === false this also compare variable types, here types are not the same */
if ($fetchResult === false) {
die("mysqli_stmt_fetch failed !");
}
Now you are free to read the documentation of all called functions to do your errors checks.
Also note that another error management (less verbose and error prone) is possible using Exceptions objects like explained by Dharman answer
I just switched to PDO from mySQLi (from mySQL) and it's so far good and easy, especially regarding prepared statements
This is what I have for a select with prepared statement
Main DB file (included in all pages):
class DBi {
public static $conn;
// this I need to make the connection "global"
}
try {
DBi::$conn = new PDO("mysql:host=$dbhost;dbname=$dbname;charset=utf8", $dbuname, $dbpass);
DBi::$conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
DBi::$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
echo '<p class="error">Database error!</p>';
}
And in my page:
try {
$sql = 'SELECT pagetitle, pagecontent FROM mypages WHERE pageid = ? LIMIT 1';
$STH = DBi::$conn->prepare($sql);
$STH->execute(array($thispageid)); // $thispageid is from a GET var
}
catch(PDOException $e) {
echo '<p class="error">Database query error!</p>';
}
if ($STH) { // does this really need an if clause for it self?
$row = $STH->fetch();
if (!empty($row)) { // was there found a row with content?
echo '<h1>'.$row['pagetitle'].'</h1>
<p>'.$row['pagecontent'].'</p>';
}
}
It all works. But am I doing it right? Or can I make it more simple some places?
Is using if (!empty($row)) {} an ok solution to check if there was a result row with content? Can't find other decent way to check for numrows on a prepared narrowed select
catch(PDOException $e) {
echo '<p class="error">Database query error!</p>';
}
I would use the opportunity to log which database query error occurred.
See example here: http://php.net/manual/en/pdostatement.errorinfo.php
Also if you catch an error, you should probably return from the function or the script.
if ($STH) { // does this really need an if clause for it self?
If $STH isn't valid, then it should have generated an exception and been caught previously. And if you had returned from the function in that catch block, then you wouldn't get to this point in the code, so there's no need to test $STH for being non-null again. Just start fetching from it.
$row = $STH->fetch();
if (!empty($row)) { // was there found a row with content?
I would write it this way:
$found_one = false;
while ($row = $STH->fetch()) {
$found_one = true;
. . . do other stuff with data . . .
}
if (!$found_one) {
echo "Sorry! Nothing found. Here's some default info:";
. . . output default info here . . .
}
No need to test if it's empty, because if it were, the loop would exit.
For some reason, the while loop below never fires.
All of this is inside a class.
$code = $this->get_postal_state_no('Western Cape');
private function get_postal_state_no($psn)
{
$sql = "
SELECT
no
FROM
ct_state
WHERE
name LIKE('".$psn."');";
$stmt = sqlsrv_query($this->conn1, $sql);
// This statement is not false, so the error handling does not happen, this is expected.
if($stmt === FALSE)
{
if(($errors = sqlsrv_errors()) != NULL)
{
foreach($errors as $error)
{
$sqlstate = $error['SQLSTATE'];
$code = $error['code'];
$sqlmessage = $error['message'];
}
}
$msg = 'Error in $stmt in get_postal_state_no() method.';
$this->do_error_log($error_msg, $sqlstate, $code, $sqlmessage, $msg, __LINE__, __FILE__, __FUNCTION__, __CLASS__, __METHOD__);
sqlsrv_free_stmt($stmt);
}
//This loop is never entered. This is not expected.
while($obj = sqlsrv_fetch_object($stmt))
{
echo "I am here now";
break;
if(!empty($obj->no) && $obj->no != '')
{
echo "Hello, I exist";
break;
// This break never happens
return $obj->no;
}
else
{
echo "Hello, I don't exist";
break;
// This break never happens
$code = $this->sp_aa_iud_ct_state($psn);
return $code;
}
sqlsrv_free_stmt($stmt);
}
}
Does anyone have an idea why? I am using the php_sqlserv driver. The SQL server profiler shopws the query for the first part executing.
Thanks
J
Looking at the documentation page for sqlsrv_fetch_object it says this about the return value:
Returns an object on success, NULL if there are no more rows to return, and FALSE if an error occurs or if the specified class does not exist.
I suspect the function is either returning NULL or FALSE, though the reasons are a little unclear. Try adding this above the while loop and see what the output is:
$obj = sqlsrv_fetch_object($stmt)
var_dump($obj);
die;
while($obj = sqlsrv_fetch_object($stmt))
{ // ...
Another helpful debugging trick is to dump out the query and then copy/paste it into your DBMS system and run the query you are executing in code directly against your database to see if any results are actually being returned:
$sql = "
SELECT
no
FROM
ct_state
WHERE
name LIKE('".$psn."');";
var_dump($sql);
Database connecting is working. The SELECT AND UPDATE FUNCTION in the class is not working at all.It is not even showing errors to help me sort out the problem. I am trying to learn how to use the prepare ,bind-param and execute statement. Please can someone help look at the codes and advise what may be wrong with it. Just spent loads of hours on this and just cant figure where the problems is. please can some help me.I am a novice and writing my very first codes . Many thanks in advance
<?php class connect_dbase{
public $mysqli;
public function connection($host="localhost",$user="root",$password="london",$db_name="users")
{
$this->mysqli=new mysqli($host,$user,$password,$db_name);
if ($this->mysqli->connect_error) {
die('Connect Error: ' . $this->mysqli->connect_error);
}
else{
echo " Database connection successful";
}
}
public function display_all($id){
if($stmt = $this->mysqli->prepare("SELECT * FROM user WHERE id =?")){
/* bind parameters for markers */
$stmt->bind_param('i',$id);
/* execute query */
$stmt->execute();
if($stmt->num_row() >0){
echo 'Total results: ' . $resultrol->num_rows;
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['name'];
echo $row['email'];
echo $row['address'];}
}
else { echo "no result found";}
}
else
{
echo "cant prepare result";
}
}
public function update_post($name, $address,$email,$mob,$id)
{
$up="UPDATE user SET name=?, address =?,email=?,mobile=? WHERE id =?";
if($stmt=$mysqli->prepare($up))
{
$stmt->bind_param("sssii", $name, $address,$email,$mob,$id);
if($stmt->excute()) {
echo " post updated";
header('location:index.php');
}
else
{
echo "post not executed";
}
}else{ echo " cannot prepare statement";}
}
}
$connect_dbase=new connect_dbase();
$connect_dbase->connection();
$connect_dbase->display_all(2);
$connect_dbase-> update_post("john","kkkkk","kkk#yahoo.com",98765,2);
// These 2 functions- $connect_dbase->display_all(2); and
$connect_dbase-> update_post("john","kkkkk","kkk#yahoo.com",98765,2); are not working when called from the class above .
?>
I agree with #MikeBrant's comments. You should make the connection happen in the constructor if you want to be assured that the connection is successful before you try to call it.
Here's another tip:
if($stmt->num_row() >0){
Note that num_rows() doesn't return anything useful until after the client has fetched the rows. So calling it right after execute() is pretty much guaranteed to make it return the wrong number.
You need to use mysqli::store_result() to transfer the result set from the server to the client, and then num_rows() will work. But be careful if the result set is very large, it could use too much memory.
Taking into account the input from Mike and Bill I have modified your code to make it functional. It could use some more work but it should give you a starting point at the very least. I created a test database with three fields, id, name and email but you should be able to plug in your own database and fields and have it still work.
<?php
class connect_dbase {
public $mysqli;
public function connection($host="localhost",$user="root",$password="",$db_name="test")
{
$this->mysqli=new mysqli($host,$user,$password,$db_name);
if ($this->mysqli->connect_error) {
die('Connect Error: ' . $this->mysqli->connect_error);
} else {
// return a true value here if successful, that way you can check
// if your connection was established
return true;
}
}
public function display_all($id){
if($stmt = $this->mysqli->prepare("SELECT * FROM test WHERE id =?")) {
// some minor changes to the bind and execute statments. I
// wrapped them in an if just to make sure there were no errors
// if i had more time i might make these more elegant rather than just
// echoing them out
/* bind parameters for markers */
if(!($stmt->bind_param('i',$id))) {
echo $stmt->error;
}
/* execute query */
if(!($stmt->execute())) {
echo $stmt->error;
}
// You could also bind the results to specific variables here and return those
//$stmt->bind_result($id,$name,$email);
//$stmt->fetch();
//$result = $name;
//assign the results to a variable and then return that variable
//rather than processing the results here
$result = $stmt->get_result();
return $result;
} else {
// if an error occurs return the error, once again another place for
// improvement but at the very least will show you an error
echo $this->mysqli->error;
}
}
public function update_post($name, $email, $id)
{
$up="UPDATE test SET name=?, email=? WHERE id =?";
// originally had $mysqli->prepare($up), fixed syntax
if($stmt = $this->mysqli->prepare($up))
{
//$stmt->bind_param("sssii", $name, $address,$email,$mob,$id);
$stmt->bind_param("ssi", $name, $email,$id);
// execute was spelled wrong
if($stmt->execute()) {
return true;
} else {
return $stmt->error;
//return false;
}
} else {
return false;
}
}
}
// set up database connection
$connect_dbase = new connect_dbase();
if($connect_dbase->connection()) {
// if connection was successful, call display_all
// and assign the results to $result
$result = $connect_dbase->display_all(2);
// you could do a foreach here also but since there
// was only one result i just echoed the values
while($row = $result->fetch_array()) {
echo $row['id'] . "<br/>";
echo $row['name'] . "<br/>";
echo $row['email'] . "<br/>";
}
// then call update_post
$update_result = $connect_dbase->update_post("asdf","asdf#yahoo.com",2);
// show a message if the update_post was successful
if($update_result) {
echo "Update successful";
}
}
?>
I commented the areas I switched around so you have an idea of what I did.
Everything with it is fine. The name of the database and table, the name of the columns etc. $username is good and exists in the database. Yet, after this runs, if I "alert" $dbuid it comes up as 0 and $dbusername comes up as empty. MySQLi throws no errors. (That is why I did if(! .. ) echo error;, to see if it throws an error on anything, but it works perfectly fine.) Where am I going wrong ?
if(!$msmysqli = new mysqli("localhost","root","","ms")){
echo $msmysqli->connect_error;
}
if(!$stmt = $msmysqli->prepare("SELECT id,name,password FROM accounts WHERE name=?")){
echo $msmysqli->error;
}
if(!$stmt->bind_param("s",$username)){
echo $stmt->error;
}
if(!$stmt->execute()){
echo $stmt->error;
}
if(!$stmt->bind_result($dbuid,$dbusername,$dbpassword)){
echo $stmt->error;
}
$stmt->close();
You simply forgt to fetch your result to get the row... thats why your code wasn't working as expected! Another thing to bare in mind is that an object, at least in php, returns always its instance while being constructed! The statement $msmysqli = new mysqli(...) is never going to be false! thats why you should check your connection as shown!
$msmysqli = new mysqli("localhost","root","","ms");
if ( $msmysqli->connect_errno ) echo $msmysqli->connect_error;
if( $stmt = $msmysqli->prepare("SELECT id,name,password FROM accounts WHERE name=?") ) {
$stmt->bind_param("s",$username);
$stmt->execute();
$stmt->bind_result($dbuid,$dbusername,$dbpassword);
$stmt->fetch();
$stmt->close();
} else {
echo $msmysqli->error;
}
$msmysqli->close();