Sunday, July 10, 2011

Commenting System

I've added a commenting system. Round of applause. This is how I added it.

The first thing to realize is that mongoDB collections can be changed on the fly. They are squishy like that. So even though the previous test posts I had added did not have comment fields this wasn't a deal breaker and I didn't have to start over or delete anything.

Step 1) Create a new php page to enter comments on. I called it commentPoster.php
            This page is passed 2 things - 1) how many comments a blog post currently has
                                                            2) the obj id of the blog post so the page can look up the item

Step 2) Modify the blog page so that the blog entries show a link under them stating how many  
            comments there are for the post. The link takes the reader to the new commenter page.

Knowing how many comments existed already was key. This allows the page to put a new comment into the new comments array in the proper place.

Here is the code.


Notice how I created the comment object with its own comments array inside. This way people can comment on other comments. This will look something like this:

Reddit Comments
Second - notice the last line which is where I update the blog entry with the new comment. I've set $n to be 1 more than the current number of comments for the blog entry. The results are that the blog entries look like this:
So you can see that it adds the number in as part of the structure. So instead of comments[1], comments[2], etc... it looks like the associative array version and is putting in the numbers themselves.


To get the number of comments link on the blog post link I did this:
After I pulled up the blog post from mongoDB I checked to see if the object had comments (all my early posts didn't). If if does have a comment field than I get the get the comments array out and use the php method sizeof to get the number of comments out.

           $numComments = 0;
          if (array_key_exists('comments', $obj)) {
            $array = $obj['comments'];
            $numComments = sizeof($array);
          }

Finally it was just a simple matter of adding the new $numComments object to the link to the commentPoster.php page.

<a href="commentPoster.php?id='.$obj['_id'].'&numComments='.$numComments.'">'.$numComments.' comments</a>

And that was that.

Until Next Time
Cheers,
TheSortedProgrammer

Friday, July 8, 2011

Progress Report P.2

Printing out the blog entries.  I dumped a bunch of blog entries I grabbed off of blogger to use as test data. This is what my vacation entry looks like:


Here is the code I'm using to display it:

Code To Show All the Blog Entries

Right away I pull up the blogs db. then grab all the entries as a Collection. Next I opened a cursor and to the Collection iterated over it.

A couple key points:
  •  I sorted the entries by date (dt) in descending order. 
      • Its a 2 step process. 
        1. Get The Collection
        2. Sort The Results

                             This is different than SQL where I would say something like:
                            SELECT * FROM BLOG ORDER BY DT DESC;
  • The Blog Entry is formatted using Text_Wiki which requires a call to                  require_once("Text/Wiki.php");
           at the beginning of the page. The $wiki object allows me to add links, lists and other formatting  easily in the blog entries. It would be great to add a nice WYSIWYG entry system like blogger uses but I can get a lot of mileage out of wiki text so its a low priority item to upgrade.

So that's where I'm at. Still need lots of features but I'm having fun with it.

Til next time
Cheers,
TheSortedProgrammer

Progress Report

I have a basic blogging site using mongodb up and running. Horah!

Basic Features:
  • Input Page without formatting
  • Blog Output Page with formatting
The Blog Entries consist of these fields:
  • User
  • Entry Title
  • Blog Entry
  • Labels
  • Date
So that's where the Collection design is at. I still need to work in comments.

So how did I get here. Let's look at some code. The first page to look at is the post-creater page.
The very modest looking page right now:

Blog Input Page
<html>
<body>
<?php
 if(isset($_POST["start"]) == false){
  $_POST["start"] = "y";
 }    
echo '<br/><p> Welcome To The Overenginered Blogger Post Creator</p> <hr\>'; 
?>

<?php
    if($_POST["start"] === "n"){       
            try{         
                date_default_timezone_set( 'America/New_York' );                             
                $conn = new Mongo();
                $db = $conn->selectDB("blog");
                $collection = $db->items;
                $item =array(
                    'title' => $_POST['title'],
                    'txt' => $_POST['txt'],
                    'labels' => $_POST['labels'],
                    'user' => $_POST['user'],
                    'dt' => new MongoDate( strtotime( date( 'Y-m-d H:i:s')))
                );
                $collection->insert($item);

                /// disconnect from server
                $conn->close();
            } catch ( MongoConnectionException $e ) {
                echo '<p>Couldn\'t connect to mongodb, is the "mongo" process running?</p>';
                exit();
            }
    }
?>

  <form action="postCreator.php" method="post">Enter a post:<br/>Title:<input type="text" name="title" /><br/><textarea name="txt" cols='88' rows="12"/><br/>Labels: <input type="text" name="labels" /><br/>User: <input type="text" name="user" /><input type="hidden" name='start' value='n' /><input type="hidden" name='action' value='i' /><input type="submit" value="Blog"/></form>
</body>
</html>

The key parts of the page are:
  1. The first few lines which checks for the POST parameter 'start' 
  2. The large chunk of code in the middle of the page is where I am connecting to mongodb and inserting a new record.
  3. The form at the bottom of the page presents a form to for user to enter a new blog entry.
The first part of the code has nothing to do with mongodb. It just handles the situation when the required argument 'start' isn't passed in by creating and setting it to 'y'. This situation happens when you first go to the page and the parameter hasn't been set yet. Once you use the form and hit 'submit' you send 'start'='n' to tell the page that you want to insert a new entry.

The second part is where the meat of the code is. I connect to the mongoDB
                $conn = new Mongo(); // connect
                $db = $conn->selectDB("blog");
                $collection = $db->items;

Then I insert the entry using the elements passed in using the form at the bottom of the page.

                 $item =array(
                    'title' => $_POST['title'],
                    'txt' => $_POST['txt'],
                    'labels' => $_POST['labels'],
                    'user' => $_POST['user'],
                    'dt' => new MongoDate(strtotime(date('Y-m-d H:i:s')))

                );

The trickiest part for me was inserting the date. My real issue was that I didn't take enough time checking out all the documentation so I missed  PHP Mongodate Class. Everything went much smoother once I found that class.  I'm so used to Oracle where I can do something like
insert into table (date_column) 
values to_date('01-Jan-2010','DD-Mon-YYYY');

So when I first hit the point I needed to put in a date I just slapped in some code:

'dt' => date('j-m-y h-i-s')
 
The problem was that this put in a String instead of a Date. This turned out to be a big issue when I went to pull up Blog Entries because I needed to pull them up by date in descending order.

DESIGN FLAW #1 - WRONG DATE TYPE

By using the MongoDate class I can now sort Blog Entries by date.

Finally,  the form is present to allow data entry. Its not a WYSIWYG editor (obviously). Right now I'm going with a WIKI Text Markup PEAR module to help bridge the gap. (More on that latter). This is a long post already so I'll save the Blog Output page for next time.

Until Then
Cheers,
TheSortedProgrammer