php mysqli result object cannot immediately be referenced in if statement...? - php

//Execute query and fetch first row
if ($qry=$db->query("SELECT statement")) {
if ($row=$qry->fetch_object()) {
}
}
//Same code as above using only one if statement
if ($qry=$db->query("SELECT statement") && $row=$qry->fetch_object()) {
}
Why does the second block of code (when run as a replacement to the first) produce the error "Call to function fetch_object on a non-object"?

This is because PHP isn't parsing the 2nd statement quite the way you'd expect.
It's reading it as:
if ($qry = ($db->query("SELECT statement") && $row = $qry->fetch_object()))
Which as you can see, means $qry is set before fetch_object is called on it.
Try to enclose your statements in ():
if (($qry=$db->query("SELECT statement")) && ($row=$qry->fetch_object()))

Related

php sql search issues

ok here is my code maybe someone out there can explain what I am doing wrong here as I just don't get it. My understanding of this is that IF the stmt finds a result it will then run the code in the {} and hence return a result. And IF there is no result then it would return nothing, as the IF statement is false. But I am getting a return in postman even though the ID that I am searching is false. It does not exist on the table. Why do I get a return?
public function getDoc($ID){
if( $xromstmt = $this->con->prepare("SELECT adegree, bdegree, cset, dset FROM xromdb WHERE ID = ?")) {
$xromstmt->bind_param("s", $ID);
$xromstmt->execute();
$xromstmt->bind_result($adegree, $bdegree, $cset, $dset);
$xromstmt->fetch();
$evalxrom = array();
$edocxrom = array();
some other code here dealing with the return etc... } <-- the end bracket
to the if statement. There is nothing past this bracket.
} bracket to getDoc
The if statement that you have is just checking that the prepare was successful. To see if there was any data returned from the query, you need to check the result of the call to fetch. Try something like this:
if ($xromstmt = $this->con->prepare("SELECT adegree, bdegree, cset, dset FROM xromdb WHERE ID = ?")) {
$xromstmt->bind_param("s", $ID);
$xromstmt->execute();
$xromstmt->bind_result($adegree, $bdegree, $cset, $dset);
if ($xromstmt->fetch()) {
$evalxrom = array();
$edocxrom = array();
...
some other code here dealing with the return etc...
}
}
You should probably also check the result of the call to execute.
The $xromstmt->prepare statement does not search the database it sets-up the search; the database is not searched until $xromstmt->execute. The execute and prepare statements will return true or false if the statement was run correctly (i.e. no errors in your code) regardless of whether any results were found.
What you want is to use is the number of rows from the query, 0 if no results found:
$num_rows = mysql_num_rows($xromstmt)
then run if statements of $num_rows
Hope this helps

Trying to get value from PHP multi_query

I'm stuck on this problem for a while now and looking for helpful suggestions.
$resultset = $connection->multi_query($sql);
pseudo:
IF $resultset > 0 (--> if the sql query returned at least one result) {
// do something
}
now the problem is with the pseudo part, i have tried to the follows:
if($resultset > 0) // takes no effect
if($resultset->num_rows > 0) // Notice: Trying to get property of non-object
I have to use multi_query so mysqli_query/mysqli_fetch_array is not a solution
thanks for the hints....
Please try:
if($connection->multi_query($sql))
{
//sample query taken from php manual, see link below
do {
/* store first result set */
if ($result = $connection->store_result()) {
while ($row = $result->fetch_row()) {
printf("%s\n", $row[0]);
}
$result->free();
}
/* print divider */
if ($connection->more_results()) {
printf("-----------------\n");
}
} while ($connection->next_result());
}
else
{
//handle error
echo mysqli_error ( $connection );
}
If you check out the documentation of multi query (here), you will see that the function returns a boolean.
Source code also taken from php manual.
multi_query() returns a boolean that indicates whether the first query was successful, it doesn't return a mysqli_result object.
You have to call the store_result() method to get the first result set.
$resultset = $connection->store_result();
To get subsequent result sets you use more_results() and next_result().
See the examples in the documentation.

PDO::exec() blocking further query from working

I'm trying to implement pagination using PHP. I found that calling exec to the connected database prevents the further query calls from working.
The piece of code at hand:
<?php
// Pagination logic
//Here we count the number of results
$query = "SELECT COUNT(*) as num FROM gig";
$total_pages = $db->exec($query);
$total_pages = $total_pages[num];
?>
After it if I try to use a query such as:
<?php>
foreach ($db->query("SELECT sname, start, venue FROM gig WHERE start = '0000-00-00 00:00:00'") as $a) {
$row="<tr><td>$a[sname]</td><td>To be announced</td><td>$a[venue]</td></tr>\n";
print $row;
}
?>
it returns
Warning: Invalid argument supplied for foreach()
As soon as the first code block is removed, the query works fine. When I check the value of $total_pages, it's 0, so something must be going wrong along the way. As far as I know, I use it in the same way as the query(which works on its own), so is there any reason why it doesn't work?
The PDO is initialized in the following way:
try {
$db = new PDO("mysql:dbname=$db_name;host=$db_server", $db_user, $db_pw);
} catch (PDOException $e) {
die('Connection failed: ' . $e->getMessage());
}
session_start();
From Manual
PDO::exec() does not return results from a SELECT statement. For a
SELECT statement that you only need to issue once during your program,
consider issuing PDO::query(). For a statement that you need to issue
multiple times, prepare a PDOStatement object with PDO::prepare() and
issue the statement with PDOStatement::execute().
Used a function of the STATEMENT object had after using querying to count the rows instead of exec:
$dbq = $db->query("SELECT * FROM gig");
$rows = $dbq->rowCount();
About the latter code block not working because of the exec failing - it seems to just be the way php queries work, if one fails, all fail. The foreach() error is for the object it's provided is not an array, for it failed.

