Joining tables in MySql to store viewed article id's - php

I have a Joomla site that I am developing and I am a novice when it comes to MySql. I need to be able to track how many articles a user has viewed and then be able to display the total number of viewed articles on the front end of the page (for instance if the user has viewed 3 articles, it should just echo the value '3' to the front end).
I'd also like to be able to store the article id and alias and be able to retrieve that data later if needed. The idea is that any particular user will be able to see how many articles they have viewed and possibly even be able to go back and review those articles (as they will no longer be displayed once viewed).
I haven't the faintest idea of where to start as far as building the table to store this data, and how to join it to the current user. Any help would be greatly appreciated, even if it is just pointing me to a good tutorial or resource.

There are three approaches, I believe:
Store All Viewed Article IDs in New Column In User Table
You could add a column to your user table to store the viewed articles. You could store the article ids as comma-separated values. Each time a new article is viewed you can append a new article ID. On the front-end, you can retrieve this string with a select statement and parse it out to get the individual IDs.
This method may not be practical with a CMS such as Joomla as adding to columns to system tables is asking for trouble.
New Table With One Row Per User
You create a new two-column table, one column has the user id and the other has the comma-separated list of viewed articles. There would be a 1-0 relationship between the existing user table and the new table.
A simple join will allow you to retrieve the viewed articles associated with the associated user.
New Table With One Row Per User/Article Combination
You create a new two-column history table which stores the user and a single viewed article ID. If a user has viewed ten articles, there will be ten rows.
Retrieving the viewed articles for a given user takes some work as you have to pull in all rows for that user and iterate through them.
Edit - Sample Code:
<?php
$config['db'] = array (
'host' => '',
'username' => '',
'password' => '',
'dbname' => ''
);
$db = new PDO('mysql:host=' . $config['db']['host'] . ';dbname='.$config['db']['dbname'],$config['db']['username'],$config['db']['password']);
$query = $db->query("SELECT user_id, article_id FROM viewed_articles WHERE user_id = 1234");
$rows = $query->fetchAll(PDO::FETCH_ASSOC);
echo '<pre>',print_r($rows,true),'</pre>';
?>
You would put in your MySQL DB and credentials in the $config array.

A good approach is to use a module to show the data and a plugin to store it.
To track the articles viewed by an user start with the Joomla documentation for plugin development. and look for content plugins.
This plugin should store, at least, the user identifier and the article identifier on a table (call it articleviews) created specially for this plugin.
To build a module check the Joomla module development. On this module you will load the data stored with the plugin from the articleviews table. Remember to index the table by user identifier, otherwise it will kill your web response as data grows.
EDIT: article identifier should be part of the index too.

Related

mysql how to allow user to update a column in a DB once with php

So I have two different tables, a users table and an articles table. The idea is to allow a user to rate an article, but only allow them to rate it once (possible change their existing rating too but I can come to that conclusion later).
As of now I just have the update value working to allow them to rate the article, but of course a user can rate an article as many times as they want.
To give you an idea of how I have everything working, when a user logins in, a session is created with their user information. So when they go to rate an article, I have the ability to check the user, I just don't know how to stop them from rating if they have already rated a specific article.
The user table consists of among other things their username and their unique ID
and the article table consists among other things the article contents, the article unique ID, and the articles rating.
I had some really sloppy ideas like when the user rates an article their ID gets stored into the articles row in some kind of "users who have rated" column, and then I can do a for loop or something to siphon out all the user IDs and then check if their ID exists in that articles entry but then each article would have a row with possibly hundreds or thousands of userIDs on it and there seems like there would be a more elegant way.
Any help or direction is appreciated :)
Create a UserRatings table which has foreign keys to the users table and the articles table, and stores a row linking the user to the article, and the rating they gave it and when it occurred.
Then if a user tried to rate it again you just check this table for the user ID/article ID combination before allowing it.
And then if you wanted got can do things like show the user a list of articles they have previously rated, etc

What is the best db architecture to capture user data related to a product table?

