Database logic for conversation (like Forum) PHP, MySql - php

I want create a page where is possible create topics and users are able to comment.
I create the table discussion with a recursive relation.
I don't if the idea is good.
How can I find the id of the parent when a user comment?
I don't if is clear...
Below you will find 3 screenshots to explain you better the situation.

I would not have the parentID point to the comment that precedes it, that's bad practice all around. The parentID should point to the topic and then when selecting all comments from the database, make a query that orders them by time or their ID to see what order they were posted in.
For example...
SELECT * FROM `discussion` WHERE `parentID` = 1 ORDER BY `time` DESC;
The parentID should be null for topics and not null (integer) for replies (the integer should point to the ID of the topic). I hope I understood what you were asking correctly.

Related

Ignoring Duplicate Records But Bumping Them Up Top

I am making a feed system similar to the way facebook works now what I am trying to implement is the duplicate functionality.
if a user writes the same post= then don't display it duplicatly as PHP normally does by default but bump it up the top so users knows another user as re-wrote it
Here's my query
$select_posts_from_groups_query = $db->query("SELECT * FROM spud_groups_posts LEFT JOIN spud_groups_members
ON spud_groups_posts.group_url = spud_groups_members.gurl WHERE member_name='$mybb_username' GROUP BY post_body ORDER BY time_posted DESC" );
how can I get it to bump it self as the latest update once a user re duplicates it it would let users know that some one else has shared it
Thanks ;)
Three solutions
Assuming you have a update timing field on your data record called time_updated, there are a couple of things you could do:
you could simply max the two:
ORDER BY max(time_posted,time_updated) DESC
This might give issues with NULL values though
substitute NULLs in the time_updated
ORDER BY nvl(time_updated, time_posted) DESC
(Oracle sql syntax nvl() substitutes NULL in the 1st param with the 2nd param - don't know what DB you are using)
always store time_updated (the best solution IMO). When creating the post (initially) set time_updated = time_created AND use
ORDER BY time_updated DESC

MySQL/PHP: Looking for matching records from three tables(Forum permissions)

Maybe I am not putting the search in correctly in Google or SOF.com, but perhaps someone is willing to assist regardless. I know this is not the best method, but I am learning and I am hoping someone can assist in this way. I have a forum system in PHP/MySQL. The forum is set up to have an ID column.
I now also have 2 tables. One is a group table and the other is a forum permission table. The group table has an ID column and a user_id column, both int. The Forum Permission table has an id, forum_id and group_id. Basically I am trying find if the user belongs to a group(Group Table) and if that group is allowed to be in that forum(Forum Permission Table). The problem is that the user can belong to multiple groups and each forum can have multiple groups assigned to it.
Is there a query which can basically just search the three tables and distinguish if the user has access to the forum? If it were just one group to one forum, or one group per user, I can figure that out, but in this case I am stuck.
Any help? Example of Table structure below:
This is the Forum Table
Forum_ID || Forum_Name
1 ||| General tal
k
For Group Table:
Group_id ||| Group_name ||| User_ID
1 ||| Administrators ||| 2
For the Forum permission table(Forum_ID corresponds to Forum_ID in the Forums Table and Group_To_Allow corresponds to Group_ID on the groups table):
ID ||| Forum_ID ||| Group_To_Allow
1 ||| 1 ||| 1
Best I can do with the formatting.
EDIT:
OK, I figured it out with the InnerJoin. So using the table structure above:
SELECT *
FROM forum_perm
INNER JOIN membergroups
ON forum_perm.forum_groupallow=membergroups.group_id
WHERE forum_perm.forum_id = 1 AND membergroups.user_id = 6
LIMIT 0,1
Forum_perm.forum_id = 1 is the id number of the forum to check for the group. Membergroups.user_id = 6 is the users id number that belongs to the that group. The limit 0,1 will limit the result to just return one result instead of looping over and over. This is good because in PHP if MySQL loops through all the results and finds one group that does not match, it will still return false. Hope this helps anyone who is trying to achieve something similar.
You could make a JOIN statement and only select the highest value with MAX() from the certain row you want. I don't know your exact table structure or how you're doing that with the forum permissions. If you have only one column in your user table (I guess that's what you have, since that's usually the case), you maybe can use it in a IN statement (WHERE field IN(...). Maybe it works to just say mysql, hey take the value of this field (if the value of this field is commata-separated). I've never done it so I don't know it works.
Maybe you should make us some screenshots from your tables in phpmyadmin, so we can give you more accurate and specific informations.
edit: It does work with just throwing the name of the column.

Capturing a row's ID to use as a table's name

Just to save anyone reading this time and trouble, DO NOT use this method to store surveys. As pointed out in the answer, this is incredibly poor programming (not to mention dangerous to kitties)
Forgive me if this question is somewhat convoluted. I'm working on building a program that allows users to create surveys and post them for users to take.
Long story short, I have a table that looks like this:
**survey_info**
id bigint(20) Auto_increment Primary Key
title varchar(255)
category bigint(20)
active tinyint(1)
length int(11)
redirect text
now, when a survey is created, a new table is also created that is custom built to hold hte input for that survey. The naming schema I'm using for these new tables is survey_{survey_id}
What I'm hoping to do is in the list of surveys, put the number of responses to a survey to the right of it.
Alright, now my actual question is this, is there a way to retrieve the number of rows in the collection table (survey_id) within the same query I'm using to gather the list of available surveys? I realize that I can do this easily by just using a second query for each survey and grab it's rowcount, but my fear is that the larger the number of surveys the user has, the more time-consuming this process will become. So is there any way to do something like:
SELECT s.id AS id, s.title AS title, c.title AS ctitle, s.active AS active, s.length AS length, s.redirect AS redirect, n.num FROM survey_info s, survey_category c, (SELECT COUNT(*) AS num FROM survey_s.id) n WHERE s.category = c.id;
I just don't know for sure how to use the s.id as part of the other table's name (or if it can even be done)
Any help, or even a point in the right direction would be appreciated!
You need to use one table for all the surveys.
Add newly created id not as a table name but as a survey id in that table.
You create a relational model that will store all surveys options in one table. This is a sample design:
survey
------
id PK
title
surveyOption
--------------
id PK
survey_id FK
option
surveyResponse
--------------
id PK
surveyOptionId FK
response

need some guidance on a php point system

am trying to build a point system which checks how much points a user have and gives a specific title to them.
I have prepared a table which the php script can refer to when checking which title should be given to a member.
MYSQL Table structure as follows:
name: ptb
structure: pts , title
For example , if you have 100 points , you gain the title - "Veteran" , if you have 500 points , you gain the title "Pro". let's say i have pts:100 , title:veteran and pts:500 , title:pro rows in the ptb table.
However i stumble upon a confusing fact.
How can i use php to determine which title to give the user by using the ptb table data?
If a user have equal or more than 100 points will gain Veteran for title BUT 500 is also MORE THAN 100 which means the php script also needs to make sure it is below 500pts .
I still not sure how to use php to do this. as i am confused myself.
I hope someone could understand and provide me some guidelines.
THANKS!
You select all records with enought points, sort the one with the highest score to the top and cut out the rest.
SELECT title FROM ptb WHERE pts <= $points ORDER BY pts DESC LIMIT 1
(PiTheNumber's solution doesn't work very well if you want to retrieve titles for multiple users)
Since the points will change over time and the mutliple users can have the same title, it sounds like this should be 2 tables:
CREATE TABLE users (
userid ...whatever type,
points INTEGER NOT NULL DEFAULT 0
PRIMARY KEY(userid)
);
CREATE TABLE titles (
title VARCHAR(50),
minpoints INTEGER NOT NULL DEFAULT 0
PRIMARY KEY (title),
UNIQUE INDEX (minpoints)
);
Then....
SELECT u.userid, u.points, t.title
FROM users u, titles t
WHERE u.points>=t.minpoints
AND ....other criteria for filtering output....
AND NOT EXISTS (
SELECT 1
FROM titles t2
WHERE t2.minpoints>=u.points
AND t2.minpoints<=t.minpoints
);
(there are other ways to write the query)

Advanced MySQL ORDER BY

I am making a basic forum using PHP and MySQL. I am using one table for all of the threads. It is named forum_posts. It has these fields:
id, creator, time, title, message, thread_reply, forum_id, locked, sticky
If the post is a new thread, then thread_reply is set to 0. Otherwise, thread_reply is set to the id of the thread that this post is replying to. On the page that shows all of the threads, I want to order the threads by the time of the last post that was replied to it. I am using this query:
SELECT `id`, `title`, `creator` FROM `forum_posts` WHERE `thread_reply` = 0 AND `forum_id` = 1 ORDER BY -`time`
The only problem is that query only orders by the time the thread was created, instead of the time the last reply was to the thread. If you don't understand what I am talking about, go look at the home page of any forum and look how it orders the threads by the time of the last post to the thread, not the time the thread was created.
I made a custom forum last week (as phpbb just didn't suit my needs).
I would first advise the following structure:
table for users
table for categories (main sections of forum)
table for threads (these are inside categories)
table for posts (these are in individual threads)
To order the posts by the last action, I simply created a field in the Threads table that was called last_action or something along those lines.
Then, when the thread is first created, I set that value to the date it was created. Then, whenever a post is edited or a new post is added to that thread, that value updates. This then means you just do:
SELECT blah, blah, blah FROM threads WHERE cat=4 ORDER BY last_action DESC
Hopefully that helps you.
Easiest way is probably to make it so that instead of using the test thread_reply=0, you use the test thread_reply=id. Make a thread starting-thread be a reply to itself. If you use that for something else it might make it a bit more messy, but you can thus do something like
SELECT * FROM
(SELECT `id`, `title`, `creator`, b.rtime FROM `forum_posts`
WHERE a.`thread_reply` = a.`id` AND `forum_id` = 1 ) a
LEFT JOIN (SELECT `thread_reply`, MAX(`time`) rtime FROM `forum_posts`
WHERE `forum_id`=1
GROUP BY `thread_reply`) b ON a.`id`=b.`thread_reply`
ORDER BY `rtime` DESC
Note that the first subquery is unnecessary, however it is probably more efficient to first filter by forum and "is it a first post".
Also, why use ORDER BY -time ASC when you could use ORDER BY time DESC?
But yes, the best way is probably just to have a table for topics, and a table for replies. (First reply in a topic is the first post; the topic itself has no inherent body text)
Use
SELECT `op`.`id`, `op`.`title`, `op`.`creator`
FROM `forum_posts` `op`, `forum_posts` `rep`
WHERE (`op`.`thread_reply` = 0 OR `op`.`thread_reply` = `rep`.`id`)
AND `op`.`forum_id` = 1
ORDER BY IF(`op`.`thread_reply` = 0, -`op`.`time`, -`rep`.`time`)
Basically what I do here is find the reply if applicable and order by its time.
If you have the possiblity:
Create two tables:
Threads: id, subject, date_created, date_last_reply, ..
Posts: id, thread_id, date, ..
SELECT * FROM threads ORDER BY date_last_reply
As you're only getting the "start" post with that query you've got no way to order by the latest reply. You need to add another column (last_reply_time etc) and have your application update that field every time a new thread is posted, and then order by that.

Categories