mysqli::prepare(): Couldn't fetch MySQL [duplicate] - php

This question already has answers here:
mysqli::query(): Couldn't fetch mysqli
(4 answers)
Closed 9 months ago.
I started using mysqli_* functions instead of the old mysql_* functions in PHP, and I'm having a bit of a problem with this code:
public function addUser($table, $code = false, $rows = false) {
if (!$code) {
header("Location: " . $this->authenticate());
} else {
$this->getToken($code);
}
$user = $this->getEndpoint('users/current', false, true);
$user = $user->response->user;
if (!$rows)
$rows = array(
"remote_id" => $user->id,
"firstName" => $user->first_name,
"lastName" => $user->last_name,
"photo" => $user->photo->medium,
"gender" => $user->gender == 'male' ? 1 : 2,
"email" => $user->contact->email,
);
$rows['access_token'] = $this->accessToken;
$stmt = $this->mysql->prepare("SELECT id FROM users WHERE access_token = '{$this->accessToken}'"); //line 136
$stmt->execute(); //line 137
}
The code returns these 2 errors:
Warning: mysqli::prepare(): Couldn't fetch MySQL in C:\Users\Grega\Server\application\inc\classes\APIConnect.php on line 136
Fatal error: Call to a member function execute() on a non-object in C:\Users\Grega\Server\application\inc\classes\APIConnect.php on line 137
What is the reason for 'Couldn't fetch MySQL'? The database connection is correct, it works in other classes, and the query returns a valid result, if I echo it and execute it in phpMyAdmin. Also, my variable is named mysql NOT mysqli!

You should read more about the difference between MYSQL to MYSQLi.
While your code is:
$stmt = $this->mysql->prepare("SELECT id FROM users WHERE access_token = '{$this->accessToken}'");
You should do it like this:
$stmt = $this->mysql->prepare("SELECT id FROM users WHERE access_token = ?");
$stmt->bind_param("s" , $this->accessToken ); //Used 's' as I guess that the accessToken is a string
The binding part is the critical part of the prepare thing. (Your queries are safe)
After that you can use $stmt->execute(); and get_result().

For the first error: you probably closed the connection somewhere before this code, and this is why ($stmt -> close() )
For the second error: when you use (prepare()), you first introduce a SQL template to the database, which then has to pass the parameters to the "bind_param()" method to send it to the database with another protocol (to prevent SQL injection) and reduce the request and attach the parameters to SQL with execute() method

Related

Trouble converting to parameterized queries

