In my database are 2 tables: "books" and "users". I'm displaying all the books on a page and would like the option for a user to click a little link "I've Read This", similar to Facebook's Like function with statuses. The user could click that they've read the book or unclick to "unread" the book. Other users logged in could also see who has read what. I'm questioning my approach and would like to get feedback on other directions to take for something like this.
What I had in mind was to have a field in the "users" table, maybe something like "books_read", in which I would store an array of values (book_id's). On the frontend where all the books are displayed, I would query the "books_read" field and if a value matched the current book_id, then underneath that book would be something like "User X has read this".
In short, I would store an array of "book_id"s in the "users" table to collect what books each user has read. I would pull this array and compare IDs to each book queried, and if there is a match, output that the user has read that book.
Am I missing something or maybe not looking at a cleaner approach?
In a RDBMS such as MySQL, it's rarely ever a good idea to store lists in a field, especially when you know you will be looking for specific pieces in the list later on. The database can not take advantage of an index by doing that.
Instead, you should make an additional table that links users and books read. Optionally, you could call it *users_books* and move read in to its own column.
users_booksread
-----------
user_id
book_id
Create a separate table, perhaps called book_read.
In it, for each book a user likes, store the user_id and the book_id.
Then you don't have messy arrays to deal with, everything is normalized, your design will be cleaner, and your database more flexible. Additionally, your user table won't have a bunch of extra crud bolted on to it that will affect performance in unfortunate ways.
Related
I'm sort of working on a CMS type structure. I've got to the point where mostly everything is in place except for small things that I keep pondering on like this one.
So let us suppose there is a user table and an articles table. Now, ofcourse if someone 'likes' an article, the user's ID will be stored in a column in the article's table. Something like this 11241,12412,12312. (these are random user IDs)
Now lets say that there's a user's profile page as well and I want to iterate through the user's liked posts and display it there.
Now, I've thought up of 2 ways of doing this.
First method being that the article IDs that the user has liked are stored in the user's table in his row and we get it from that but this seems sort of inefficient. Because if the user has liked a lot of articles, then I could run out of space in the column of the database?
Second method would be to go through every article and see if the user's ID exists in the list of likers saved of the article. However this method would be really slow and a really bad practice, IMO.
So what's the best practice for this?
Create a table that has two columns: user_id and article_id. When a user “likes” an article, insert a row into this table. Then when you want to see which articles user #123 has liked, you can just issue a query like this:
SELECT `article_id` FROM `article_user` WHERE `user_id` = '123';
If you need the article data, it’s easy enough to just join on the article_id column:
SELECT `article`.*
FROM `article`
LEFT JOIN `article_user` ON `article`.`id` = `article_user`.`article_id`
WHERE `article_user`.`user_id` = '123';
I am learning PHP the fun way, by making something useful. I'm making a personal PHP/MYSQL website for tracking watched episodes of tv-shows, and it's going quite good so far, albeit messy.
I have a user table, a episode table and an series table. Each of these are self explanatory I guess. What I want to do is make each user in the user table able to track what episodes have been watched. (Each single episode is in the episode table with a field that joins it with the Series table to keep track)
What I cannot get my head around is this:
How can I track if said user has watched said episode?
The only solutions I've come up with is
Add a field in the episodes database with the userID and mark them as 0 or 1, which isn't a very nice solution.
Even worse; each user has a "watched_id" field with several values for each watched episodes.
I know enough to know that this is not a good approach,
how can I approach this more effectively?
You need to create a many-to-many relationship using a mapping table ie. named "watched" with the following fields
id
user_id
episode_id
watched_at
...
Hope that helps. There is a lot of documenteation on the net if your searching for "many-to-many relationship", here is just an example:
http://www.joinfu.com/2005/12/managing-many-to-many-relationships-in-mysql-part-1/
I am working on a little project where a user submits an article to MySQL, and then PHP send the post to the screen. So far so good.
Now i want to extend it to a "two level" post system, where people can comment on the articles.
The case is, i dont know how to do that.
The table i use for storing articles:
TABLE: posts
id user date avatar signature post
Should i make a new row named comments in the posts table, or should i place the comments in a seperate table? one for articles, one for comments?
All help is much appreciated.
Depends on how you use it on your website. You have to ask: "are my articles and comments essentially the same concept?" If yes, then use one table, if no, use two. On most websites articles work differently, can be categorized, editted etc., and usually need a different fields which would clutter the comments table... so in that case two tables are more reasonable. But if you conclude that on your website articles and comments are generally the same (but try to think future proof: wouldn't you need to add some article functionality in 2 months?) then you can think of articles also as of comments and have one table for them.
If you decide to merge things to one table, and you realize that you need another column to distinguish type of the post, and that some columns remain unused for some types, it is a clear warning signal you should have two tables!
This is a little subjective, but I would just set up a parent/child relationship on your posts table, make a parent_id column that is a foreign key for the id column in the same table. for extra credit, you can make it a nested set relationship which will allow you to pull the parent and all the children in one query
I have a site that scrapes all the episodes from tv.com from certain series.
So my database has a User table, a Show table, an Episode table, a Show_User table (to associate shows with users, HABTM), an Episode_Show table (to associate episodes with shows, HABTM), a Episode_User table (to associate episodes with shows, only as a way of marking them as 'watched').
Now I want to add a way of marking an episode as 'downloaded' too.
So at the moment, the Episode_User table has two fields, Episode_Id and User_Id. Should I create a new table entirely for this? Or just add a field to the Episode_User table?
I'm using CakePHP's automagic features, and don't particularly want to break it. But if I have to, I have to...
Thanks for any advice.
I don't see why you would want to create a new table for episodes a user has downloaded. To me it would make the most sense to modify the Episode_User table to have a field for watched and a field for downloaded, since it's all relating back to the same pair of entities, users and episodes.
However, any time I've stored information about a relationship between two tables in that manner, I've found that regardless of the framework I'm using, the ORM inevitably become more complicated, but I don't think there's any way around there.
With CakePHP for handling those kinds of complicated situations, read up about the model behavior, Containable. It's not very well documented in the CakePHP book, but is really quite useful in a situation where you need to use the fields in Episode_User, for example, if you needed to find all of the users that had watched a particular episode, but not downloaded it.
Also, it occurred to me, while reading your post, that you could possibly make your data model more simple by having a hasMany relationship between shows and episodes. An episode will never belong to more than one show, so your episodes table could just have another field, show_id, which related back to the show table, and you wouldn't even need the Episode_Show table.
I have set up a company intranet website built with PHP/MySQL and allow users to post reviews. After joining up on this website I have grown to like the "comment" function and would like to add that same functionality to allow users to "comment" directly to other users reviews.
Currently all reviews are stored in a single table in the DB.
1) Should I create another table to then store all the comments since there can be many comments per review?
2) Once I figure out where to store these values can the rest of this functionality be built out in PHP or will other programming need to also be introduced?
Sounds like a good plan. You can have a table like Comments(commentID, reviewID, comment_body, ...). You can then insert a new entry when adding a new comment, or select all comments with a given reviewID to display comments for a given review.
Yes, you will almost certainly implement this in PHP (the same language you use in the rest of your application). You'll also have to edit some HTML, and maybe javascript as well.
Yes and yes.
Comments should be a seperate table, because they're comments, not reviews. They are two different things, therefore, they should not go in the same table.
Once you've created that table with the appropriate references to other tables, it's just a matter of constructing a query which pulls out all of the information you need (e.g. SELECT user.user_name, comment.comment_text, comment.post_time FROM comment, user WHERE comment.user_id=user.user_id AND comment.review_id = 123, where 123 is the ID of the review you're getting comments for).
The exact layout for your comment table will depend on your specific needs, but as a minimum, you'll want to know which review it's a comment for, who posted it, when they posted it, and what they actually posted.
To insert comments, create a form on the page that displays the individual review, and when filled in, create an INSERT query which inserts into your comment table.