SQLite3 count rows - php

I am trying to count the number of rows returned from a query
This is currently the code I have
function products()
{
$loggedin = loggedin();
$db = db();
$stmt = $db->prepare('SELECT game_id, name, developer, price FROM game WHERE quantity > 0 ORDER BY game_id DESC');
$result = $stmt->execute();
$row1 = $result->fetchArray();
$rows = count ($row1);
if ($rows == 0)
{
echo "Sold out";
}
else
{
while ($row = $result->fetchArray()) {
echo '<p>'.$row['name'].'</p>';
}
}
}
At present it will only return the first item in the table, even though all rows match
if I change my code to
function products()
{
$loggedin = loggedin();
#$page = 'index.php';
$db = db();
$stmt = $db->prepare('SELECT game_id, name, developer, price FROM game WHERE quantity > 11 ORDER BY game_id DESC');
$result = $stmt->execute();
while ($row = $result->fetchArray()) {
echo '<p>'.$row['name'].'</p>';
}
Then I get all the result from the table correctly
if I change the query to a value outside the quantity like
quantity > 20
then I get the error
Warning: count(): Parameter must be an array or an object that implements Countable
what I would like it to do is if row1 is == 0 the show sold out other wise display all the rows
so if a row does not match the query it will not be included in the results
I can not use PDO, and I have not been able to find out to use count on https://www.php.net/manual/en/book.sqlite3.php

That should do it.
function products() {
$loggedin = loggedin();
$db = db();
$games = $db->query('SELECT game_id, name, developer, price FROM game WHERE quantity > 0 ORDER BY game_id DESC');
if (empty($games->fetchArray())) {
echo "Sold out";
return;
}
// Reset the result back to the first game
$games->reset();
while ($game = $games->fetchArray(SQLITE3_ASSOC)) {
echo '<p>'.$game['name'].'</p>';
}
}

I'd do something like:
function products() {
$db = db();
$stmt = $db->prepare('SELECT game_id, name, developer, price FROM game WHERE quantity > 0 ORDER BY game_id DESC');
$result = $stmt->execute();
$count = 0;
while ($row = $result->fetchArray()) {
echo '<p>'.$row['name'].'</p>';
$count++;
}
if ($count == 0) {
echo "<p>Sold out</p>";
}
}
The only way to find out how many rows were returned by a query is to fetch all of them (and you don't actually care how many rows were returned, just that at least one was). So just increment a counter once per row returned, and after stepping through all rows, if that counter is still 0, it means no rows were returned, and you can display the relevant message.

Related

Database error in code. What isn't working is the grade query

$Prereq = "SELECT PreReqId FROM PreReq WHERE CourseId ='$CCourseId'";
$Query1= mysqli_query($db,$Prereq);
$array1 = mysqli_fetch_array($query1,MYSQLI_ASSOC);
$value= $array1['PreReqId'];
foreach($value as $i => $test)
{
$Grade = "SELECT Grade FROM Enrolled WHERE CourseId = '$test' AND UserId ='$UserId'";
$query2= mysqli_query($db,$Grade);
$array2= mysqli_fetch_array($query2,MYSQLI_ASSOC);
$value2= $array2['Grade'];
if($value2 == 'A' || $value2 == 'B' || $value2 == 'C')
{
return result = 1;
}
else
{
return result =0;
}
}
I have to check for preqrequitie grades for courses before a user can enroll in a class. As is I am able to get and echo the right prereqId. What isn't working is the grade query. Not sure why.
Though the question is rather unclear. I can suggest the following;
Your first query $Prereq only selects one value: PreReqId
You
have a typo in $Query1and than using it as mysqli_fetch_array($query1,MYSQLI_ASSOC)
It is not clear where $UserId is being set.
Try using Prepared statements to prevent Sql injections
Try the following:
$Prereq = "SELECT * FROM PreReq WHERE CourseId ='$CCourseId'";
$query1= mysqli_query($db, $Prereq);
// loop through query results
while ($row = mysqli_fetch_array($query1, MYSQLI_ASSOC))
{
// For each row perform another query
$Grade = "SELECT Grade FROM Enrolled WHERE CourseId = '".$row['PreReqId ']."' AND UserId ='$userId'";
$query2= mysqli_query($db, $Grade);
while ($row2 = mysqli_fetch_array($query2, MYSQLI_ASSOC))
{
if($row2['Grade'] == 'A' || $row2['Grade']== 'B' || $row2['Grade'] == 'C')
{
return result = 1;
}
else
{
return result =0;
}
}
}
Why not have your database perform this logic and just check if any prerequisites are missing?
function isStudentAllowedToEnroll($UserId, $CCourseId) {
$student_may_enroll = false;
// I assumed your MySQL connection is in the global scope, if not you can
// also just pass it in as another argument to the function if you'd like
global $db;
// Find all prerequisites for the course, exclude the ones the student
// has passed, then count how many are left
$query = "
SELECT COUNT(*)
FROM PreReq
LEFT JOIN Enrolled
ON Enrolled.CourseId = PreReq.PreReqId
AND Enrolled.UserId = ?
AND Enrolled.Grade IN ('A', 'B', 'C')
WHERE PreReq.CourseId = ?
AND Enrolled.CourseId IS NULL
";
if ($stmt = $db->prepare($query)) {
// I'm assuming your ids are integers, if they're strings change "ii" to "ss"
$stmt->bind_param("ii", $UserId, $CCourseId);
if ($stmt->execute()) {
$stmt->bind_result($missing_prerequisites);
$stmt->fetch();
if ($missing_prerequisites == 0) {
// No missing prerequisites, student is allowed to enroll
$student_may_enroll = true;
}
} else {
trigger_error($stmt->error, E_USER_WARNING);
}
$stmt->close();
} else {
trigger_error($db->error, E_USER_WARNING);
}
return $student_may_enroll;
}
I can understand if the query is a bit confusing. What it does is find all prerequisites for the course from the PreReq table. For each prerequisite, it tries to find a matching course in the Enrolled table for the given student with a passing grade. It then discards those matches, so in the end it counts the number of prerequisites that the student has not passed; either because the student hasn't enrolled in it or because they don't have a passing grade for it.
If the user id is an int value you should remove the single quotes.

How to echo result from query

Maybe I am overthinking this, but I have narrowed my query to find a row down to 1 result that I need, and it will not display. Wondering if someone could tell me what I am doing wrong.
$result = mysqli_query($link, "SELECT pageid FROM article ORDER BY id DESC LIMIT 1");
$row = mysqli_use_result($result);
echo $row;
I have it selecting the last row and supplying me with the stored data from the pageid of the last row.
I had to adapt my code. I believe it was because I use mysql. However, this code will work if you use mysqli
$pageid = "SELECT pageid FROM articles ORDER BY id DESC LIMIT 1";
$resultpageid = $link->query($pageid);
if ($resultpageid->num_rows > 0) {
while ($row = $resultpageid->fetch_assoc()) {
$pagenumber = $row["pageid"];
}
} else {
echo "0 results";
}
mysqli doesn't have any function to get a single column from a single row. You need to use one of the fetch methods e.g. fetch_array(). You don't need any loop if you use LIMIT 1.
Just fetch a single row and get the column from the returned array:
$pageid = "SELECT pageid FROM articles ORDER BY id DESC LIMIT 1";
$resultpageid = $link->query($pageid);
$row = $resultpageid->fetch_assoc();
// or
$row = $resultpageid->fetch_array();
if ($row) {
echo $row["pageid"];
} else {
echo "No record found!";
}

PHP check if ID already is in use

I am currently busy with creating my own 6 player game based on PHP/MySQL. I want to check if the ID from players_online is already in use, if yes then it need to keep searching until it found one (till max 6) else it need to return 0;
$con is the connection to the database and you can find the settings on the .mysql_config.php
This is what I got:
function find_local_id()
{
include'./mysql_config.php';
$i=1;
$select_id=mysqli_fetch_assoc(mysqli_query($con, "SELECT `ID` FROM `players_online` WHERE ID = ".$i.""));
if ($select_id["ID"] == $i) {
$i++;
$select_id=mysqli_fetch_assoc(mysqli_query($con, "SELECT `ID` FROM `players_online` WHERE ID = ".$i.""));
if ($select_id["ID"] == $i) {
$i++;
$select_id=mysqli_fetch_assoc(mysqli_query($con, "SELECT `ID` FROM `players_online` WHERE ID = ".$i.""));
if ($select_id["ID"] == $i) {
$i++;
$select_id=mysqli_fetch_assoc(mysqli_query($con, "SELECT `ID` FROM `players_online` WHERE ID = ".$i.""));
if ($select_id["ID"] == $i) {
$i++;
$select_id=mysqli_fetch_assoc(mysqli_query($con, "SELECT `ID` FROM `players_online` WHERE ID = ".$i.""));
if ($select_id["ID"] == $i) {
$i++;
$select_id=mysqli_fetch_assoc(mysqli_query($con, "SELECT `ID` FROM `players_online` WHERE ID = ".$i.""));
if ($select_id["ID"] == $i) {
return 0;
} else {
return 6;
}
} else {
return 5;
}
} else {
return 4;
}
} else {
return 3;
}
} else {
return 2;
}
} else {
return 1;
}
Is there a way to have this smaller/compact? Because I think this is pretty big for just a small function. :)
I think this would work:
function find_local_id()
{
include'./mysql_config.php';
$result = mysqli_query($con, "SELECT `ID` FROM `players_online`");
while($row = mysqli_fetch_assoc($result)) {
$ids[] = $row['ID'];
}
if($available = array_diff(range(0, 6), $ids)) {
return min($available);
}
return 0;
}
If you have mysqli_fetch_all use that.
Get all of the IDs in the table
See which ones (1-6) are not in the results
If any are available return the lowest one
If not return 0
First of all, you could use a loop to do this (but you don't need one).
You're hitting the DB many times unnecessarily.
Create a function or query (like the one below) that accepts one integer id and returns the count of rows.
<?php
$db = new PDO('mysql:host=localhost;dbname=yourdb', 'user', 'pass');
$id = ''; //input, whether it be a param from a function, session superglobal, GET or POST.
$exists = $db->prepare('SELECT id FROM players_online WHERE id = ?');
$exists->execute(array($id));
echo $exists->rowCount(); // if greater than 1 or equal, it exists.
You'd be far better off doing something like
$sql = "SELECT * FROM players_online WHERE id BETWEEN {$i} AND {$i}+6";
$stmt = mysqli_query($con, $sql) or die(mysqli_error($con));
$in_use = mysqli_num_rows($stmt);
If all 6 IDs are in the database, then you'll get 6 rows in $in_use. If 5 show up, then you'll get 5 rows, etc...
You seem to have a really flawed design in that you are never going to scale for more than one game at at time with this approach, are going to need to delete rows from your table to make it work when generating a new game, and are going to have problems with race conditions in cases where concurrency is high. But assuming you have a means for managing inserting player record id's in order (1,2,3, etc.). Your query can simply be:
SELECT MAX(id) FROM players_online
This will tell you the current highest id in the table. You would simply insert the next player with the id value incremented by 1 above the current max value.

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.

Returning each unique user from a MySQL table and also the count of the number of rows for each user

I am using the following MySQL query to generate a table for users in a database. The query is designed to just return one row for each user, even though there are multiple rows for each user. This works fine, however I also need to calculate the number of unique entries for each user, to enter into the table where it states HERE. Do I need to use another query to return the count for all entries, and if so how do I integrate this with the code I already have?
$query="SELECT from_user, COUNT(*) AS num FROM tracks GROUP BY from_user ORDER BY COUNT(*) DESC";
$result=mysql_query($query) or die(mysql_error());
while ($row = mysql_fetch_array($result)) {
$user = $row['from_user'];
echo "<tr>";
echo "<td>".$user."</td>";
echo "<td>uploads (**HERE**)</td>";
echo "<td>favourites (count)</td>";
echo "</tr>";
}
?>
</table>
Because you've already created the custom field 'num', you can use that to get the count!
Add the following line after user = ...
$count = $row['num'];
Then you can
echo "<td>uploads ($count)</td>";
It miss your table stucture to know your field name, but, if i well understand your question you can use count + distinct in mysql.
You can check this answer too.
SELECT DISTINCT(from_user) AS user,
COUNT(from_user) AS num
FROM tracks
GROUP BY from_user
ORDER BY num DESC";
For the second problem you can doing a second query, or do a join tracks .
I think, in your case it's easier to you to do se second query inside the loop to get all detail from 'user' result.
$query1="SELECT DISTINCT(from_user), COUNT(*) AS num
FROM tracks
GROUP BY from_user
ORDER BY COUNT(*) DESC";
$query2="SELECT * FROM tracks";
$result1=mysql_query($query1) or die(mysql_error());
$result2=mysql_query($query2) or die(mysql_error());
$user_array = array();
while ($row = mysql_fetch_array($result1)) {
$user = $row['from_user'];
$num = $row['num'];
$uploads_array = array();
while ($sub_row = mysql_fetch_array($result2)) {
if( $sub_row['from_user'] == $user ) {
//for example only due to the unknown structure of your table
$uploads_array[] = array(
"file_name" => $sub_row['file_name'],
"file_url" => $sub_row['file_url']
);
}
}
$user_array[] = array(
"name" => $user,
"num_entry" => $num,
"actions" => $uploads_array
);
}
// now the table with all data is stuctured and you can parse it
foreach($user_array as $result) {
$upload_html_link_arr = array();
$user = $result['name'];
$num_entry = $result['num_entry'];
$all_actions_from_user_array = $result['actions'];
foreach($all_actions_from_user_array as $upload) {
$upload_html_link_arr[] = sprintf('%s', $upload["file_url"],$upload["file_name"]);
}
$upload_html_link = implode(', ',$upload_html_link_arr);
$full_row = sprintf("<tr><td>%s</td><td>uploads : %s</td><td>favourites (%d)</td></tr>", $user, $upload_html_link, $num_entry);
// now just echo the full row or store it to a table for the final echo.
echo $full_row;
}
I hope this help, mike

Categories