ZF2 already active query prevents execution

I have something like the following, in a function that deletes both the files and db entries:
$adapter = $this->getAdapter();
$query = $adapter->query("call find_results_by_job_id(?)", array($jobId));
$items = array();
while (($current = $query->current()) !== false)
{
$id = $current['id'];
$items[] = $id;
$query->next();
}
$this->deleteFromDataStore($items);
$result = $adapter->query("call delete_results_by_job_id(?)", array($jobId), \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);
(Some of that might not look like the best way to do it, because I simplified it for this example)
I'm getting this error on the last line: SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active.
I'm assuming that the problem is because the query/adapter hasn't closed the connection from iterating results yet when I try to execute another statement. If that is the case, how can reuse the adapter, or close the query, or whatever I have to do before the last line?
The strange part is that code following almost exactly this same pattern works in another method.
Answer:
When using the PDO driver, $query->getDataSource()->getResource()->closeCursor(); fixes it
Seems like you are using an unbuffered query in MySQL.
If it is so, you will either have to turn buffering on or break execution of previous query which seems to hang?
Something like $query->close()
EDIT:
If $query is instance of StatementInterface, then there is getResource() which returns mysqli_stmt and you can call close() on it.
EDIT2: (to incorporate final resolution)
In case it uses PDO, you can get PDOStatement and call closeCursor()
Assuming you have the result of a query in your hands and you dont know whether it is a ResultSet or a Result, the following will do the job.
Tested as of Zend Framework 3.
use Zend\Db\ResultSet\ResultSet;
...
public function closeResult( $result )
{
if( is_a($result, ResultSet::class) )
{
$stmt = $result->getDataSource()->getResource();
}
else
{
$stmt = $result->getResource();
}
$stmt->closeCursor();
}
$this->adapter
->query($sql)
->execute()
->getResource()
->fetchAll(\PDO::FETCH_ASSOC);

How to get all errors after calling to mysqli_multi_query?

I'm using this code:
$mysqli = new mysqli(...);
$sql = file_get_contents("my_sql_file.sql");
$result = $mysqli->multi_query($sql);
if (!$result)
report_error(); //my function
while ($mysqli->more_results()) {
$result = $mysqli->next_result();
if (!$result)
report_error();
}
However the 'while' loop in the code above turned out to be an infinite loop. Anything wrong?
Actually your code doesn't really make sense. The proper way to handle multiqueries is the following (see php manual)
if ($mysqli->multi_query($query)) {
do {
// store first result set
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_row()) {
// do something with the row
}
$result->free();
}
else { error_report(); }
} while ($mysqli->next_result());
}
else { error_report(); }
The code provided in the question reaches to an infitie loop because "If your second or late query returns no result or even if your query is not a valid SQL query, more_results(); returns true in any case.", see this note on php.net: http://us3.php.net/manual/en/mysqli.multi-query.php#104076
And further more, mysqli_more_results always returns true in the code because the results are not discarded, must call mysqli_store_results to discard result after each call to mysqli_next_result. See: http://us3.php.net/manual/en/mysqli.multi-query.php#91677
There is no official way to catch all errors when executing MySQL text (multi-commands separated by semicolons) by mysqli_multi_query. The function mysqli_multi_query will stop execution when it faces a bad SQL command, so it is only possible to catch the first error (no matter where the error occurs, in the first SQL command or any other SQL command in the SQL text).
Related to Jon's answer to this question: When does mysqli_multi_query stop execution?
And as noted in http://www.php.net/manual/en/mysqli.multi-query.php#106126 The first error can be catched by scanning mysqli_next_result coz: $mysqli->next_result() will return false if it runs out of statements OR if the next statement has an error.
Finally the answer is that results must be discarded after calling to mysqli_next_result using mysqli_store_result:
$mysqli = new mysqli(...);
$sql = file_get_contents("my_sql_file.sql");
$result = $mysqli->multi_query($sql);
if (!$result)
report_error(); //my function
while ($mysqli->more_results()) {
$result = $mysqli->next_result();
//important to make mysqli_more_results false:
$discard = $mysqli->store_result();
if (!$result)
report_error();
}

Categories