Disqus-like comment thread logic in PHP - php

I'm trying to make a commenting thread like Disqus has done. I'm having trouble setting up the logic in PHP to display the comments such that one can reply to each comment and those comments will then stay attached to each other.
here's my MySQL comments table:
comment_id comment item_id replied_to_id time
1 hello1 1 1 1:00pm
2 hello2 1 1 2:00pm
3 hello3 1 3 3:00pm
4 hello4 2 4 4:00pm
5 hello5 1 2 2:00pm
6 hello6 1 3 6:00pm
item_id is a column which indicates the parent item that the comments are discussing.
If I pull from my database all the comments with item_id=1, then I'm not sure how to thread them such that the comment_id and replied_to_id's are appropriately matched. For example, comment_id=2 should be matched to comment_id=1.
Here's my PHP:
<?foreach($comments as $row){
if($row->comment_id==$row->replied_to_id){
echo $row->comment."-".$row->time; //desired output: hello1-1:00pm
foreach($comments as $sub_row){
if($row->comment_id!=$sub_row->replied_to_id){
echo $sub_row->comment."-".$sub_row->time;// desired output: hello2-2:00pm
foreach($comments as $sub_sub_row){
if($row->comment_id!=$sub_sub_row->replied_to_id){
echo $sub_sub_row->comment."-".$sub_sub_row->time;// desired output: hello5-5:00pm
}
}
}
}
}
else{
echo $row->comment."-".$row->time; // desired output: hello3-3:00pm
}
}
This just looks wrong. There has got to be a better way to do this.

Simple demo, not necessarily the most optimal, but working:
function displayComments(array $comments, $parentId = null) {
foreach ($comments as $comment) {
if ($comment['replied_to_id'] == $parentId) {
echo $comment['comment'];
displayComments($comments, $comment['id']);
}
}
}
This assumes top-level comments have no replied_to_id (null). Your example with comment 1 replying to 1 doesn't make much sense.

Related

Join two tables and create indexed array where each row is a category containing multiple data,

Table: policy
id
title
description
open_flg (defines published status)
open_date (defines publishing date)
1
policy title1
desc example
1
2022/02/22
2
policy title2
desc example
1
2022/02/23
Table: policy_case
id
policy_id
title
contents
open_flg
open_date
1
1
example
example
1
2022/02/22
2
2
example
example
1
2022/02/23
3
2
example
example
1
2022/02/23
I want to make a table where 'policy' is the parent and policy_case is the child. policy.id is the same as policy_case.policy_id It should be something like this:
id
title
description
case_title
case_contents
1
policy title1
desc example
example
example
1
policy title1
desc example
example
example
2
policy title2
desc example
example
example
I've used the following code:
$this->db->select('policy.id,policy.title,policy.description,case.policy_id,case.id as case_id,case.title as case_title,case.contents as case_contents');
$this->db->from('policy');
$this->db->join('policy_case case', 'case.policy_id = policy.id');
$join = $this->db->get_compiled_select();
$query = $this->db->query($join);
$data['policies'] = $query->result_array();
The only problem I have is that policy.description and policy.title will also get duplicates depending on the number of cases. If I try to use foreach to output the array data it will create 3 policy titles, instead of 2.
Here's my current page HTML (I haven't figured a way to loop the cases inside policy):
<?php foreach ($policies as $key => $val) { ?>
<h2><?php echo $val['title']; ?></h2>
<p><?php echo $val['description']; ?></p>
<h3><?php echo $val['case_title']; ?></h3>
<p><?php echo $val['case_contents']; ?></p>
<?php } ?>
You could restructure the result so that cases is an array within each policy, but it is an unnecessary step which would offer no benefit.
When iterating over your result set, you need to keep track of the previous policy, so you can decide whether to print the <h2>, or not:
<?php
$prev_policy_id = null;
foreach ($policies as $policy) {
if ($policy->policy_id != $prev_policy_id) {
echo "<h2>{$policy->title}</h2>";
echo "<p>{$policy->description}</p>";
}
echo "<h3>{$policy->case_title}</h3>";
echo "<p>{$policy->case_contents}</p>";
$prev_policy_id = $policy->policy_id;
}
?>
This is dependent on the result set being ordered by policy, so all cases in the same policy are together:
$data['policies'] = $this->db->select('case.policy_id, policy.title, policy.description, case.id as case_id, case.title as case_title, case.contents as case_contents')
->from('policy');
->join('policy_case case', 'case.policy_id = policy.id')
->order_by('policy.id', 'ASC')
->get();
Obviously, you can continue using result_array() (just add it after ->get()), I just dropped it as I find the object notation easier to read.

