phpBB recent posts widget

On a language website that I maintain I recently switched to a full-fledged phpBB forum from a previous solution that included a comment box on every page, provided by the online service Disqus.

phpBB is the classical choice for forum software, it is open source, based on php (as the name suggests), well supported, with a lot of information scattered around on the internet, with many useful extensions and a bewildering amount of parameters to be configured.

Here are some of the pros/cons of phpBB that I noticed in comparison to the previous set-up I used:
+ More control over the content, the comments are now stored on my server
+ Better organization of topics, possibility to move messages from one thread to another, the accumulated threads serve as some sort of knowledge-base
+ More fine-grained user permissions and moderating options. While this is useful, I would be happier with some sane defaults, as it takes quite a lot of time to play around with all these settings, to little visible benefit to the users.
+ Better integration: I can customize phpBB to closely match the looks of my site, more so than with the widgets I used previously
+ Users can create user accounts within my site
+ Since phpBB has been around for ages, most people are comfortable using it
- A lot of time wasted setting up, configuring, customizing, upgrading, etc. the software
- A lot of time wasted fighting spam. While there are many half-solutions available, in this regard running your own forum is clearly inferior to a centralized service like Disqus
- The look and feel of the forum is slightly heavy-weight and outdated (not too web2.0-y). This is not a big problem, as it is familiar even to non-technical people.
- Higher threshold for commenting. Although I tried to keep registration requirements, rules, captcha’s to a minimum, the number of messages written is somewhat smaller than in the previous system. However, the posts are longer, usually more substantial and better organized, so this is actually a +.

All in all I am quite happy with phpBB, even though it is not nearly as minimalistic as I would prefer it to be. One thing, however, that I was still missing from the Disqus days is a recent posts widget. This would be embedded on a different page than the actual forum (for example on the front page) and it would show the most recent 5-10 posts that were written in the forum. As I found no obvious ready-made solution, I wrote my own, which was not very difficult, as the database structure of the forums is quite straightforward.

You can download it below, with some explanation on how to install it. Let me know if you find it useful, or if you make any improvements to it. I spent about as much time putting it together, as it took me to write this post, so it is really nothing fancy. It is released under the WTFPL license, which means that you can … well, you know.

You can see it in action on the http://www.nebulo.ro site (text in Romanian), as it shows recent comments for the forum on the same site.

Installation

Put the following line in the web page where you want the recent comments to appear:

<div id="recent-widget"></div>

And somewhere later in the same file:

<script type="text/javascript">
httpRequest("recent-widget.php", showrecent);
function showrecent(WIDGET){
 d = document.getElementById('recent-widget');
 d.innerHTML = WIDGET;
}

function httpRequest(url, callback) {
  var httpObj = false;
  if (typeof XMLHttpRequest != 'undefined') {
    httpObj = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    try{
      httpObj = new ActiveXObject('Msxml2.XMLHTTP');
    } catch(e) {
      try{
        httpObj = new ActiveXObject('iMicrosoft.XMLHTTP');
      } catch(e) {}
    }
  }
  if (!httpObj) return;
  httpObj.onreadystatechange = function() {
    if (httpObj.readyState == 4) { // when request is complete
      callback(httpObj.responseText);
    }
  };
  httpObj.open('GET', url, true);
  httpObj.send(null);
}
</script>

This will load the recent-widget.php file that writes the actual widget and put the output into the HTML file. Upload this on your server, so that it is accessible from your main page. The only advantage to this javascript-loader is that you can easily display the same widget on many different HTML pages. Otherwise you can simply put the stuff from recent-widget.php into your own php files.

Here is the recent-widget.php

Before you upload it, you have to modify some things in it that are about the access to the forum database and links to the forum itself and you can modify other things, like the actual layout, colors used, number of posts, etc. See the TODO comments in the file for more information. This assumes that you are running phpBB with MySQL, but if you run some other database, such as SQLite, it should still be easy to modify. Obviously, this whole widget is nothing too complicated, so even if you never programmed in php, or seen an SQL query before, it is still a decent way to learn if you tweak it to work.

16 comments ↓

#1 Sean on 07.07.11 at 10:12 am

Thanks for the widget! It works great.

I have one question–the widget can’t parse emoticons, it returns this:

s:? –> (broken image) s:? –>

Any thoughts? I’m fine with it not being able to display the emoticons themselves, but it would be nice to just not display anything.

#2 lkozma on 07.09.11 at 8:37 pm

I made some small changes now, cleaning up a small portion of the code (the whole thing could use a rewrite), so now the part that removes the BBCode formatting are the lines starting with $ppost = …

After the last such line, you can add further commands if some unwanted stuff still remains in the text (such as the smiley you mention).

For example, for removing s:? you can add:
$ppost = str_replace(“s:?”, “”, $ppost);

There’s probably a systematic way of removing all BBCode smileys, if someone contributes, I’ll be happy to add it.

I didn’t get the broken image part. Is it written like this in words, or a broken image icon appears in the widget or you just mean that the smiley icon is missing?

#3 Sean on 07.26.11 at 6:46 am

I’m getting an actual broken image, not the words (broken image).

