Roll Your Own Static Commenting System in PHP
1421 words · 8 minutes
The Terrible-ness of Commenting Systems
The current state of affairs regarding interactive comment systems is, well, terrible. It is especially awful if you're a privacy conscious person who does not generally load third-party scripts or frames on the websites you visit.
Even further, many comment systems are charging exorbitant fees for something that should be standard.
Of course, there are some really terrible options:
- Facebook Comments
- Discourse
There are some options that are better but still use too many scripts, frames, or social integrations on your web page that could impact some users:
- Disqus
- Isso
- Remark42
Lastly, I looked into a few unique ways of generating blog comments, such as using Twitter threads or GitHub issues to automatically post issues. However, these both rely on external third-party sites that I don't currently use.
Stay Static with Server-Side Comments
The main issue for my personal use-case is that my blog is completely, 100% static. I use PHP on the back-end but website visitors only see HTML and a single CSS file. No external javascript and no embedded frames.
So, how do we keep a site static and still allow users to interact with blog posts? The key actually pretty simple - I'm already using PHP, so why not rely on the classic HTML <form>
and a PHP script to save the comments somewhere? As it turns out, this was a perfect solution for me.
The second issue for my personal use-case is that I am trying to keep the contents of my website accessible over time, as described by @brandur, in his post entitled Blog with Markdown + Git, and degrade gracefully through time .
This means I cannot rely on a database for comments, since I do not rely on a database for any other part of my websites.
I blog in plain Markdown files, commit all articles to Git, and ensure that future readers will be able to see the source data long after I'm gone, or the website has gone offline. However, I still haven't committed any images served on my blog to Git, as I'm not entirely sold on Git LFS yet - for now, images can be found at img.cleberg.net.
Saving my comments back to the Git repository ensures that another aspect of my site will degrade gracefully.
Create a Comment Form
Okay, let's get started. The first step is to create an HTML form that users can see and utilize to submit comments. This is fairly easy and can be changed depending on your personal preferences.
Take a look at the code block below for the form I currently use. Note that <current-url>
is replaced automatically in PHP with the current post's URL, so that my PHP script used later will know which blog post the comment is related to.
The form contains the following structure:
<form>
- This is the form and will determine which PHP script to send the comment to.<section hidden>
- This section is hidden from the user and is used to ensure that we know which blog post sent the comment.<section>
Display Name (Optional) - Used to accept a display name, if entered.<section>
Comment (Required) - Used to accept the user's full comment. Markdown is allowed.<button>
- A button to submit the form.
Leave a Comment
Post URL
Display Name
Your Comment
Comments are saved as Markdown and cannot be edited or deleted.
Submit
Handle Comments via POST
Now that we have a form and can submit comments, we need to create a PHP script so that the server can fetch the comment data and save it. Make sure your PHP script name matches the name you entered in the action
field in your form.
See the code block below for the contents of my comment.php
script. We perform the following tasks in this script:
- Grab the POST data from the HTML form.
- Sanitize the comment data with
htmlentities
. - Set the display name to
Anonymous
if it was left blank. - Create a PHP object that combines all of this data.
- Check if our destination file
comments.json
exists. - If so, convert the PHP object to JSON and save it to the file.
- If the
comments.json
file does not exist, the script will exit with an error. You can alter this to ensure it creates the script, but my source code includes the file by default, so it will always exist. - Finally, send the user back to the
#comments
section of the blog post they just read.
If you're using Apache, make sure the www-data
user on your server has the correct permissions to your website directory or else it will not be able to write to comments.json
.
Display User Comments
Now that we can submit comments, and they are saved to the comments.json
file, let's make sure we can show those comments in each blog post.
The code block below shows the function I use to decode my comments.json
file, check if the comments apply to the current post, and then display them.
This piece of code should really be inside a function (or at least in an organized PHP workflow). Don't just copy-and-paste and expect it to work. You need to at least supply a $query
variable depending on the page visited.
Bonus: Create a 'Recent Comments' Page
Finally, the last part of my current system is to create a Recent Comments page so that I can easily check-in on my blog and moderate any spam. As an alternative, you could use PHP's mail()
function to email you for each blog comment.
The code to do this is literally the same code as the previous section, I just make sure it is printed when someone visits https://example.com/comments/
.
Possible Enhancements
This comment system is by no means a fully-developed system. I have noted a few possible enhancements here that I may implement in the future:
- Create a secure moderator page with user authentication at
https://blog.example.com/mod/
. This page could have the option to edit or delete any comment found incomments.json
. - Create a temporary file, such as
pending_comments.json
, that will store newly-submitted comments and won't display on blog posts until approved by a moderator. - Create a
/modlog/
page with a chronological log, showing which moderator approved which comments and why certain comments were rejected.