getting child id's from database dynamically?

I try to get the child id's of products dynamically.Below is my table structure.
parent|child
---------------------
44 | 35,6,47,5,50
---------------------
47 | 8,9
---------------------
50 | 12, 15
am going to pass only one parent id and get the child ids, and if anyone of child ids having again child, then i have to fetch that record also.example 44->35,6,47,5,50 in this 47 and 50 is having child ids, so my final output should be like this 44-> 35,6,47,8,9,5,50,12,15.
I tried below this,
$sql=mysql_fetch_assoc(mysql_query("select * from chain_product where parent='44'"));
$parent=$sql['parent'];
$child=$sql['child'];
$ex=explode(",",$child);
$count=sizeof($ex);
for($i=0;$i<$count;$i++)
{
$list=add_child($ex[$i],$child);
$check=explode(",",$list);
$chck_count=sizeof($check);
if($chck_count>$count)
{
$exit=add_child($ex[$i],$list);
print_r($exit);
}
}
function add_child($main,$ch)
{
$find=mysql_query("select * from chain_product where parent='$main'");
$res=mysql_fetch_assoc($find);
if($res)
{
$replace=$main.",".$res['child'];
$alter=str_replace($main,$replace,$ch);
echo $alter;
}
}
but i get the result like this,
35,6,47,8,9,5,5035,6,47,5,50,12,15
but i need output should be like this..
35,6,47,8,9,5,50,12,15.
can anyone help me to do this..
Your database structure isnt optimal for this, this would be better:
id | parent
1 | 0
2 | 1
3 | 1
4 | 2
5 | 2
This way you can do something recursive:
function getChilds($parent=0, $depth=0){
// Select the items for the given $parent
$query = $conn->mysqli_query("SELECT id WHERE parent=".$parent); // mysqli is better, but mysql will do fine
// get the items by the parent giving as input:
while($fetch = $query->fetch_assoc() ){
echo str_repeat('-', $depth) . " ".$fetch['id'];
getChilds($fetch['id'], $depth+1); // Use id of this line to find its childs
echo "<br />";
}
}
getChilds(0); // And start it. The 0 is optional, I personaly prefer -1. Whatever rows your boat
This is called a tree structure and should give something like this:
1
- 2
- - 4
- - 5
- 3
In this example I use an echo for display purposes, you can return the values via an array, same principle
To answer a bit better, your current structure could support a similar method, but because you use strings, it will be allow slower and alot less flexible. You can see the difference in the code you are using, and the amount I just used. If you would remove the echo's and only return arrays, it will be even smaller :)

Json Decode,Access, show and separate names with ID, every 9 names

Hello :) I give you the Json Decode below.
http://pastebin.com/XqhTMWCS
It presents my last 10 games. I need to get my 4 teamates for every game,and my 5 enemies.(names) When someone is a teamate, his "teamId" is 100 and when someone is an enemy,the "teamId" is 200. I need to separate and show them.
Like: You were playing Vayne. Your team was:
sirjack1101 playing champion ID 89
blablaa playing ID 22
blablaaa playing ID 23
blablaaaa playing ID 24
The enemy team was:
blablsaa playing ID 31
bsadaaas playing ID 12
basdasdb playing ID 53
blablsad playing ID 67
blablsav playing ID 121
I can find only the first username using this :
$recent = "My json" ;
$rec = file_get_contents($recent);
$recdat = json_decode($rec, true);
$fellow = $recdat[gameStatistics][0][fellowPlayers][0][summonerName];
echo $fellow;
And I can get only my 1st champion name using the same code... I need your help! :)
Thanks in advance!
Sounds like you just need a foreach loop to iterate over all players.
<?php
define('TEAMMATE_ID', 100);
define('ENEMY_ID', 200);
$teammates = $enemies = array();
foreach ($data['gameStatistics'][0]['fellowPlayers'] as $player) {
if ($player['teamId'] == TEAMMATE_ID) {
$teammates[] = $player['summonerName'] .' playing ID '. $player['championId'];
}
else if ($player['teamId'] == ENEMY_ID) {
$enemies[] = $player['summonerName'] .' playing ID '. $player['championId'];
}
}
// List of teammates.
print "Teammates:\n";
print implode("\n", array_slice($teammates, 0, 4));
// List of enemies.
print "Enemies:\n";
print implode("\n", array_slice($enemies, 0, 5));
?>
Hopefully I'm not way off base...

