I am working on newsfeed and I hope I this right but I want that the image that is uploaded, is linked to the user who uploads it. I have 2 tables.
users in here the accounts are stored.
picas in here the uploaded images are stored.
I have in users a primary key called user_id and I have in the picas table a primary key called id.
I made in picas a new colomn called user_id and when an image is uploaded I tell PHP to get the id from the user who is logged in and then insert that within the user_id colomn from the table picas so I can see which user uploaded the image.
So my users table looks like this:
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| user_id | int(1) | NO | PRI | NONE | AUTO_INCREMENT |
+-------------+-------------+------+-----+---------+----------------+
And my picas table looks like this:
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | int(1) | NO | PRI | NONE | AUTO_INCREMENT |
+-------------+-------------+------+-----+---------+----------------+
| user_id | int(1) | NO | | NONE | |
+-------------+-------------+------+-----+---------+----------------+
For now I have a problem with the newsfeed. It displays different users with their avatar and names, but if I post something when I'm logged in on an account, it posts for every user. So if I have 5 different users, I log in, I upload an image, then I see 5 posts instant. Check my screenshot here for better display --> http://i.imgur.com/VXwlbra.png
Same goes for the title if you click the image. If I give up a title, then it shows also on the other users.
My code when I upload:
uploadfile.php here I store the uploaded file into the database.
<?php
if (isset($_POST['submit_pica'])) {
$newName = md5(time().$_FILES['pica']['tmp_name']).'.jpeg';
$postTitle = $_POST['postTitle'];
$ses_user = $_SESSION['username'];
$getuserid = mysqli_fetch_assoc($mysqli->query("SELECT id FROM users WHERE username='$ses_user'"));
$userid = $getuserid['id'];
$result = $mysqli->query("INSERT INTO picas (id, name, title, created_at, user_id)
VALUES (null, '$newName', '$postTitle', null, '$userid')");
echo "<script>
$('.upload_button').click(function() {
$('#uploadform').slideUp(300);
});
</script>";
move_uploaded_file($_FILES['pica']['tmp_name'], 'upload/'.$newName);
}
?>
showimages.php (here I output the images from the database.
<?php
$result = $mysqli->query("SELECT *
FROM picas, users
ORDER BY created_at DESC");
$ses_user = $_SESSION['username'];
while($pica = $result->fetch_assoc()) {
echo '<div class="image_post">
<div class="user_avatar"><img src="avatars/'.$pica['username'].'.jpeg" /></div>
<div class="user_name">'.$pica['username'].'</div> <br><br><br>
<div class="image_title">'.$pica['title'].'</div>
<img src="upload/'.$pica['name'].'" />
</div>';
}
?>
My friend says I had to create a foreign key so it created a relationship between the user_id from picas and user_id from users.
Apparently it didn't work. I got the latest version from everything.
I can only choose from: users or picas table (logic, because those are the only ones I have) and then in the option field right next to it, I can only choose id or user_id (depends on which table I choose).
It gives me the this error: http://i.imgur.com/2ukfKsH.png
In the imgur link you see also what I fill in. I go to the table: picas > structure > relation view
It isn't working. I hope using the foreign key is the solution to this problem with the newsfeed, because I want that when the image is uploaded, it outputs the user who uploaded it with the uploaded image and not that it does that + every other user that is stored in the database. Please help me. I struggle with this for already a week. It's driving me crazy!
Thanks for the care you've taken writing this question.
Pro tip: Avoid using SELECT * in queries in software. Using SELECT * allows you to be sloppy in your thinking about what you want in your result set.
Pro tip: If you want results from more than one table, use JOIN directives rather than a comma-separated list of tables. This makes you think clearly about how your tables relate to each other.
You're using this query to display your items.
SELECT * /*wrong!*/
FROM picas, users /*combinatorial explosion!*/
ORDER BY created_at DESC
This query assembles a result set using every possible combination of rows from picas and users. Lucky for you you don't have 50 users and 100 entries in picas yet, or this query would yield 5000 rows.
What you need for your query is something like this:
SELECT users.user_id, users.username,
picas.id, picas.name, picas.title, picas.created_at
FROM users
JOIN picas ON users.user_id = picas.userid
WHERE users.username = '$ses_user'
ORDER BY picas.created_at DESC
This will construct a resultset with the columns I've mentioned. It will use the criterion in the ON clause to join the data from the two tables in a way that makes sense.
Related
I have several Posts tables and one Votes table. How can I prevent inserting non-existing post_id (in Posts tables) in the Votes table?
// Posts_1 // Posts_2 // Posts_3
+----+---------+ +----+---------+ +----+---------+
| id | content | | id | content | | id | content |
+----+---------+ +----+---------+ +----+---------+
// Votes
+----+---------+
| id | post_id |
+----+---------+
It should be noted, in reality the structure of Posts tables is different. (all Posts tables have not the same structure), Then I can not combine all Posts tables as one table.
Now I want to prevent of inserting invalid rows in the Votes table. (invalid = post_id is not exist in the none of Posts tables)
So, If I have just one table, I can create a foreign key on the Votes.post_id reference to Posts.id, But the problem is having several Posts table. ok, well, Is there any suggest?
The table structure is crazy. You need to have a POST Index Table, which combines all the posts to one single place and gives it like this:
// Posts_Index
+----+---------+------------+
| id | post_id | post_table |
+----+---------+------------+
// Votes
+----+---------+
| id | post_id |
+----+---------+
Else you need to reverse map the way. So that, post_id -> votes.id.
A solution could be that you use post_table_ref in votes table to identify from which table the post has been voted for. This post_table_ref must be fixed for the whole application.
Depending on table from which post is coming from, you'll have to give post_table_ref in you votes update query.
E.g: if the post is coming from post_table_01 you'll have to set post_table_ref to 1 in votes update query. At the time of getting records from votes table you'll use the same post_table_ref in WHERE clause of your SELECT FROM VOTES query.
You can't in this data structure, because you don't have one primary key to reference, but three, which can have the same value multiple times in different tables.
Using a FK column for each posts_# table can have your Votes referencing no or multiple posts_# tables.
If you -really- need 3 or more different posts tables, you could create one central post_base table with PK and let the other posts tables reference it.
Table posts_base:
Id int primary key,
-- possibly other common data
then give the posts_# tables the posts_base.Id as FK and let Votes.post_id reference posts_base.Id!
Also, read some books about relational database design first; it's rather easy to create tables with somethin in it, but without knowing about foreign keys, normalization and the like, the database quickly becomes a messy trash dump, which can neither meet performance nor data integrity requirements.
Or, if you don't need it or want to code all that yourself (easier in the beginning than learning relational DB design, but troublesome later on), shift to NoSQL, where you just dump posts as documents and add Votes to these documents when submitted (so they can never be orphaned).
I have a store where I sell products with duration (expiration time for users).
I have a mysql table for users who look like this
| user_id | user_name | user_password | user_email |
and another one for products :
| product_id | product_name | product_price |
I'm selling two products, so now I'm wondering if should I add two columns in user table so it will look like this .
| user_id | user_name | user_password | user_email | product_one | product_two |
and in those fields put the date of expiration for the users who already bought the products (both of them will be blank by default),
or should I just make a new table for the purchased products and then store the appropriate user_id.
Thanks in advance, any help is appreciated.
The second choice is more like a 3NF (3rd Normal Form). I have some little experience in e-shops (mainly in Opencart) and in my opinion, and from whatever I've already seen, this is how they're working.
In fact, it's far better to have one more table which will hold the 'Orders' and a 'User_Id', and another table that will hold the 'Orders' and the 'Product_Ids' in them.
I'm neither a database nor an e-shop platform expert, but according to my experience, I'd go with the second one.
EDIT
I'm editing my current answer to add an example. So, you already have two tables, one for users (customers) and one for products. These two table are (as already mentioned) the following (I don't know the actual table names, so I'll put mine).
table 'users':
| user_id | user_name | user_password | user_email |
table 'products':
| product_id | product_name | product_price |
So, my suggestion is to introduce a new entity (let's name that entity 'order') and create a table that will contains each order matched with the user that made it. So the 'orders' table will be something like this:
| order_id | user_id |
Then you will have another table that will match each order with a product_id. In this table you can have also your 'expiration time' field. A sample of such table is the following:
table 'order_products':
| order_id | product_id | product_exp_date |
However, tha last table has a flaw: it has not a PRIMARY KEY. You have to be a little creative here and import a field in order to hold a primary key, such as order_product_id, which will hold a UNIQUE identifier for each separate product in each separate order. But you'll have to find a way on how to do this.
Hope this clarified my thought.
You want a separate table, which I will name users_products. This will allow you to add products. It's generally more flexible.
It will have these columns
user_id
product_id
expiration
You can find what current products a user possesses like this:
select u.user_name, u.user_email, p.product_name
from users u
left join users_products up on u.user_id = p.user_id
left join products p on up.product_id = p.product_id
and p.expiration >= NOW()
The primary key of your users_products table should be a compound key made of all three columns.
When you sell a user with ID 123 the product with id 321, expiring in 30 days, you represent that in your database with this query.
INSERT INTO users_products
(user_id, product_id, expiration)
VALUES ( 123, 321, NOW() + INTERVAL 30 DAY)
Recently I've been working on a PHP/MySQL script which reads information from a database with user info and file info stored in two separate tables.
Below are the schema's for the tables.
Table1
UID | Username | PermissionLevel
1 | First | 1
2 | Next | 3
3 | More | 2
Table2
FID | Filename | FileLevel | UploadUsername
1 | file.txt | 2 | First
2 | hand.mp4 | 1 | First
3 | 1245.dds | 1 | Next
4 | beta.sql | 3 | More
For the purpose of this message I have omitted the passwords column and the file title/description column, since they play no part in the result I am trying to achieve.
So far I have come up with this SQL code
SELECT DISTINCT table2.*,
table1.*
FROM table2 JOIN table2 ON table2.FileLevel <= table1.PermissionLevel
WHERE table2.UploadUsername = table1.Username
ORDER BY FID DESC LIMIT 7
This generates the appropriate listing I want, but does not filter the level of content shown.
Any user with a PermissionLevel of 1 should only see Files with a FileLevel of 1. Users with PermissionLevel of "2" can see files of FileLevel of both 2 AND 1, and so on.
But at the current stage it seems to just want to display ALL results regardless of File/Permission Level.
I've been stuck at this issue for a couple of days now and just can't seem to get my head around this.
It's likely to be something simple I may have overlooked, but I hope that a fresh pair of eyes may help me.
I'm not sure if I understand the question fully, but this is what I could make of it. You have a query that returns all uploaded files. You now want to filter that list, so it sometimes shows less results, depending on the user's permission level. Please note that this user is the active user on the website, who is not necessarily the same user who uploaded a file, so this condition does not work on the table1 table of your query.
A common solution to this is to have a session variable storing your current user's id, and possibly other information.
$_SESSION['user'] = 'somebody';
$_SESSION['permissionLevel'] = 3;
If you don't have permissionLevel in a local variable, you will have to join on the table1 table twice, once to find the uploader and once to find the permission level of the current user. You also have a typo in your original query. The following will give you both users
SELECT *
FROM table2
JOIN table1 uploader WHERE table2.UploadUsername=table1.Username
JOIN table1 currentuser WHERE table2.PersmissionLevel<=table1.PermissionsLevel AND users.Username='$_SESSION[user]'
ORDER BY FID DESC
I have a comments section on a website i'd like to streamline a bit if possible so it's not as much of an impact on the database. When a user selects a post, and if it has comments associated with it, it lists the comments. when the comments list, it fetches the username from another table. I store the id for the user in the comments table, and use that id to select the record from the users table. and displays as "user" said:
lets say i have 1000 comments on a post, it will hit the users table 1000 times to grab user names. I think this is probably a bad design. i thought of a few solutions, but don't know what would be recommended in this situation.
should i just be storing the username inside the comments table?
should i store all of the usernames already called in a session array?
put all of the usernames in a file, and call from the file?
or is there another solution that i haven't thought of?
i'm kind of confused. I thought i was doing the right thing by using the IDs in the comment table, and then using it to fetch the username, but after reading about a million posts on using less impact on the database, i'm starting to question myself.
WOW, thanks for all of the useful answers. here is the table scheme, i don't know why i didn't put in in originally.
comments table for jokes:
id | author_id | joke_id | date_created | body
---+-----------+---------+--------------+-----
1 | 3 | 2 | 2011-06-12 | this is a comment
and for the users:
id | user_name | password | email | date_joined | visible
---+-----------+----------+-------+-------------+---------
3 | booboo | password | email | todays_date | 1
This is what JOINs are for - so that you can run a single query and efficiently get the combined information from multiple tables. E.g.:
SELECT comments.id, comments.content, users.name
FROM comments
JOIN users ON comments.user = users.id
WHERE comments.id in (1,2,3)
would look up the 3 comments with id 1, 2, and 3, plus also get the username of each commenter, and return rows that looked like this:
comments.id | comments.content | users.name
------------+-------------------+---------
1 | "First comment." | "Poster1"
2 | "Second comment." | "Poster2"
3 | "Third comment." | "Poster3"
It sounds like you have a userID field in your comments table, but need to look up the username, correct? If so, a JOIN would be the best solution.
Something like:
SELECT *
FROM `comments`
LEFT JOIN `users` ON `users`.`id` = `comments`.`userid`
WHERE `postid`='1'
To read more on joins and their endless possibilities, read up here
SELECT * FROM comments LEFT JOIN users ON comments.posterid = users.id
Google for LEFT JOIN for more info :)
Do you allow the same username to be used more than once? If not, then I would use the username field as the PK of your users table and store that in the commentstable as the FK. That'll solve your issue nicely.
If changing the PK of your users table is too much of an issue, then just store the username in the comments section since you can still use that select a single record from your users table.
I currently have a couple tables that I'm joining together so I can form all of the relevenat results into a news feed of recent activity. The only problem I'm having is figuring out which table the information is coming from.
$recentActivity = mysql_query("
SELECT *
FROM members
LEFT JOIN market
ON members.id = market.user
LEFT JOIN sales
ON members.id = sales.uid
WHERE members.id='$id'
");
I'm then running a while loop
<? while ($recent = mysql_fetch_assoc($recentActivity)) { ?>
If the result in the loop comes from the market table I would like to be able to echo "market" or something like that and do the same if it comes from the sales table.
Hope this makes sense.
You cannot. The only possible way is to explicitly specify aliases for all (necessary) market table fields. Like:
SELECT members.*,
market.id AS market_id,
market.foobar AS market_foobar
etc. The same with sales table
There's this convention that a lot of people use. If I have a table, Users:
--------------------------------
| user_username | varchar(20) |
| user_email | varchar(40) |
| user_phone | varchar(13) |
---------------------------------
This allows you do have joins and know specifically what table that data came from. It's a sort of namespacing.
If you can rename your fields in the table, I would heavily consider it.