Trouble with checking mysqli_fetch_assoc results - php

I'm having an issue on a personal project. I'm creating a project board where a user can log in, create different projects and add tasks to them. Basically a categorised to do list.
When the user logs in they are redirected to a screen that lists their already created boards. If no boards have been created then a link to "create board" will be displayed
When the user logs in their user name is saved in a session and called with $username
I have two tables, user and boards:
USER:
+---------+----------+-----------------+------------+
| user_id | username | email | password |
+---------+----------+-----------------+------------+
| 1 | user1 | user#user1.com | pass1 |
| 2 | user2 | user#user2.com | pass2 |
| 3 | user3 | user#user3.com | pass3 |
+---------+----------+-----------------+------------+
BOARDS:
+----------+-----------------+---------+
| board_id | board_name | user_id |
+----------+-----------------+---------+
| 1 | user1-board1 | 1 |
| 2 | user1-board2 | 1 |
| 3 | user2-board1 | 2 |
| 4 | user2-board2 | 2 |
+----------+-----------------+---------+
Note user 3 hasn't created any boards.
I run the below query to pull all associated boards for the current logged in user and display the board name.
$query = "SELECT board_id, board_name, boards.user_id, username ";
$query .= "FROM boards, user ";
$query .= "WHERE boards.user_id = user.user_id ";
$query .= "AND user.username = '{$username}' ";
$set = mysqli_query($connection, $query);
This all works fine and when I run the below code I can display the board names.
while ($boards = mysqli_fetch_assoc($set)) {
echo $boards['board_name'];
echo "<hr/>";
}
The problem I am having is displaying a "create board link" when a user is logged in but hasn't created any boards. I.e user 3.
My code:
if (!mysqli_fetch_row($set)) {
echo "create board";
} else {
while ($boards = mysqli_fetch_assoc($set)) {
echo $boards['board_name'];
echo "<hr/>";
}
}
I have tried variations of the above code but this is the closet i've got. If user 3 (who has no boards) logs in, he is greeted with "create board" so I presume it works as there are no rows of data associated with that user. However, if user 1 logs in (has 2 boards) only the second board name is being displayed. If I remove the !mysqli_fetch_row code then both board names are outputted. Obviously the fetch_row is effecting the results but I can't work out why.
If anyone can offer any guidance in how to check if a user has any boards I would be very grateful. Also if anyone can explain (for my own personal development) why running fetch_row alters my result set that is passed to the while loop it would be a bonus.
Thanks in advance

This line:
if (!mysqli_fetch_row($set)) {
both fetches and consumes a row from the result set. Since you're not assigning that returned row to a variable, it's utterly lost. If there are rows found, you then go off to the else clause, now missing one row of results.
You need to check how many rows were found, THEN start consuming:
if (mysqli_num_rows($set) == 0) {
... there are no rows ...
} else {
... there are rows: loop and display them
}

Related

How to show data from two tables only for matching record

I have two tables.
First one stores user information called "users"
| user | password | email |
|:---- |:--------:| ---------------:|
| user1 | pass1 | email#email.com |
| user2 | pass1 | email#email.com |
| user3 | pass1 | email#email.com |
and second "materials" and it stores information about what every user has
| user | lumberjack| farmer etc |
|:---- |:---------:| -----------------:|
| user1| 10 | 20 |
| user2| 20 | 50 |
| user3| 30 | 40 |
I want to get data from 2nd tables but only for specific user.
I tried this but it shows materials for every user that is in both tables. And what i want to do is to show one row from 2nd table that has same user name as logged.
For example if user1 is logged i want to show that he has 10 lumberjacks and 20 farm, if user2 is logged then 20 lumberjacks 50 farms etc.
$sql = "SELECT lumberjack, stonemanson, farmer FROM materials JOIN users ON materials.user = users.user ";}
$res = $conn->query($sql);
if ($res->num_rows > 0)
{
while ($row = $res->fetch_assoc())
{
echo "Lumberjack: " . $row["lumberjack"]. " Stonemanson: " . $row["stonemanson"]. " Farmer: " . $row["farmer"]. "<br>";
}
}
Concerning your query add WHERE clause to it.
Eg if the user id is 26 SQL query will be
SELECT lumberjack, stonemanson, farmer FROM materials JOIN users ON materials.user = users.user WHERE users.user=26
And checking your table structure, if you will not need any data from the users table then you shouldn't bother to use JOIN
this will also work fine and it'll be faster
SELECT lumberjack, stonemanson, farmer FROM materials WHERE materials.user =26
NB: using query() makes your code vulnerable to SQL injection
You should use Mysqli or PDO prepared statement.
Stackoverflow has many answers on that. So after you have resolved your issue, then start read on SQL injection and use of PDO or Mysqli prepared statement