How to retrieve 1 record at a time from db

I have a table comment as follow:
Comment
comment_id cmt followupid
1 Hello 3
2 hi 4
3 Hey 2
4 wassup 1
My query is that I want to echo "Hello", "hi", "hey" , "Wassup" and other (the record continues) individualy, I have used
$comment = mysql_result($runQuery, $i,"cmt");
echo $comment;
which works fine but the problem is that it echoes all the comments at once, what I want is to echo all the comment but one at a time. the comment are in a div tag such that each the div appears only after 1 second the page is loaded. I want each comment to appear after different time interval
for e.g:
Hello to appear at 5pm (not necessarily the corect time it can be just an int)
hi 5.10 pm
hey 6.30 pm
Please Help!
The following code should give you some hints.
$result = mysql_query($runquery);
while($row=mysql_fetch_assoc($result)){
// $row contains a single row.
echo $row['cmt'], $row['comment_id']
}
Create another variable storing time divisions(or number of rows). So that different output at different time can be fetched. For eg. If your table has 24 rows(or items), then this variable shall have a value 24. Use it to divide you output times(As in 24 hours, each hour a different value).
Now, the PHP part(I am not much familiar with date and time functions in PHP, so you can totally ignore the paragraph above.
$result = mysql_query($runquery);
$j = 0;
$i = rand( 0, mysql_num_rows($result) );
while($row=mysql_fetch_assoc($result)){
// $row contains a single row.
if( $j++ = $i )
echo $row['cmt'], $row['comment_id'];
}
This will fetch one random row from the table, but not depending upon the server time.

How can I put rows of MySQL data under the appropriate titles using PHP?

I have the following MySQL table structure:
num field company phone website
1 Gas abcd 123456789 abcd.com
2 Water efgh 987654321 efgh.com
3 Water ijkl 321654987 ijkl.com
4 Heat mnop 987654321 mnop.com
5 Gas qrst 123789654 qrst.com
...
Is it possible with PHP (maybe using some mixture of GROUP_BY and ORDER_BY) to echo the data to the screen in the following format:
Gas:
abcd qrst
123456789 123789654
abcd.com qrst.com
Water:
efgh ijkl
987654321 321654987
efgh.com ijkl.com
Heat:
mnop
321654987
mnop.com
The exact format of it isn't important. I just need for the different rows of data to be listed under the appropriate field with none of the fields repeated. I've been trying to figure this out for a while now, but I'm new to PHP and I can't seem to figure out how to do this, if it's even possible, or if there's a better way to organize my data to make it easier.
To avoid performing a "Gas" query, a "Water" query and a "Heat" query, you could order the results by "field" and then handle the display in PHP...
SELECT
Field,
Company,
Phone,
Website
FROM
tblYourTable
ORDER BY
Field
In your PHP loop, you would need to keep tabs on your current "Field" and start a new list when it changes. For example:
$CurrentField = '';
... loop
if ($MyData->Field != $CurrentField) {
$CurrentField = $MyData->Field;
....
}
... end loop
I will assume that you know how to retrieve MySQL data into an array... so, we have:
[0] {
num => 1,
field => "Gas",
company => "abcd",
phone => "123456789",
website => "abcd.com"
}
[1] ... (so on)
Then create a loop like:
foreach($data as $row) {
$service = $row["field"]; //Water, Gas, etc...
unset($row["field"]); //do not add this
foreach($row as $key => $value) {
$field[$service][$key][] = $value;
}
}
The resulting array will be something like:
$field["Gas"]["company"][0] = "abcd";
$field["Gas"]["company"][1] = "qrst";
$field["Water"]["company"][0] = "efgh";
...
$field["Gas"]["phone"][0] = "123456789";
$field["Gas"]["phone"][1] = "123789654";
$field["Water"]["phone"][0] = "987654321";
...
In that way you can then generate the output:
foreach($field as $service => $infoarr) {
echo $service."\n";
foreach($infoarr as $info => $datarr) {
foreach($datarr as $datum) {
echo $datum."\t";
}
echo "\n";
}
echo "\n";
}
Theorically (untested) will output:
Gas
abcd qrst
123456789 123789654
Water
efgh ...
I hope you find it useful... There should be a better way, but I didn't thought
too much about it...

Categories