So i'm trying to convert all of my SQL statements to prepared statements etc to prevent SQL injection attacks, but i'm having some issues fetching stuff etc
My code:
if($_GET["action"] == "ban"){
if(isset($_GET["username"])){
$username = $_GET["username"];
$banMsg = $_GET["banMsg"];
$email = "test#gmx.ch";
$sql = "SELECT * FROM bans WHERE username = ?";
$stmt = $db->prepare($sql);
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->fetch();
$stmt->close();
if($result->num_rows > 0){ //LINE 61
die(json_encode(array("status" => 400, "message" => "User already banned")));
}
$result2 = $db->prepare("INSERT INTO bans (username, ip, email, message, expire, ban_creator) VALUES (?, ?, ?, ?, ?, ?)");
$result2->bind_param("sssssd", $username, null, $email, $banMsg, null, 1); // LINE 72^^
$result2->close();
if($result2){
updateBanCache();
die(json_encode(array("status" => 200, "message" => "Successfully banned")));
} else {
die(json_encode(array("status" => 400, "message" => "SQL error")));
}
}
Also $result = $stmt->get_result(); doesn't wanna work for me, i do have mysqlnd driver installed in my php / cpanel though.
Any pointers would be helpful thanks!
ERROR LOG:
[11-Nov-2020 04:46:04 America/New_York] PHP Notice: Trying to get property 'num_rows' of non-object in /home/public_html/index.php on line 61
[11-Nov-2020 04:46:04 America/New_York] PHP Fatal error: Uncaught Error: Cannot pass parameter 3 by reference in /home/elysianmenu/public_html/index.php:72
Stack trace:
#0 {main}
thrown in /home/public_html/index.php on line 72
SIDE NOTE: I also tried using $result = $stmt->get_result(); but I end up with error:
[11-Nov-2020 04:57:30 America/New_York] PHP Fatal error: Uncaught Error: Call to undefined method mysqli_stmt::get_result() in /home/public_html/index.php:55
Stack trace:
#0 {main}
thrown in /home/public_html/index.php on line 55
^^ Yes i do have the mysqlnd driver installed
From the docs: Fetch results from a prepared statement into the bound variables.
fetch() returns either TRUE, FALSE or NULL, but not the result set you expected. Instead, it sets the output to the variables you previously bound (using bind_param()) by reference. This is why you have to use variables, and not actual scalar types.
If your query did not return any rows, fetch() will return NULL. Update your code as follows:
$stmt = $db->prepare($sql);
$stmt->bind_param("s", $username);
$stmt->execute();
if ($stmt->fetch() === TRUE)
die(json_encode(array("status" => 400, "message" => "User already banned")));
$stmt->close();
And to fix the error on line 72, you have to pass the values by reference, using variables. Something like this:
$ip = NULL;
$expire = NULL;
$ban_creator = 1;
$result2->bind_param("sssssd", $username, $ip, $email, $banMsg, $expire, $ban_creator);
Don't forget to execute the query! You're checking $result2 before anything actually happened.
The action of banning a user MUST NOT come from a GET request ($_GET["action"]). This would make it incredibly simple for a webcrawler to stumble upon your banning script and ban all of your users (if it somehow found a list of usernames). The whole payload should be coming in as $_POST. The bottomline is: use $_POST when you are writing data, use $_GET when you are reading data.
You MUST NOT blindly trust the user input. You should be validating the data even before connecting to the db. If the payload is invalid, no resources should be engaged.
When you are only interested in the row count of a result set (and not the values in the result set), write COUNT(1) in your query. This way you can check the lone value to be zero or a non-zero value with no unnecessary overheads. Use something like this https://stackoverflow.com/a/51259779/2943403
ip, expire, and ban_creator should have default settings in your table declaration of NULL, NULL, and 1. You should only mention those columns in an INSERT query if you wish to store a different value. Your INSERT query should only be binding 3 parameters. And of course check the outcome of the executed insert, like this: $stmt->execute() : How to know if db insert was successful?

PHP with PDO problem mysqli_stmt::fetch() [duplicate]

This question already has answers here:
Can I mix MySQL APIs in PHP?
(4 answers)
Closed 2 years ago.
I need to convert my code to PDO and I don't know where is the problem.
$user = $_SESSION['user_email'];
$get_user = "SELECT * FROM users where user_email='$user'";
//This 2 lines was there in original
$run_user = mysqli_query($con,$get_user); //original
$row=mysqli_fetch_array($run_user); //original
//Converting to PDO
$run_user = $con->prepare($get_user);
$run_user->execute();
$row = $run_user->fetch(PDO::FETCH_ASSOC); //line 27
// line 38 and 39
$user_id = $row['user_id'];
$user_name = $row['user_name'];
My errors are:
Warning: mysqli_stmt::fetch() expects exactly 0 parameters, 1 given in
/Applications/XAMPP/xamppfiles/htdocs/network/includes/header.php on
line 27
Notice: Trying to access array offset on value of type null in
/Applications/XAMPP/xamppfiles/htdocs/network/includes/header.php on
line 38
Notice: Trying to access array offset on value of type null in
/Applications/XAMPP/xamppfiles/htdocs/network/includes/header.php on
line 39
To convert your code to PDO you must ensure that you connect with PDO first. These are two very different APIs and you can't mix them.
First connect:
$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8mb4", 'user', 'pass', [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_EMULATE_PREPARES => false
]);
Then prepare and execute a statement. Pay attention to never include variables directly in SQL. Every piece of data should be bound separately. In your SQL, put ? where the data should be bound to, and then pass an array with values in execute()
$run_user = $pdo->prepare('SELECT * FROM users where user_email=?');
$run_user->execute([
$_SESSION['user_email']
]);
Now you can fetch the data. Make sure that your SQL actually fetched something before trying to access it.
$row = $run_user->fetch(PDO::FETCH_ASSOC);
if($row) {
$user_id = $row['user_id'];
$user_name = $row['user_name'];
}
You're mixing the mysqli and PDO interfaces. This isn't possible.
See this demo on how to do the same thing in PDO.
<?php
// Create a database using PDO, by passing a DSN (Data Source Name), username, and password.
// Replace yourserverhost, yourusername, yourpassword with the real credentials.
// Depending on the charset of your tables, you may want to change utf8mb4 as well,
// although this is a typical value.
$pdo = new PDO(
'mysql:host=yourserverhost;dbname=yourdatabasename;charset=utf8mb4',
'yourusername',
'yourpassword'
);
$user = $_SESSION['user_email'];
$sql = 'SELECT * FROM users where user_email=?';
$statement = $pdo->prepare($sql);
$statement->bindValue(1, $user, PDO::PARAM_STR);
$statement->execute();
$row = $statement->fetch(PDO::FETCH_ASSOC);
$user_id = $row['user_id'];
$user_name = $row['user_name'];
Your initial query is rewritten with a positional parameter (?).
The query is then made into a prepared statement to avoid SQL injection. The variable is bound using bindValue, starting at index 1. Other flavors of parameter binding are available.
PDOStatement::execute() runs the query.
PDOStatement::fetch(PDO::FETCH_ASSOC) fetches your row.
Do stuff with $row['user_id'] and $row['user_name'].

