Order by After Where clause not working in MySQLi PHP - php

Order By After Where is not returning results below is the code and screenshot of not running code.
SELECT * from `SalesMessages` where `ThreadId`= ? ORDER BY `id` desc Limit 25;
However if I remove bind params it works fine.
SELECT * from `SalesMessages` where `ThreadId`=63 ORDER BY `id` desc Limit 25;
Below is screen shot from mySql
mysql query and results
HERE IS HOW I WROTE MYSQLI Code
global $conn;
$arr = array();
mysqli_set_charset( $conn, 'utf8'); // ALREADY TRIED COMMENTING THIS LINE
$stmt = $conn->prepare($query);
$stmt->bind_param('i', $ThreadId);
try {
if ($stmt->execute()) {
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
..SOME CODE..
}
if (count($arr) > 0)
return $arr;
} else {
throw "QueryError";
}
} catch (Throwable $e) {
print_r($e);
}
}
Here is the structure of Table
DATA BASE STRUCTURE
I am expecting results from mysql in PHP code as array.

It was connection Error guys Which was using another database which does not had records. Everything else is working fine now. Actually the table in connected database had no record in required table.

Related

how to echo out every item in table using PDO?

I want to echo everything from table that matched the criteria, currently it should be 3 rows that match, but it echoes out only 1.
public function fetchInventoryItems($user_id)
{
try
{
$stmt = $this->db->prepare("SELECT * FROM items WHERE item_owner=?
AND inventory=?");
$stmt->execute([$user_id,'1']);
if ($stmt->rowCount() > 0)
{
while($userRows = $stmt->fetch(PDO::FETCH_ASSOC))
{
$itemId = $userRows['item_id'];
$stmt = $this->db->prepare("SELECT * FROM items_db WHERE
item_id=?");
$stmt->execute([$itemId]);
while($itemRows = $stmt->fetch(PDO::FETCH_ASSOC))
{
echo '<div class="dragcontainer inventory" ><div
id="'.$itemRows['item_id'].'" class="item '.$itemRows['item_type'].'"
style="background-image:url('.$itemRows['item_icon'].')" draggable="true">
</div></div>';
}
}
}
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
first fetch should retrieve 3 rows but the while loop only cycles once.
i guess it has something to do with PDO but i dont know what exactly
In the line...
$stmt = $this->db->prepare("SELECT * FROM items_db WHERE item_id=?");
Your overwriting the use of $stmt in the outer loop. Change this and any uses of this version to something else ($stmt1 would do)...
$stmt1= $this->db->prepare("SELECT * FROM items_db WHERE item_id=?");
You could rework both these SQL queries into 1 SQL statement, which would reduce the overhead and stop this sort of issue.

SQL Count Not Working From Inside of PHP Code

I have the weirdest issue going on. COUNT() is not working from inside my PHP code, but it is working in the SQL input space in the PHPMyAdmin database. For example if I use the following query:
SELECT COUNT(*) FROM posts WHERE category = "coding"
It will return the correct results from the SQL input in the PHPmyadmin part, but from the PHP code it will always return 1. Here is the code I am using for the PHP:
function numberofposts($category, $connection) {
$query = "SELECT COUNT(*) FROM posts WHERE category = :category";
$params = array(':category' => $category);
try{
$stmt = $connection->prepare($query);
$result = $stmt->execute($params);
}
catch(PDOException $ex){
echo ("Failed to run query: " . $ex->getMessage());
}
return $result;
}
echo "Number of Posts: " . numberofposts("art", $connection);
What it is doing is in the first code at the top it will return the correct results, but in the PHP code it is always returning 1. Is there a problem with me PHP? Please just post if you do not understand what I am asking, or if you would like more information.
You are doing a select and you execute the statement, but you are not fetching the row with the results.
You probably want something like:
function numberofposts($category, $connection) {
$query = "SELECT COUNT(*) as cnt FROM posts WHERE category = :category";
^^^ for easy access
$params = array(':category' => $category);
try{
$stmt = $connection->prepare($query);
$stmt->execute($params);
$row = $stmt->fetch();
}
catch(PDOException $ex){
echo ("Failed to run query: " . $ex->getMessage());
}
return $row['cnt'];
// if you don't alias the column you can do:
// return $row[0];
}

PHP PDO Row Counting

i want to check the rows if there are any events that are binded to a host with host_id parameter, everything is well if there is not any events binded to a host, its printing out none, but if host is binded to one of the events, its not listing the events, but if i remove the codes that i pointed below with commenting problem starts here and problem ends here, it lists the events. I'm using the fetchAll function above too for another thing, there is not any such that error above there, but with the below part, it's not listing the events, how can i fix that?
Thanks
try
{
$eq = "SELECT * FROM `events` WHERE `host_id` = :id AND `confirmed` = '1' ";
$eq_check = $db->prepare($eq);
$eq_check->bindParam(':id', $id, PDO::PARAM_INT);
$eq_check->execute();
//problem starts here
$count3 = $eq_check->fetchAll();
$rowCount = count($count3);
if ($rowCount == 0)
{
echo "None";
}
//problem ends here
while($fetch = $eq_check->fetch (PDO::FETCH_ASSOC) )
{
$_loader = true;
$event_id = $fetch['event_id'];
$event_name = $fetch['event_name'];
$link = "https://www.mywebsite.com/e/$event_id";
echo "<a target=\"_blank\" href=\"$link\"><li>$event_name</li></a>";
}
}
catch(PDOException $e)
{
$log->logError($e." - ".basename(__FILE__));
}
Thank you
You can't fetch twice without executing twice as well. If you want to not just re-use your $count3 item, you can trigger closeCursor() followed by execute() again to fetch the set again.
To reuse your $count3 variable, change your while loop into: foreach($count3 as $fetch) {
The reason that it is not listing the events when you have your code is that the result set is already fetched using your fetchAll statement (The fetchAll doesn't leave anything to be fetched later with the fetch).
In this case, you might be better off running a select count(*) to get the number of rows, and then actually running your full query to loop through the results:
An example of this in PDO is here:
<?php
$sql = "SELECT COUNT(*) FROM fruit WHERE calories > 100";
if ($res = $conn->query($sql)) {
/* Check the number of rows that match the SELECT statement */
if ($res->fetchColumn() > 0) {
/* Issue the real SELECT statement and work with the results */
$sql = "SELECT name FROM fruit WHERE calories > 100";
foreach ($conn->query($sql) as $row) {
print "Name: " . $row['NAME'] . "\n";
}
}
/* No rows matched -- do something else */
else {
print "No rows matched the query.";
}
}
$res = null;
$conn = null;
?>
Note that you cannot directly use rowCount to get a count of rows selected - it is meant to show the number of rows deleted and the like instead.

PHP PDO bug when trying to parameterize SQL LIMIT :offset, :display?

This query returns 5 results in phpMyAdmin:
SELECT * FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT 0,5
And this returns count=12 in phpMyAdmin (which is fine, because there are 12 records):
SELECT COUNT(*) AS count FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT 0,5
This function was working fine before I added the two variables (offset, display), however now it doesn't work, and printing the variables out gives me offset=0, display=5 (so still LIMIT 0,5).
function getProducts($offset, $display) {
$sql = "SELECT * FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT ?,?;";
$data = array((int)$offset, (int)$display);
$rows = dbRowsCount($sql, $data);
logErrors("getProducts(".$offset.",".$display.") returned ".$rows." rows.");
if ($rows > 0) {
dbQuery($sql, $data);
return dbFetchAll();
} else {
return null;
}
}
It's not working because my dbRowsCount(...) method was returning empty string (stupid PDOStatement::fetchColumn), so I changed it to return the count with PDO::FETCH_ASSOC and it returns count=0.
Here is the function which does the row-count:
function dbRowsCount($sql, $data) {
global $db, $query;
$regex = '/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/is';
if (preg_match($regex, $sql, $output) > 0) {
$query = $db->prepare("SELECT COUNT(*) AS count FROM {$output[1]}");
logErrors("Regex output: "."SELECT COUNT(*) AS count FROM {$output[1]}");
$query->setFetchMode(PDO::FETCH_ASSOC);
if ($data != null) $query->execute($data); else $query->execute();
if (!$query) {
echo "Oops! There was an error: PDOStatement returned false.";
exit;
}
$result = $query->fetch();
return (int)$result["count"];
} else {
logErrors("Regex did not match: ".$sql);
}
return -1;
}
My error log gives me this output from the program:
Regex output: SELECT COUNT(*) AS count FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT ?,?;
getProducts(0,5) returned 0 rows.
As you can see, the SQL has not been malformed, and the method input variables were 0 and 5 as expected.
Does anyone know what has gone wrong?
Update
Following a suggestion, I did try to execute the query directly, and it returned the correct result:
function dbDebugTest() {
global $db;
$stmt = $db->query("SELECT COUNT(*) AS count FROM tbl_product WHERE 1 ORDER BY last_update LIMIT 0,5;");
$result = $stmt->fetch();
$rows = (int)$result["count"];
logErrors("dbDebugTest() returned rows=".$rows);
}
Output:
> dbDebugTest() returned rows=12
Following another suggestion, I changed !=null to !==null, and I also printed out the $data array:
logErrors("Data: ".implode(",",$data));
if ($data !== null) $query->execute($data); else $query->execute();
Output:
> Data: 0,5
However, the dbRowsCount($sql, $data) still returns 0 rows for this query!
Update 2
Following advice to implement a custom PDOStatement class which would allow me to output the query after the values have been binded, I found that the function would stop after $query->execute($data) and so the output would not be printed, although the custom class works for every other query in my program.
Updated code:
function dbRowsCount($sql, $data) {
global $db, $query;
$regex = '/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/is';
if (preg_match($regex, $sql, $output) > 0) {
$query = $db->prepare("SELECT COUNT(*) AS count FROM {$output[1]}");
logErrors("Regex output: "."SELECT COUNT(*) AS count FROM {$output[1]}");
$query->setFetchMode(PDO::FETCH_ASSOC);
logErrors("Data: ".implode(",",$data));
$query->execute($data);
logErrors("queryString:".$query->queryString);
logErrors("_debugQuery():".$query->_debugQuery());
if (!$query) {
echo "Oops! There was an error: PDOStatement returned false.";
exit;
}
$result = $query->fetch();
return (int)$result["count"];
} else {
logErrors("Regex did not match: ".$sql);
}
return -1;
}
Output:
Regex output: SELECT COUNT() AS count FROM tbl_product_category WHERE id=?;
Data: 5
queryString:SELECT COUNT() AS count FROM tbl_product_category WHERE id=?;
_debugQuery():SELECT COUNT(*) AS count FROM tbl_product_category WHERE id=?;
Regex output: SELECT COUNT(*) AS count FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT ?,?;
Data: 0,5
// function stopped and _debugQuery couldn't be output
Update 3
Since I couldn't get the custom PDOStatement class to give me some output, I thought I'd rewrite the getProducts(...) class to bind the params with named placeholders instead.
function getProducts($offset, $display) {
$sql = "SELECT * FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT :offset, :display;";
$data = array(':offset'=>$offset, ':display'=>$display);
$rows = dbRowsCount($sql, $data);
logErrors("getProducts(".$offset.",".$display.") returned ".$rows." rows.");
if ($rows > 0) {
dbQuery($sql, $data);
return dbFetchAll();
} else {
return null;
}
}
Output:
Regex output: SELECT COUNT(*) AS count FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT :offset, :display;
Data: 0,5
// Still crashes after $query->execute($data) and so logErrors("getProducts(".$offset."...)) wasn't printed out
Update 4
This dbDebugTest previously worked with declaring the limit values 0,5 directly in the SQL string. Now I've updated it to bind the parameters properly:
function dbDebugTest($offset, $display) {
logErrors("Beginning dbDebugTest()");
global $db;
$stmt = $db->prepare("SELECT COUNT(*) AS count FROM tbl_product WHERE 1 ORDER BY last_update LIMIT :offset,:display;");
$stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
$stmt->bindParam(':display', $display, PDO::PARAM_INT);
if ($stmt->execute()) {
$result = $stmt->fetch();
$rows = (int)$result["count"];
logErrors("dbDebugTest() returned rows=".$rows);
} else {
logErrors("dbDebugTest() failed!");
}
}
The function crashes, and only this is output:
Beginning dbDebugTest()
Update 5
Following a suggestion to turn errors on (they are off by default), I did this:
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
That itself, made the dbDebugTest() from Update 4 work!
Beginning dbDebugTest()
dbDebugTest() returned rows=12
And now an error is generated in my webserver logs:
[warn] mod_fcgid: stderr: PHP Fatal error:
Uncaught exception 'PDOException' with message 'SQLSTATE[42000]:
Syntax error or access violation: 1064 You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax to use
near ''0', '5'' at line 1'
in /home/linweb09/b/example.com-1050548206/user/my_program/database/dal.php:36
Line 36 refers to dbRowsCount(...) method and the line is $query->execute($data).
So the other method getProducts(...) still doesn't work because it uses this method of binding the data and the params turn into ''0' and '5'' (is this a bug?). A bit annoying but I'll have to create a new method in my dal.php to allow myself to bind the params in the stricter way - with bindParam.
Thanks especially to #Travesty3 and #eggyal for their help!! Much, much appreciated.
Based on Update 2 in the question, where execution stops after the execute statement, it looks like the query is failing. After looking at some PDO documentation, it looks like the default error handling setting is PDO::ERRMODE_SILENT, which would result in the behavior you are seeing.
This is most likely due to the numbers in your LIMIT clause being put into single-quotes when passed in as parameters, as was happening in this post.
The solution to that post was to specify the parameters as integers, using the bindValue method. So you will probably have to do something similar.
And it looks like you should also be executing your queries with try-catch blocks in order to catch the MySQL error.
bindValue method:
if ($data !== null)
{
for ($i=0; $i<count($data); $i++)
$query->bindValue($i+1, $data[$i], PDO::PARAM_INT);
$query->execute($data);
}
else
$query->execute();
You're testing to see if $data is NULL with the equality, rather than the identity, operator (see the PHP manual for more information on how NULL values are handled by the various comparison operators). You need to either use the identity test === / !==, or else call is_null().
As #Travesty3 mentioned above, to test whether an array is empty, use empty().

PDO: Does fetchColumn moves the pointer of the returned results set?

I recently implemented PDO and noticed that my query results lacked the first row. That's probably because fetchColumn() retrieves the first row and moves the pointer to the second row so that the while() loop starts at row 2. Is that correct? If so, how can I avoid that and improve the following code block?
$STH = $DBH->prepare("SELECT * FROM users");
$result = $STH->execute();
if (!$result)
{
return false;
}
elseif($STH->fetchColumn()>0)//counterpart of mysql_num_rows()
{
while ($row = $STH->fetch())
{
...
}
}
}
Is that correct?
Yes. Also, fetchColumn() is not an equivalent for mysql_num_rows(). Instead, fetchColumn() retrieves the indexed column value (defaulting to index 0) of the current row and as assumed, advances the cursor.
If you need a count of the number of rows returned in your query, I suggest you first issue a SELECT COUNT(1) ... query with the same conditions, using fetchColumn() to return the count.
See example #2 on this manual page - http://www.php.net/manual/en/pdostatement.rowcount.php
For example
$stmt = $DBH->query('SELECT COUNT(1) FROM users');
// using a straight PDO::query() call as a prepared statement would be
// overkill for these queries
if ($stmt->fetchColumn() == 0) {
return false;
}
$stmt = $DBH->query('SELECT * FROM users');
while ($row = $stmt->fetch()) {
...
}
After googling around I came up with this solution:
$STH = $DBH->prepare("SELECT * FROM users");
if(!$STH)
{
$error = $DBH->errorInfo();
}
else
{
$result = $STH->execute();
if($result===false)
{
return false;
}
else
{
$rows = $STH->fetchAll(PDO::FETCH_ASSOC);
if(count($rows) > 0)
{
foreach ($rows as $row)
{
...
}
}
}
}
}

Categories