Comment prints more than once

I've made a CMS following the tutorial by phpacademy on Youtube, and now I'm extending it by adding comments.

I got it to print the data from the database with the comments.

However, it prints it more than once.

Code:

Article.php (Where I print the articles)

<?php

include_once('includes/connection.php');
include_once('includes/article.php');
include_once('includes/comments.php');

$article = new Article;
$comment = new Comment;

if(isset($_GET['id'])){
    $id = $_GET['id'];
    $data = $article->fetch_data($id);
    $comments = $comment->fetch_data($id);
?>

<html>
    <head>
        <title>CMS</title>
        <link rel="stylesheet" type="text/css" href="assets/style.css">
    </head>
    <body>
        <div class="container">
            <a href="index.php" id="logo">CMS</a>

            <h4><?php echo $data['article_title']; ?> - <small>posted <?php echo date('l jS', $data['article_timestamp']); ?></small></h4>
            <div id="content">
                <p><?php echo $data['article_content'] ?></p>
            </div>
            <a href="index.php">&larr; Back</a><br>
            <div id="comments">
                <?php 

                foreach($comments as $comment){
                    ?>
                    <div class="comment">
                        <span class="poster">Posted <?php echo date('l jS', $comments['comment_timestamp'])." by ".$comments['poster_name']; ?></span>
                    <?php echo $comments['comment_content']; ?>

                    </div>
                <?php   
                }

                ?>
            </div>
        </div>
    </body>
</head>

<?php

}else{
    header('Location: index.php');
    exit();
}

?>

includes/Comments.php:

<?php

class Comment{
    public function fetch_all(){
        global $pdo;

        $query = $pdo->prepare("SELECT * FROM comments");
        $query->execute();

        return $query->fetchAll();
    }

    public function fetch_data($post_id){
        global $pdo;
        $query = $pdo->prepare("SELECT * FROM comments WHERE post_id = ?");
        $query->bindValue(1, $post_id);
        $query->execute();

        return $query->fetch();
    }
}

?>

If you need more code, or me to explain my problem more in detail, just comment.

Answers


I don't think your $comments array contains what you think it contains.

Right now it contains an array for a single database row, presumably a row with 5 columns of data.

This is because $comment->fetch_data($id) will only fetch a single row of data from the database. It is a poorly designed method.

As such $comments array looks something like this:

[
  0 => 'field 1 value',
  1 => 'field 2 value',
  ...
  4 => 'field 4 value',
 'field 1 name' => 'field 1 value',
  ...
  'field 5 name' => 'field 5 value'
]

Note it would have both numeric and associative indexes because you are using default PDO fetch mode (which is usually configured to fetch both numerical and associative index).

When you loop on $comments you are actually looping through these values and since you are trying to output data from $comments instead of l$comment which is locally defined for your loop. Because of this, you are actually accessing the associative keys in this $comments array.

What you want to do is to change your fetch method to fetch ALL rows in the DB result set. That might look like this:

public function fetch_data($post_id){
    global $pdo;
    $query = $pdo->prepare("SELECT * FROM comments WHERE post_id = ?");
    $query->bindValue(1, $post_id);
    $query->execute();

    $rows = array();
    while($row = $query->fetch(PDO::FETCH_ASSOC)) {
        $rows[] = $row;
    }
    return $rows;    
}

And then you need to change the echo statements in your loops to actually echo from $comment (the local variable name defined for the loop) rather than $comments.


You need to edit how you retrieve your comments using your function:

public function fetch_data($post_id){
    global $pdo;
    $query = $pdo->prepare("SELECT * FROM comments WHERE post_id = ?");
    $query->bindValue(1, $post_id);
    $query->execute();

    return $query->fetch();
}

Should be something similar to:

public function fetch_data($post_id){
    global $pdo;
    $query = $pdo->prepare("SELECT * FROM comments WHERE post_id = ?");
    $query->bindValue(1, $post_id);
    $query->execute();
    $results = array();
    while($row = $query->fetch()){
        $results[] = $row;
    }
    return $query->fetch();
}

Then it should work right as you think it should

Your array previously was:

$comments = array(
    'comment_id' => '1',
    0 => '1',
    'poster_name' => 'Mackan90096',
    1 => 'Mackan90096',
    'comment_content' => 'Hi! This is a test comment!',
    2 => 'Hi! This is a test comment!',
    'comment_timestamp' => '1385144211',
    3 => '1385144211',
    'post_id' => '4',
    4 => '4'
);

And now it will be:

$comments = array(
    0 => array(
        'comment_id' => '1',
        0 => '1',
        'poster_name' => 'Mackan90096',
        1 => 'Mackan90096',
        'comment_content' => 'Hi! This is a test comment!',
        2 => 'Hi! This is a test comment!',
        'comment_timestamp' => '1385144211',
        3 => '1385144211',
        'post_id' => '4',
        4 => '4'
    )
);

Note: using $comments as $comment as your foreach parameter is not good because $comment then overwrites your Comment class variable for later use.


Need Your Help

Bibliography as section in LaTeX / BibTeX

latex bibtex

I'm writing a short document using sections rather than chapters as the top-level (documentclass report). However,

Google OAuth Local Redirect URI

ruby-on-rails oauth devise

I've found a couple topics similar to this*, but none feature an answer that is working for me currently.