A Simple Stack Overflow-Style Badge Framework for PHP

badgesI'm pretty infatuated with Stack Overflow's badge system, so I decided to cook up a generic framework for adding one to my crossword site. Herein I will present my work in progress for the consumption of my dear readers.

The storage of these badge-awarding rules seemed interesting to me. It'd have to be flexible enough to take data from any part of the site related to a user, and not be a hassle to add new badges or check a user's list of acquired badges. I haven't put the caching in yet, which would form the basis for making awarded badges permanent, instead of calculated on the fly, but it's still pretty fun to work with.

I started off by creating a simple Badge interface.


interface Badge {
  public function getActive();
  public function validFor($user);
  public function toString();
  public function getColor();

Then tossed in a little abstract class to handle some defaults:


abstract class AbstractBadge implements Badge {
  public function getColor() {
    return "#cccccc";

  public function getActive() {
    return true;

  public function toString() {
    return "Default";

Now I needed a way to go through these badges and find out which applied to a User object. I wanted to use a plugin style system where I'd just need to have a directory full of these Badge implementors and it would figure out which ones to apply. This bit is certainly in-progress, but works well enough to demonstrate.



class Badges extends ArrayObject {
  public function __construct() {
    $badgedir = opendir(BADGE_DIR);
    while ($f = readdir($badgedir)) {
      if (preg_match('/Badge\.php$/',$f)) {
        try {
          include BADGE_DIR.'/'.$f;
          $cls = str_replace('.php','',$f);
          $badge = new $cls;
          if ($badge instanceof Badge) {
            if ($badge->getActive())
        } catch (Exception $ex) {}
    return $this;

  public function getUserBadges($user) {
    $result = new ArrayObject();
    foreach ($this as $badge) {
      if ($badge->validFor($user))
    return $result;

This iterates through the Badges in a directory (one defined by a path in my site config file, in this case), and returns all active badges for a certain user. Now it's fairly trivial to add new badges.

For example, we could have a badge that would reward the user for being me.


class AdamBadge extends AbstractBadge {
  public function validFor($user) {
    return $user->username == 'adam';

  public function toString() {
    return "Your name is Adam";

And now I'll be congratulated for being myself every time I check my user profile. What a fine feeling it is.

2 thoughts on “A Simple Stack Overflow-Style Badge Framework for PHP”

  1. Up next:

    “class AdamBadge extends AbstractBadge {
    public function validFor($user) {
    return $user->username == ‘gibzon’;

    public function toString() {
    return “You are awesome!”;

Leave a Reply

Your email address will not be published. Required fields are marked *