I'm fetching some data and trying to print it to the page but i'm getting the following error -
PHP Catchable fatal error: Object of class PDOStatement could not be converted to string
This is my query function;
function query($query, $bindings, $conn)
{
$stmt = $conn->prepare($query);
$stmt->execute($bindings);
return $stmt;
}
the query and printing to the page;
$testimonials = query ('SELECT * FROM testimonials ORDER BY id = :id DESC LIMIT 1',
array('id' => ['id']), $conn);
print $testimonials;
I'm not sure how I can turn it to a string without re-writing the function or should I be doing that?
You are not actually returning any results, you're returning the PDO object
change the return from
return $stmt;
to
return $stmt->fetchAll(PDO::FETCH_ASSOC);
this will return multiple results (if they are available)
or
return $stmt->fetch(PDO::FETCH_ASSOC);
will return a single result
UPDATE
To answer your comment, you can use
return ($stmt->rowCount() > 0) ? $stmt->fetchAll(PDO::FETCH_ASSOC) : false;
Note: this will return an array, which means you need to access the array to print what you want.. you can do this like so:
foreach( $testimonials as $testimonial )
{
print( $testimonial['field_name_from_database'] );
}
it should be,
print_r($testimonials);
For debug/test purpose, it's better to use var_dump(), it provide an html formated output with additionnal informations (type, length) and work recursively.
Also you return a PDOStatement object, it's a prepared request that havent been executed. You need it to fetch the results (fetch or fetchAll).
PHP :
function query($query, $bindings, $conn)
{
$stmnt = $conn->prepare($query);
$stmt->execute($bindings);
return $stmt->fetchAll();
}
Related
Some people recommends calling close() on a prepared statement when I am done with the result of a query.
I often reuse the same variable name for the prepared statement, so I was wondering if overriding the variable automatically calls close() on the prepared statement ?
Example of how I currently do it (The SQL is made up for the examples):
// Fetch the requested user
$stmt = $mysqli->prepare("SELECT * FROM user WHERE id = ?");
$stmt->bind_param("i", $_GET['userid']);
$stmt->execute();
$user = $stmt->get_result()->fetch_assoc();
// Fetch all posts associated with the user
$stmt = $mysqli->prepare("SELECT * FROM posts WHERE user_id = ?");
$stmt->bind_param("i", $user['id']);
$stmt->execute();
$result = $stmt->get_result();
$posts = array();
while ($row = $result->fetch_assoc()) {
$posts[] = $row;
}
Should I call $stmt->close(); between fetching the user and fetching the posts or is it done when I override $stmt by calling $stmt = $mysqli->prepare(...); ?
Yes, most of the time, because PHP will try to clean up objects which have no reference as soon as possible. That means that once you overwrite it, there will be no more references to the old object and PHP will clean it up. Part of cleaning up mysqli_stmt object involves closing the statement.
But the reason why some people recommend calling $stmt->close() explicitely is to avoid errors such as this:
mysqli_sql_exception: Commands out of sync; you can't run this command now in ...
This error happens when you have not fetched all results from MySQL and you try to create a new statement by calling prepare or query. MySQL will not let you execute anything else until you fetch all remaining rows. This is usually achieved with get_result() or store_result(). If you always fetch the results in their entirety then you really don't need to worry much about when exactly the statement gets closed. Let PHP take care of it for you.
The best course of action is to avoid using mysqli functions directly. You should write some simple function which will encapsulate all the mysqli functionality so that you never have to worry about this low-level stuff. A sample function could look like this:
function safeQuery(\mysqli $db, string $sql, array $params = []): ?array {
$stmt = $db->prepare($sql);
if ($params) {
$stmt->bind_param(str_repeat("s", count($params)), ...$params);
}
$stmt->execute();
if ($result = $stmt->get_result()) {
return $result->fetch_all(MYSQLI_BOTH);
}
return null;
}
$result = safeQuery($mysqli, 'SELECT * FROM user WHERE id = ?', [$_GET['userid']]);
if ($result) {
$user = $result[0];
$posts = safeQuery($mysqli, 'SELECT * FROM posts WHERE user_id = ?', [$user['id']]);
foreach ($posts as $post) {
}
}
so I have the following method:
public function checkLogin($username){
$sql_login=$this->dbc->prepare("SELECT username FROM credentials WHERE username=?");
$sql_login->bind_param("s", $username);
$stmt=$sql_login->execute();
$result = $stmt->get_result();
return $result;
}
By doing a var_dump (and removing $result = $stmt->get_result();) I can see that $stmt is passing a boolean.
I'm new to OOP in php. I'm thinking that get_result() function should get the result of the $stmt execution.
What am I doing wrong please ?
$result = $stmt->get_result(); converts a mysqli::statement object into a mysqli::result object, it does not return any rows from the resultset
You are also using the returned value from $sql_login->execute(); which is in fact just a boolean instead of the statement object called $sql_login in your case i.e. $result = $sql_login->get_result();
So you need to add something to actually fetch the row that was returned by the query, for example $row = $result->fetch_assoc(); like this
public function checkLogin($username){
$sql_login=$this->dbc->prepare("SELECT username
FROM credentials
WHERE username=?");
$sql_login->bind_param("s", $username);
$sql_login->execute();
$result = $sql_login->get_result();
$row = $result->fetch_assoc(); // fetch the row as an assoc array
return $row;
}
I have a question, namely - I have created a function that selects certain things from the base. I passed the function argument as bindParam, but I get an empty array. The only way in this case is to insert a variable from the argument directly into the query without binding. What is the reason for this?
function sampleFunction($test, $test2, $db) {
$stmt = $db->prepare("SQL QUERY WITH :test AND :test2");
$stmt->bindParam(':test', $test);
$stmt->bindParam(':test2', $test2);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
I'm trying to delete a row from a table, and check if it worked / if a row has been found and removed. I use the following query to do so:
DELETE FROM TableName WHERE val1=1 AND val2=2 AND val3=3. I send that code via the connection $conn using a prepare and execute function, and it works just fine. The row I'm looking for is being found and deleted. But if I want to check if it worked using $conn->affected_rowsit returns -1, which means that an error occured. I don't understand, where the error could be, that affected_rowsreturns -1, even though the query has been executed properly...
If you do not understand the issue, feel free to ask in a comment.
code:
$query = "DELETE FROM ComTasks WHERE comid=? AND obj=? AND type=0";
$response = paramQuery($conn, $query, array($communityid, $userid), "ss");
echo $conn->affected_rows; //=> -1
function paramQuery($conn, $query, $params, $str){
if(!is_array($params)) $params = array($params);
$stmt = $conn->prepare($query);
if($stmt === false) return -1;
for($i=0; $i<count($params); $i++){
$params[$i] = &$params[$i];
}
array_unshift($params, $str);
call_user_func_array(array($stmt, 'bind_param'), $params);
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
return $result;
}
Since you are using a prepared statement and $stmt, the affected_rows should also be called from $stmt:
$stmt->affected_rows;
However since you wrapped it in a function, and do a $stmt-close(), this will not work outside of the function call. You may have to adjust your function to store that value before close, and before the return of the function.
Some more info here on php manual: http://php.net/manual/en/mysqli-stmt.affected-rows.php
All the examples I see using mysqli_fetch_object use mysql_query(), I cannot get it to work with prepared statements. Does anyone know what is wrong with this code snippet, as fetch_object returns null.
$sql = "select 1 from dual";
printf("preparing %s\n", $sql);
$stmt = $link->prepare($sql);
printf("prepare statement %s\n", is_null($stmt) ? "is null" : "created");
$rc = $stmt->execute();
printf("num rows is %d\n", $stmt->num_rows);
$result = $stmt->result_metadata();
printf("result_metadata %s\n", is_null($result) ? "is null" : "exists");
$rc = $result->fetch_object();
printf("fetch object returns %s\n", is_null($rc) ? "NULL" : $rc);
$stmt->close();
The output is:
preparing select 1 from dual
prepare statement created
num rows is 0
result_metadata exists
fetch object returns NULL
This is the code I use to create an object from a prepared statement.
It could perhaps be used in a subclass of mysqli?
$query = "SELECT * FROM category WHERE id = ?";
$stmt = $this->_db->prepare($query);
$value = 1;
$stmt->bind_param("i", $value);
$stmt->execute();
// bind results to named array
$meta = $stmt->result_metadata();
$fields = $meta->fetch_fields();
foreach($fields as $field) {
$result[$field->name] = "";
$resultArray[$field->name] = &$result[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $resultArray);
// create object of results and array of objects
while($stmt->fetch()) {
$resultObject = new stdClass();
foreach ($resultArray as $key => $value) {
$resultObject->$key = $value;
}
$rows[] = $resultObject;
}
$stmt->close();
MySql Native Driver extension (mysqlnd), has the get_result method:
$stmt->execute();
$obj = $stmt->get_result()->fetch_object();
I don't believe the interface works like that.
Going by the documentation and examples (http://www.php.net/manual/en/mysqli.prepare.php) it seems that $stmt->execute() does not return a resultset, but a boolean indicating success / failure (http://www.php.net/manual/en/mysqli-stmt.execute.php). To actually get the result, you need to bind variables to the resultset (aftere the execute call) using $stmt->bind_result (http://www.php.net/manual/en/mysqli-stmt.bind-result.php).
After you did all that, you can do repeated calls to $stmt->fetch() () to fill the bound variables with the column values from the current row. I don't see any mention of $stmt->fetch_object() nor do I see how that interface could work with a variable binding scheme like described.
So this is the story for "normal" result fetching from mysqli prepared statments.
In your code, there is something that I suspect is an error, or at least I am not sure you intended to do this.
You line:
$result = $stmt->result_metadata();
assignes the resultset metadata, which is itself represented as a resultset, to the $result variable. According to the doc (http://www.php.net/manual/en/mysqli-stmt.result-metadata.php) you can only use a subset of the methods on these 'special' kinds of resultsets, and fetch_object() is not one of them (at least it is not explicitly listed).
Perhaps it is a bug that fetch_object() is not implemented for these metadata resultsets, perhaps you should file a bug at bugs.mysql.com about that.