This is a fictitious example to try to illustrate some design choices I have...any thoughts or links deeply appreciated.
Imagine we have a MySQL database with a table (call it libTBL) that contains a row for each book in a library.
This table will be updated, by admins, as new books are added.
Users will be able to create a library of such books - that is, a list representing THEIR selected books.
Users can add a personal, private comment to each book and other meta data (when they started reading it, a review etc).
Users can also add their own books, but these books should not appear in the libTBL table.
What are best practices for capturing this user data?
When a user is created, create a row in a new table, with each book in the libTBL represented, so IF the user adds notes or other data we already have a home for it?
Create a new row in a user library table only when they make a note on a specific book?
-- One use case, though, is a user ordering their subset library...which would require a new row for each book they order (or all of them, depending on how ordering was implemented).
Use bookID and userID to query a user table for custom values for a particular book?

Display Images for Specific Users

I have a website coded in html/css and a bit of js and jQuery.
MySql is my choice of database.
I have a login-system and users can create their own accounts on my site.
The problem is, that I'm trying to somehow restrict users so that only user A can view content (in this case, images) that I have specified for him. User B can only view its own content and so on.
I tried to mess with Role Based Access Control in php but I failed.
I'm looking for a simple solution. I have one (1) table with users where the "user_id" is the primary key.
Isn't there a way to do something like this?
if(user_id == 1) {
Do somethnig here
}
Charles, as commented there are many "open source content management systems" available that do this out of the box - I personally favour http://www.silverstripe.org/
However your question is about how to structure your database and I would recommend a "many many" relationship ( https://en.wikipedia.org/wiki/Many-to-many_(data_model) ). To create this you will need a table in the middle that stores all the id's from both ends.. e.g.
member - id - plus other fields
member_image - contains only member_id and image_id
image - id - plus other fields
to complete your code example...
$sql = "SELECT 1 FROM member_image WHERE member_id = $iMemberID AND image_id = $iImageID"
...it would be "if" the above SQL returned a row or not they member can access that image

What's the best practice of getting a user's list of article likes from a database?

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';

Optimal MySQL design for user-specific activity feeds

I'm building a website that constructs both site-wide and user-specific activity feeds. I hope that you can see the structure below and share you insight as to whether my solution is doing the job. This is complicated by the fact that I have multiple types of users that right now are not stored in one master table. This is because the types of users are quite different and constructing multiple different tables for user meta-data would I think be too much trouble. In addition, there are multiple types of content that can be acted upon, and multiple types of activity (following, submitting, commenting, etc.).
Constructing a site-wide activity feed is simple because everything is logged to the main feed table and I just build out a list. I have a master feed table in MySQL that simple logs:
type of activity;
type of target entity;
id of target entity;
type of source entity (i.e., user or organization);
id of source entity.
(This is just a big reference table that points the script generating the feed to the appropriate table(s) for each feed entry).
In generating the user-specific feed, I'm trying to figure out some way to join the relationship table with the feed table, and using that to parse results. I have a relationships table, comprised of 'following' relationships, that is similar to the feed table. It is simpler though b/c only one type of user is allowed to follow other content types/users.
user/source id;
type of target entity;
id of target entity.
Columns 2 & 3 in the feed and follow table are the same, and I have been trying to use various JOIN methodologies to match them up, and then limit them by any relationships in the follow table that the user has. This is has not been very successful.
The basic query I am using is:
SELECT *
FROM (`feed` as fe) LEFT OUTER JOIN `follow` as fo
ON `fe`.`feed_target_type` = `fo`.`follow_e_type`
AND fo.follow_e_id = fe.feed_target_id
WHERE `fo`.`follow_u_id` = 1 OR fe.feed_e_id = 1
AND fe.feed_e_type = 'user'
ORDER BY `fe`.`feed_timestamp` desc LIMIT 10
This query also attempts to grab any content that the user has created (which data is logged in the feed table) that the user is, in effect, following by default.
This query seems to work, but it took me sometime to get to it and am pretty sure I'm missing a more elegant solution. Any ideas?
The first site I made with an activity feed had a notifications table where activities were logged, and then friends actions were pulled from that. However a few months down the line this hit millions of records.
The solution I am programming now pulls latest "friends" activities from separate tables and then orders by date. The query is at home, can post the example later if interested?

Categories