I’ll test out your new version now. Thanks so much for the response!

#4 Sean on 07.26.11 at 7:30 am

Thanks man, the cleaned up code works awesome! Here’s what I used to clean up all of my errant smilies and broken images:

$ppost = str_replace(“”, “”, $ppost);
$smilies = array(“s:D”, “s:)”, “s;)”, “s:(“, “s:P”);
$ppost = str_replace($smilies, “”, $ppost);
$ppost = preg_replace(“”,”",$ppost);

Just added all of the offending smilies to an array and removed them with an str_replace in the next line.

Also used a preg_replace to kill the broken images.

Works great!

#5 Johnny Hastings on 08.08.11 at 7:20 pm

Thanks very much for posting this! I was able to use it as a very solid starting point for a recent posts widget on my site. Much appreciated.

#6 Bethany on 09.20.11 at 3:45 pm

Can anyone help me out with this? I really like what this script can do, but I don’t like that one topic name could potentially be returned so many times while a thread is popular. Is there any way to make it so that a thread only appears once on the list, and is just bumped to the top when someone posts on it again? Does that make sense?

#7 lkozma on 09.22.11 at 9:27 pm

@Bethany: good idea, makes a lot of sense.

A quick & dirty solution is the following:

in the long line that starts with “$result = ”

insert ” group by tid ” (without quotes) just before “order”.

So you will have something like:
…user_id group by tid order by post_time…

Hope it works…

#8 Bethany on 09.23.11 at 10:20 am

Works perfectly. Thanks for your response and time. Very helpful. ;D

#9 Jim on 09.24.11 at 9:06 pm

Any way to link directly to the post, instead of linking to the thread?

#10 Jim on 09.24.11 at 9:38 pm

Also, I tried your group by fix, and it now only returns one post/topic.

Query: select phpbb_posts.post_time as post_time, phpbb_posts.post_text as post_text, phpbb_posts.topic_id as tid, phpbb_posts.forum_id as fid, phpbb_topics.topic_title as topic_title, phpbb_users.username as username, phpbb_posts.post_username as anon from phpbb_posts, phpbb_topics, phpbb_users where phpbb_posts.forum_id != 14 and phpbb_posts.forum_id != 15 and phpbb_posts.forum_id != 30 and post_approved=1 and phpbb_posts.topic_id=phpbb_topics.topic_id and phpbb_posts.poster_id=phpbb_users.user_id group by tid order by post_time desc limit 8;

#11 Bethany on 10.01.11 at 3:26 pm

I swear it was working fine for me before… but that’s impossible. o_O I’m really confused. Because now I’m having an issue where… let’s see. I THINK it’s showing the most recent CREATED threads, but not the most recent posted in threads?

Sorry to be a bother, but do you have any thoughts on this?

#12 Rune on 10.03.11 at 3:18 pm

Looks like this one doesn’t take permissions into matter. At least I still can see the officers posts when I’m logged out.

Can you confirm/deny this please?

Else, thanks for a great widget! :)

#13 Jim on 10.04.11 at 7:55 pm

@rune, I dont think it is possible to hide specific user group’s posts, but you can hide posts in a particular forum. Just add this to your WHERE clause:

phpbb_posts.forum_id != 14

so WHERE phpbb_posts.forum_id != 14 AND phpbb_posts.forum_id != 15

#14 lkozma on 10.09.11 at 6:32 pm

@Rune:
indeed, the widget as it is now ignores permissions.

@Jim:
Thanks for the workaround.

The description of the phpbb tables structure can be found at http://www.phpbbdoctor.com/doc_tables.php so other smaller modifications should not be too difficult.

#15 lkozma on 10.10.11 at 7:42 pm

@Bethany:

Yes, the simple change that I sent earlier did not show the most recent post from threads but _any_ post from the most recently modified threads. I know this is not the best, so I added the query now which should do exactly what you want, i.e. show the five most recent posts from the five most recently edited threads (one post from each thread).

I added the line to the recent-widget.php, but I copy it here as well (this should replace the quoted part in the line starting with $result=…)

“select phpbb_posts.post_time as post_time, phpbb_posts.post_text as post_text, phpbb_posts.topic_id as tid, phpbb_posts.forum_id as fid, phpbb_topics.topic_title as topic_title, phpbb_users.username as username, phpbb_posts.post_username as anon from phpbb_posts, phpbb_topics, phpbb_users where post_id IN (select * from (select max(post_id) as mpt from phpbb_posts group by topic_id order by mpt desc limit 5) alias ) AND post_approved=1 and phpbb_posts.topic_id=phpbb_topics.topic_id and phpbb_posts.poster_id=phpbb_users.user_id order by post_time desc;”

Note that the “limit 5″ is now towards the middle of the query, rather than the end, so if you want to change it to show, say, 10 newest posts, change it there.

Aside: before some MySQL expert jumps at me that this is inefficient because of the triply nested “select”, let me say that this query actually seems to be faster than the previous one, which makes sense if you think a bit about what might happen behind the scenes.

#16 Bethany on 10.11.11 at 9:29 am

I’m sorry to be a bother. Thanks so much for your help. It’s been invaluable. <3

Leave a Comment