Reputation: 90
I have a mySQL table entitled users. It has a UID, rating, username, password, etcetera.
My goal is to make a system (tribes) similar to Facebook's friends list. Each user will be able to view the profile of users and add them to their tribe. Each user is the chief of only one tribe, but can be the villager of as many tribes as he/she wants to be. The rating system would take into account all of the tribe's members ratings.
After doing some research on relational database tables and grouping, I am not clear about how I should go about setting up the tables, or the PHP code that would go along with that.
If someone can get me pointed in the right direction, it'd be much appreciated!
EDIT: One of the big problems I foresee is accepting to be in a tribe. I'm not sure how you account for this.
Upvotes: 2
Views: 116
Reputation: 57388
similar to Facebook's friends list. Each user will be able to view the profile of users and add them to their tribe. Each user is the chief of only one tribe
Okay, so you have a User
table, and also will need a Tribe
table.
Then the relations you're describing are a chief-of
, which is one-to-one (one user can be chief of one tribe; one tribe has only one chief), therefore you can either store this within User
(chief_of: Tribe) or within Tribe
(chief: User).
CREATE TABLE User ...
chief_of integer
Here, chief_of
might be a foreign key so that if you delete a tribe, the relevant tuple will have its chief_of
set to NULL (a user can't be chief of a no longer existing tribe).
The membership is a bit more complicated because one user can belong to several tribes, and a tribe will have more than one member.
This is a many-to-many relationship and is usually done with a table holding key pairs:
CREATE TABLE member_of (
user_id integer,
tribe_id integer
);
Both fields are natural candidates for foreign keys. Here you can find a similar implementation using Authors
and Books
.
To indicate that Bob is a member of the Clan of the Cave Bear, you retrieve the ids of Bob and Bears, and insert a tuple in member_of
.
To retrieve all members of the clan, you can use a JOIN:
SELECT Users.* FROM Users
JOIN member_of ON (Users.user_id = member_of.user_id)
WHERE member_of.tribe_id =
(SELECT tribe_id FROM Tribes WHERE tribe_name = 'Clan of the Cave Bear');
I think that a shorter version of that ON in MySQL is USING(user_id)
(meaning that both tables have an identical column identically named), but in my opinion the ON
is clearer.
You can also retrieve a virtual "is_chief" column:
SELECT Users.*, chief_of = tribe_id AS is_chief FROM Users
JOIN member_of ON (Users.user_id = member_of.user_id)
WHERE member_of.tribe_id =
(SELECT tribe_id FROM Tribes WHERE tribe_name = 'Clan of the Cave Bear');
The one user whose chief_of
attribute is equal to the tribe id will have is_chief
set to TRUE, which is equal to 1, so
SELECT Users.*, chief_of = tribe_id AS is_chief FROM Users
JOIN member_of ON (Users.user_id = member_of.user_id)
WHERE member_of.tribe_id =
(SELECT tribe_id FROM Tribes WHERE tribe_name = 'Clan of the Cave Bear')
ORDER BY (chief_of = tribe_id) DESC, user_name;
will retrieve the users in alphabetical order, except the chief, who, if present, will come first.
As for the acceptance into the tribe, this identifies three states: a user is not in a tribe, a user is in the tribe, a user asked to be in a tribe. The first two are actually two faces of the same attribute member_of
. So naturally we might create a new attribute and call it wants_in
. It would map to a table identical to member_of
.
A chief could retrieve all tuples of wants_in
whose tribe_id
is equal to his own chief_of
(so if it's NULL, meaning he's not a chief, this will automatically return nothing). Then he might see this as a table of checkboxes with user names. When he approves the join, for each approval you delete the tuple from wants_in
and put it into member_of
.
Or you might decide that "membership" is a state in itself, so that you have a more complex join table
user_id,
tribe_id,
status
where status
could be, say,
Upvotes: 2
Reputation: 57217
It sounds like you'll need two classes: Villager
and Tribe
.
Then, maybe a database field called chief_of
or something that is null
if the person is not a chief, and contains the name of their tribe that they are the chief.
In the classes you can have a getChiefOf()
method that can be tested to see if the user is a chief or not.
Alternatively, you could have a table of chiefs, indexed by UID, with the same column that says which tribe they're chief of. A little less efficient but a better structure. A drawback that jumps to mind is if the UID for some reason is changed, two tables would have to be updated, so maybe the first one's better.
Upvotes: 2