Php/Mysql count dancers from each moment added issue

I have a dance contest site and each user can login and add dance moments,
in my html table with all moments from all users i have all the data but i want in a html column to add "number of dancers for each moment added by the logged user id".
I have this:
$c = mysql_query("SELECT * FROM moments");
$dancers = 0;
while($rows = mysql_fetch_array($c)){
for($i = 1; $i <= 24; $i++){
$dan_id = 'dancer'.$i;
if($rows[$dan_id] != "" || $rows[$dan_id] != null )
$dancers++;
}
}
echo "<th class="tg-amwm">NR of dancers</th>";
echo "<td class='tg-yw4l'>$dancers</td>";
phpMyAdmin moments table: has id, clubname, category, discipline, section, and this:
But this process is count all the dancers names from all users moments.
Example for this process: You have a total of 200 dancers !
I want the process to count for me all dancers names for each moment added in the form not a total of all entire users moments, something like this: if user john has two moments added: Moment 1: 5 dancers - moment 2: 10 dancers, and so on for each user.
Let me try to put you in the right way (it seems a long post but I think it's worth the beginners to read it!).
You have been told in the comments to normalize your database, and if I were you and if you want your project to work well for a long time... I'd do it.
There are many MySQL normalization tutorials, and you can google it your self if you are interested... I'm just going to help you with your particular example and I'm sure you will understand it.
Basically, you have to create different tables to store "different concepts", and then join it when you query the database.
In this case, I would create these tables:
categories, dance_clubs, users and dancers store "basic" data.
moments and moment_dancers store foreign keys to create relations between the data.
Let's see the content to understand it better.
mysql> select * from categories;
+----+---------------+
| id | name |
+----+---------------+
| 1 | Hip-hop/dance |
+----+---------------+
mysql> select * from dance_clubs;
+----+---------------+
| id | name |
+----+---------------+
| 1 | dance academy |
+----+---------------+
mysql> select * from users;
+----+-------+
| id | name |
+----+-------+
| 1 | alex |
+----+-------+
mysql> select * from dancers;
+----+-------+
| id | name |
+----+-------+
| 1 | alex |
| 2 | dan |
| 3 | mihai |
+----+-------+
mysql> select * from moments;
+----+--------------+---------------+-------------------+
| id | main_user_id | dance_club_id | dance_category_id |
+----+--------------+---------------+-------------------+
| 1 | 1 | 1 | 1 |
+----+--------------+---------------+-------------------+
(user alex) (dance acad..) (Hip-hop/dance)
mysql> select * from moment_dancers;
+----+-----------+-----------+
| id | moment_id | dancer_id |
+----+-----------+-----------+
| 1 | 1 | 1 | (moment 1, dancer alex)
| 2 | 1 | 2 | (moment 1, dancer dan)
| 3 | 1 | 3 | (moment 1, dancer mihai)
+----+-----------+-----------+
Ok! Now we want to make some queries from PHP.
We will use prepared statements instead of mysql_* queries as they said in the comments aswell.
The concept of prepared statement can be a bit hard to understand at first. Just read closely the code and look for some tutorials again ;)
Easy example to list the dancers (just to understand it):
// Your connection settings
$connData = ["localhost", "user", "pass", "dancers"];
$conn = new mysqli($connData[0], $connData[1], $connData[2], $connData[3]);
$conn->set_charset("utf8");
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Here we explain MySQL which will be the query
$stmt = $conn->prepare("select * from dancers");
// Here we explain PHP which variables will store the values of the two columns (row by row)
$stmt->bind_result($dancerId, $dancerName);
// Here we execute the query and store the result
$stmt->execute();
$stmt->store_result();
// Here we store the results of each row in our two PHP variables
while($stmt->fetch()){
// Now we can do whatever we want (store in array, echo, etc)
echo "<p>$dancerId - $dancerName</p>";
}
$stmt->close();
$conn->close();
Result in the browser:
Good! Now something a bit harder! List the moments:
// Your connection settings
$connData = ["localhost", "user", "pass", "dancers"];
$conn = new mysqli($connData[0], $connData[1], $connData[2], $connData[3]);
$conn->set_charset("utf8");
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Query to read the "moments", but we have their main user and dancers in other tables
$stmtMoments = $conn->prepare("
select
moments.id,
(select name from users where users.id = moments.main_user_id) as main_user,
(select name from dance_clubs where dance_clubs.id = moments.dance_club_id) as dance_club,
(select name from categories where categories.id = moments.dance_category_id) as dance_category,
(select count(*) from moment_dancers where moment_dancers.moment_id = moments.id) as number_of_dancers
from moments
");
// Five columns, five variables... you know ;)
$stmtMoments->bind_result($momentId, $momentMainUser, $momentDanceClub, $momentDanceCategory, $momentNumberOfDancers);
// Query to read the dancers of the "moment" with id $momentId
$stmtDancers = $conn->prepare("
select
dancers.name as dancer_name
from
dancers join moment_dancers on dancers.id = moment_dancers.dancer_id
where
moment_dancers.moment_id = ?
");
$stmtDancers->bind_param("i", $momentId);
$stmtDancers->bind_result($momentDancerName);
// Executing the "moments" query
$stmtMoments->execute();
$stmtMoments->store_result();
// We will enter once to the while because we have only one "moment" right now
while($stmtMoments->fetch()){
// Do whatever you want with $momentId, $momentMainUser, $momentDanceClub, $momentDanceCategory, $momentNumberOfDancers
// For example:
echo "<h3>Moment $momentId</h3>";
echo "<p>Main user: $momentMainUser</p>";
echo "<p>Dance club: $momentDanceClub</p>";
echo "<p>Category: $momentDanceCategory</p>";
echo "<p>Number of dancers: $momentNumberOfDancers</p>";
echo "<p><strong>Dancers</strong>: ";
// Now, for this moment, we look for its dancers
$stmtDancers->execute();
$stmtDancers->store_result();
while($stmtDancers->fetch()){
// Do whatever you want with each $momentDancerName
// For example, echo it:
echo $momentDancerName . " ";
}
echo "</p>";
echo "<hr>";
}
$stmtUsers->close();
$stmtMoments->close();
$conn->close();
Result in browser:
And that's all! Please ask me if you have any question!
(I could post the DDL code to create the database of the example with the content data if you want)
Edited: added dancers table. Renamed moment_users to moment_dancers. Changed functionality to adapt the script to new tables and names.

Query database then email posts from where user is subbed to

So I have a subscriptions table, here's the schema
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| user_id | int(11) | YES | | NULL | |
| sub_to | int(11) | YES | | NULL | |
| date_subbed | varchar(255) | YES | | NULL | |
+-------------+------------------+------+-----+---------+----------------+
Pretty basic, here's an example row
+----+---------+--------+------------------------+
| id | user_id | sub_to | date_subbed |
+----+---------+--------+------------------------+
| 23 | 13 | 2 | 08/19/2014 07:44:49 pm |
+----+---------+--------+------------------------+
All pretty basic stuff. So user 13 is essentially subbed to user 2. So lets say that another user joins the site and another row is created with user 14 subs to user 5.
And now user 2 and user 5 post a message on the site and it gets inserted into the database. I want the users who are subscribed to someone to get an email with the newest post.
//Get user subs
$stmt = $con->prepare("SELECT * FROM subscription");
$stmt->execute();
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $key) {
print_r($key);
}
I've already tried a foreach loop but I couldn't see how it would work. So to sum things up I want to email the user when their is a new post. I'll be sending out an email every 24 hours so I don't kill the server. I want to make sure it's fully automated too. I know how to do the 24 hour time thing, but when I say automated I mean that it'll query and email by its self. Any pointers or ideas?
I figured it out. Just use ob_start(), and loop through each user. Select the posts they're subscribed to. Then inside the loop email it to each user. I used this query
SELECT
articles.*
FROM
articles
INNER JOIN subscriptions ON articles.from_id = subscriptions.sub_to
INNER JOIN users ON subscriptions.user_id = users.id
WHERE
users.email = :email
http://sqlfiddle.com/#!2/a1ceb/9
I kindof tried to do what your saying with SQL fiddle, but in trying it out it seemed impossible with the current schema. In the link above I have many comments about how you should completely redesign your schema. The query is a pretty big headache and not scalable unless you set up a new schema.
$sql="select email id from subscription";
$rs=mysql_query($sql); //resultset
if(mysql_num_rows($rs)>0) //checking whether anyone subscribed the user or not
{
while($d=mysql_fetch_array($rs))
{
$sql1="select * from subscription where sub_to in ('".$d["user_id"]."')";
$rs1=mysql_query($sql1);
while($ds=mysql_fetch_array($rs1)
{
$to=$ds["email_id"];//assuming the field for email id
$subject="";
$msg="";
#mail($to,$subject,$msg);
}
}
}
$sql="select email id from subscription";
$rs=mysql_query($sql); //resultset
if(mysql_num_rows($rs)>0) //checking whether anyone subscribed the user or not
{
while($d=mysql_fetch_array($rs))
{
$sql1="select email id from subscription where sub_to in('".$d["user_id"]."')";
$rs1=mysql_query($sql1);
while($ds=mysql_fetch_array($rs1))
{
$to=$ds["email_id"];//assuming the field for email id
$subject="";
$msg="";
#mail($to,$subject,$msg);
}//inner while end
}//outer while end
}

How to increment the search count in php/mysql?

I have a table consists of several fields (id, firstname, surname, username, search_count)
I've build a small search engine that search my table to find any match exists either in the firstname or in the surname and I am getting the results with no problems.
Now, what I am trying to do is to increment the search_count field by 1 every time there is a match!
For example let's say we have the following table users:
id | firstname | surname | username | search_count
1 | John | Mike | un1 | 0
2 | John | Jeff | un2 | 0
3 | Dale | John | un3 | 0
4 | Mike | Gorge | un4 | 0
and let's say we are searching for Jeff as a keyword
so, the query will return 1 record
what I want to do is to increment the search_count by 1 for match record
so the results will be something like as:
id | firstname | surname | username | search_count
2 | John | Jeff | un2 | `1`
and if we make a new search (e.g. John) the results should be something like:
id | firstname | surname | username | search_count
1 | John | Mike | un1 | 1
2 | John | Jeff | un2 | 2
3 | Dale | John | un3 | 1
I've tried several approach but with no luck.. So I appreciate any hints and help
here is my code...
<?php
// open the HTML page
include 'html_open.php';
// require the db connection
require '/inc/db.inc.php';
// require the error messages
require '/inc/echo.inc.php';
if (isset($_GET['keyword'])) {
$keyword = $_GET['keyword'];
if (!empty($keyword)) {
// build our search query
$search_query = "SELECT * FROM `users` WHERE `firstname` = '".mysql_real_escape_string($keyword)."' OR `surname` = '".mysql_real_escape_string($keyword)."' ORDER BY `search_count` DESC";
// run the search query
$search_query_run = mysql_query($search_query);
// search results
$search_results_num = mysql_num_rows($search_query_run);
// check query return results
if ($search_results_num>0) {
echo 'Search engine returns <strong>[ '.$search_results_num.' ]</strong> result(s) for <strong>[ '.$keyword.' ]</strong>:<br>';
// retrieving the information found
echo '<ol>';
while ($search_result_information = mysql_fetch_assoc($search_query_run)) {
//$current_search_count = ;
echo '<li>'.$search_result_information['username'].'. This user has been searched: '.$search_result_information['search_count'].' times before.</li>';
}
echo '</ol><hr>';
include 'search_form.php';
} else {
echo '<hr>Search engine returns no result for <strong>[ '.$keyword.' ]</strong>, please try another keyword.<hr>'; // hint: no result found
include 'search_form.php';
}
} else {
echo $err20_002; // hint: must insert input
include 'search_form.php';
}
} else {
echo $err20_001; // hint: form has not been submitted
include 'search_form.php';
}
// close the HTML page
include 'html_close.php';
?>
P.S. I am new to PHP / MySQL and this is my first code :)
...
while ($search_result_information = mysql_fetch_assoc($search_query_run)) {
# add this following line
mysql_query('UPDATE `users` SET search_count=search_count+1 WHERE id='.$search_result_information['id']);
# Edit. Change result to show new number
$search_result_information['search_count']++; # this adds 1 to the value (does not affect stored data in database)
echo '<li>'.$search_result_information['username'].'. This user has been searched: '.$search_result_information['search_count'].' times before.</li>';
}
...
In your case you need to fetch the found values and perform an update statement adding +1 to the search_count column
$search_query = "SELECT id, firstname, surname, username, search_count FROM `users` WHERE `firstname` = '".mysql_real_escape_string($keyword)."' OR `surname` = '".mysql_real_escape_string($keyword)."' ORDER BY `search_count` DESC";
$search_query_run = mysql_query($search_query);
// search results
$search_results_num = mysql_num_rows($search_query_run);
// check query return results
if ($search_results_num>0) {
echo 'Search engine returns <strong>[ '.$search_results_num.' ]</strong> result(s) for <strong>[ '.$keyword.' ]</strong>:<br>';
// retrieving the information found
echo '<ol>';
while ($search_result_information = mysql_fetch_assoc($search_query_run)) {
//$current_search_count = ;
$update_search = "UPDATE users SET search_count = search_count + 1 WHERE id = {$search_result_information['id']}"; // so every `id` will increment its search_count with 1. You will need to select the rows once again, to take this count, or to manually increment in PHP
mysql_query($update_search);
echo '<li>'.$search_result_information['username'].'. This user has been searched: '.$search_result_information['search_count'].' times before.</li>';
P.S.: Using mysql_* lib is strongly NOT recommended. As you can see from the red box in the official documentation http://www.php.net/manual/en/function.mysql-query.php you should choose one of the current actually supported APIs

What is the correct way to join two tables in SQL?

I have two tables. The first table holds simple user data and has the columns
$username, $text, $image
(this is called "USERDATA").
The second table holds information about which users "follow" other users, which is set up with the columns
$username and $usertheyfollow
(this is called "FOLLOWS").
What I need to do is display the data individually to each user so that it is relevant to them. This means that userABC for instance, needs to be able to view the $text and $image inputs for all of the users whom he/she follows. To do this, I believe I need to write a sql query that involves first checking who the logged in user is (in this case userABC), then selecting all instances of $usertheyfollow on table FOLLOWS that has the corresponding value of "userABC." I then need to go back to my USERDATA table and select $text and $image that has a corresponding value of $usertheyfollow. Then I can just display this using echo command or the like...
How would I write this SQL query? And am I even going about the database architecture the right way?
With tables like so:
userdata table
______________________________
| id | username | text | image |
|------------------------------|
| 1 | jam | text | image |
+------------------------------+
| 2 | sarah | text | image |
+------------------------------+
| 3 | tom | text | image |
+------------------------------+
follows table
_____________________
| userId | userFollow |
|---------------------|
| 1 | 2 |
+---------------------+
| 1 | 3 |
+---------------------+
and use the following SQL:
SELECT userdata.text, userdata.image FROM follows LEFT JOIN userdata ON follows.userFollow = userdata.id WHERE follows.userId = 1
will get all the text and images that user with id '1' follows
As it turns out, neither of these answers were right. #jam6459 was closest.
The correct answer is the following:
SELECT userdata.text, userdata.image, follows.userFollow
FROM userdata
LEFT JOIN follows ON follows.userFollow = userdata.username
WHERE follows.userId = $username
I also found it easier to not have a username correspond to an Id as in jam's table example. This is because the same user can have multiple entries in "USERDATA". I instead used username as the Id.
function get_text_image($username)
{
$sql = "SELECT * FROM USERDATA where username='".$username."'";
$result = mysql_query($sql);
while($row = mysql_fetch_array($result))
{
echo $row['text'];
echo $row['image'];
}
}
function display_data_of_followers($userid)
{
$sql = "SELECT usertheyfollow FROM follow WHERE userid = ".$userid."";
$result = mysql_query($sql);
while($row = mysql_fetch_array($result))
{
get_text_image($row['usertheyfollow']);
}
}
display_data_of_followers($userid);

Categories