OOP alternative to the mysqli_stmt::fetch_array() [duplicate]

This question already has answers here:
Call to undefined method mysqli_result::fetch()
(2 answers)
Closed 1 year ago.
in this code i get the error: Fatal error: Call to undefined method mysqli_stmt::fetch_array()
What is the problem?
$search= "player";
($sql = $db->prepare('select job from jobs where job like ?'));
$sql->bind_param('s', $search);
$sql->execute();
$sql->bind_result($search);
$data = array();
while ($sql->fetch_array(MYSQLI_ASSOC)) {
$data[] = array(
'label' => $row['job']
);
echo json_encode($data);
}
$sql -> close();
$db -> close();
thanks
Using prepared statements there is no fetch_array(). Use mysqli_stmt::fetch() instead or to fetch multiple records use mysqli_result::fetch_all()
Check the manual: mysqli_stmt::fetch() or mysqli_result::fetch_all()

Update PHP prepare bindparam [duplicate]

This question already has answers here:
What to do with mysqli problems? Errors like mysqli_fetch_array(): Argument #1 must be of type mysqli_result and such
(2 answers)
Closed 6 years ago.
This is my PHP code:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$UpdateChecklist = 'UPDATE checklists SET ADMIN_ID=?, COMPUTER_ID=? WHERE id=?';
$stmtChecklist = $connection->prepare($UpdateChecklist);
$stmtChecklist->bind_param('ii', $_POST['ADMIN_ID'], $_POST['COMPUTER_ID']);
$isUpdate = $stmtChecklist->execute();
$lastUpdateId = mysqli_insert_id($connection);
$stmtChecklist->close();
$UpdateInstalledProgram = 'UPDATE checklist_programs SET CHECKLIST_ID=?, PROGRAM_ID=? WHERE id = ?';
$stmtProgramId = $connection->prepare($UpdateInstalledProgram);
$stmtProgramId->bind_param('ii', $lastUpdateId, $programId);
foreach ($_POST['PROGRAM_ID'] as $program) {
$programId = $program;
$stmtProgramId->execute();
}
$connection->close();
if ($isUpdate) {
header('Location: OverViewCheckList.php');
exit(0);
}
}
?>
and, I got some error which I don't know how to fix it:
Warning: mysqli_stmt::bind_param(): Number of variables doesn't match number of parameters in prepared statement in C:\xampp\htdocs\checklist\updateChecklist.php on line 34
Warning: mysqli_stmt::bind_param(): Number of variables doesn't match number of parameters in prepared statement in C:\xampp\htdocs\checklist\updateChecklist.php on line 44
Warning: mysqli::query(): Couldn't fetch mysqli in C:\xampp\htdocs\checklist\updateChecklist.php on line 57
Fatal error: Call to a member function fetch_assoc() on null in C:\xampp\htdocs\checklist\updateChecklist.php on line 59
In your both of your queries you are using 3 ?'s but only binding 2 variables.
Query 1:
$UpdateChecklist = 'UPDATE checklists SET ADMIN_ID=?, COMPUTER_ID=? WHERE id=?';
$stmtChecklist = $connection->prepare($UpdateChecklist);
$stmtChecklist->bind_param('ii', $_POST['ADMIN_ID'], $_POST['COMPUTER_ID']); /* Here*/
Query 2:
$UpdateInstalledProgram = 'UPDATE checklist_programs
SET CHECKLIST_ID=?, PROGRAM_ID=? WHERE id = ?';
$stmtProgramId = $connection->prepare($UpdateInstalledProgram);
$stmtProgramId->bind_param('ii', $lastUpdateId, $programId); /* Here */
You need to add a third variable e.g.:
$stmtChecklist->bind_param('iii', $_POST['ADMIN_ID'], $_POST['COMPUTER_ID'], $id3);
$stmtProgramId->bind_param('iii', $lastUpdateId, $programId, $id3);

Error: Call to undefined method mysqli_stmt::fetch_object() [duplicate]

This question already has answers here:
Call to undefined method mysqli_result::fetch()
(2 answers)
Closed 1 year ago.
in this code i get the error: Fatal error: Call to undefined method mysqli_stmt::fetch_array()
What is the problem?
$search= "player";
($sql = $db->prepare('select job from jobs where job like ?'));
$sql->bind_param('s', $search);
$sql->execute();
$sql->bind_result($search);
$data = array();
while ($sql->fetch_array(MYSQLI_ASSOC)) {
$data[] = array(
'label' => $row['job']
);
echo json_encode($data);
}
$sql -> close();
$db -> close();
thanks
Using prepared statements there is no fetch_array(). Use mysqli_stmt::fetch() instead or to fetch multiple records use mysqli_result::fetch_all()
Check the manual: mysqli_stmt::fetch() or mysqli_result::fetch_all()

Categories