Using Gravatars in your Laravel application

Gravatars are immensely popular in the online world, as is Laravel for PHP based web applications these days. We can easily use Gravatars within our Laravel based applications with my SimpleGravatar package. Letting your users use one on your site has many advantages – the least being user experience. If a user has a Gravatar set up and it’s linked to their site account the instant they join, they don’t have to go to the bother of adding a site specific avatar for themselves. Similarly, if the user doesn’t have an avatar set up at all, Gravatar can provide a default image to use.

Setting up our users table

When we create our users table in Laravel (likely via a Migration – if you’re not using one, you’re doing it wrong), we’ll want to be sure to add an avatar field. This can be a simple string type field with a default value.

class CreateUsersTable extends Migration
{
	public function up()
	{
		Schema::create('users', function($table)
		{
			...
			$table->string('avatar')->default('gravatar');
			...
		});
	}

	...
}

This will mean that when a new user registers, the avatar field for their record will default to “gravatar” if they do not set a custom on-site avatar image.

Installing the package

Installing the SimpleGravatar package is extremely easy via Composer. Simply add the following line to your Laravel project’s compsoer.json file under the “require” section:

"euantor/simple-gravatar": "dev-master"

Now all we need to do is add the Service Provider to our project’s app/config/app.php file as part of the ‘providers’ array key:

	'providers' => array(
		...
		'Euantor\SimpleGravatar\SimpleGravatarServiceProvider',
		...

Adapting our User model to utilize Gravatars

Now all we have to do is adapt our User model to utilize the Gravatar if the user does not have a custom one set. To do this, we must add a new accessor method to the class:

use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;

class User extends Eloquent implements UserInterface, RemindableInterface
{
	...

	public function getAvatarAttribute($val)
	{
		if (empty($val) OR $val == 'gravatar') {
			$gravatar = App::make('simplegravatar');
			return $gravatar->setDefault('mm')->getGravatar($this->attributes['email']);
		}

		return $val;
	}

	...
}

What the above code does is check if the ‘avatar’ field is empty for the user being fetched or if it equals the string “gravatar”. If it’s either, it returns the URL to the user’s Gravatar image (or the Mystery Man default image if the user has no avatar associated to their email).

Enhancements

You may wish to implement a few enhancements to this method if using it on a live site. It’s not particularly optimal to be making remote calls to the service for all user images – what if the external server goes down for whatever reason? It might be a good idea to implement a cache type mechanism whereby user’s avatars are fetched and stored locally for a certain amount of time (or stored on a CDN). This is entirely up to you though.

The long awaited MyStatus update is almost here

I’ve been talking about updating MyStatus for over a year now and bringing it up to date. Reviewing the code base recently, this is definitely long past due.

As such, I have today started doing just that. This new update will include a lot of changes, most of which will be made in the back-end to clean up the code (including adding my new method for adding templates) but will also include some new features:

  • The ability for your users to “like” status updates. This has been requested a few times and is obviously quite a popular feature.
  • The ability for your users to comment on status updates. Again, this has been requested a few times.
  • Full MyAlerts integration for the above two new features.
  • Bump of jQuery version to 1.8 at least. The current version uses some now deprecated methods such as .live() (replaced by .on() a while back).

I don’t have any real time frame for this work’s completion (I’m still focused on finishing off version 1.0.4 of MyAlerts) but keep an eye on the GitHub repository as I slowly work on the update. I’ve already started pushing a few minor updates today such as adding a basic class to handle Status CRUD operations.

Writing super neat queries in MyBB

MyBB‘s base database class helps make things much easier in many ways by providing useful methods such as simple_select(), fetch_array() and insert_query(). Sometimes though, nothing beats writing a proper query by hand and handing it over to either the query() or write_query() methods.

When you feel the need to do this, you can simple write the query string as a parameter of the method. Or you could do what I’ve started doing in order to gain syntax highlighting (in Sublime Text anyway – not sure if other editors do this…) and that is using sprintf() to replace the table prefix into a given SQL string. For example, see below first the traditional approach.

$alerts = $this->db->write_query("SELECT a.*, u.uid, u.username, u.avatar, u.usergroup, u.displaygroup FROM ".TABLE_PREFIX."alerts a INNER JOIN ".TABLE_PREFIX."users u ON (a.from_id = u.uid) WHERE a.uid = ".(int) $this->mybb->user['uid']." AND (alert_type IN ({$alertTypes}) OR a.forced = 1) ORDER BY a.id DESC LIMIT ".(int) $start.", ".(int) $limit.";");

Notice how ugly it looks with that TABLE_PREFIX constant being needed everywhere? Why don’t we make this a little neater?

// Sanitise our variables - $alertTypes is a script built array and as such is already cleaned
$uid = (int) $this->mybb->user['uid'];
$start = (int) $start;
$limit = (int) $limit;

$queryString = "SELECT a.*, u.uid, u.username, u.avatar, u.usergroup, u.displaygroup FROM %salerts a INNER JOIN %susers u ON (a.from_id = u.uid) WHERE a.uid = {$uid} AND (alert_type IN ({$alertTypes}) OR a.forced = 1) ORDER BY a.id DESC LIMIT {$start}, {$limit};";
$alerts = $this->db->write_query(sprintf($queryString, TABLE_PREFIX, TABLE_PREFIX));

With this cleaner method our SQL string is nicely formatted and colour schemed by the editor, making finding mistakes within it much easier:

Ooh, pretty highlighting…

Obviously, there may be a slight performance hit using this method, but I haven’t really benchmarked it. I just love how much neater my code looks. If anybody does feel the need to benchmark it, feel free to post your results in the comments below!

Preparing for MyBB 1.8

As anybody who regularly visits either the MyBB Community or the MyBB Blog will know, the alpha version of MyBB 1.8 was made public on GitHub today. Months of preparation have led to this day and it’s now finally here.

As the blog points out, this is only an alpha version of the latest and greatest in forum software and as such should not be used in a live environment. Ever. If you’re determined to try the alpha out for development purposes, do so in a localhost environment. There are a few reasons behind this – though the main one is that we won’t be providing any support until we at least reach the beta milestone.

This is an extremely exciting time for MyBB as a project though and I urge everybody to get involved in some capacity – even if it is to just install a local copy and drool over the sexy new theme. The project has often been criticised in the past for it’s less than open development principles where only core members of the team could access and contribute to code. This is now completely different. Users can fork, commit and submit pull requests against the core to help the advancement of the software even further.

Getting Started with the MyBB 1.8 alpha

I know not everybody is a git pro (I myself struggle with it occasionally too…) and as such, here’s a simple guide on how to fork the main repository, clone it to your local machine and start playing. The first thing we need to do is actually fork the repository:

Simply head to the repository mybb/mybb then click the fork button at the top right of the screen and confirm the fork to your account.

You now have a copy of the repository stored within your account. Time to clone it to your machine to actually start playing. To do this, we’ll open a terminal window (or a git shell if you’re using Windows). The first thing to do is to change the current working directory into the area where you wish to clone the code to. In my case, this will be my Desktop. We’ll then clone the actual repository:

cd ~/Desktop
git clone https://github.com/euantor/mybb.git mybb-current

Obviously, you’ll change the actual URL to point to your forked version of the repository. Running the above commands should give you an output similar to the below:

Yay! Our source code is now available at ~/Desktop/mybb-current

We can now open our favourite text editor and start changing code around. If you wish to install this copy, it’s probably best to copy the code into your htdocs so your web server can access it (or use PHP’s shiny new built in test server using “php -S localhost:8080 index.php”). You should also then add a .gitignore file to ignore your ./inc/config.php and ./inc/settings.php files – we hardly want them being made public on github should we commit our edits back to our repository after all, do we?

.DS_Store
install/
install/*
inc/config.php
inc/settings.php

That’s pretty much all there is to it. Pretty easy, eh? Hope you all enjoy playing with the new Alpha version and contribute wherever possible.

Laravel 4 Migrations – fixing the “Class not found” error

Laravel 4 (aka Illuminate)’s release is just around the corner. I’ve been getting to know it locally by building a few simple apps to play with some of the amazing new features. When it came to trying out the new migrations via artisan though, I continually hit an error that looked like the following:

Class x not found in var/www/...

After much searching on google and posing a question on Stack Overflow, I finally found my answer in the Laravel IRC channel. The problem lies with Composer rather than Laravel. To make things quicker, Composer apparently caches its class autoloads. In most cases, this is fine as running the artisan command to create a new migration clears this cache. In my case though, the cache was not cleared and as such my new migration class was not being autoloaded. This can be very easily fixed by running the following command in your terminal while in your project root:

php composer.phar dump-autoload

Now you should be able to run your migration as you always would have done and shouldn’t encounter any errors.

Templating MyBB plugins the super easy way

There are many different techniques used to add new templates via MyBB plugins. I’ve seen people building arrays within their plugin files, using XML files and more. In this post though, I will outline my current favourite way that makes use of standard HTML files and PluginLibrary along with PHP’s DirectoryIterator.

There are a few advantages to this in my opinion, though the two main ones are as follows:

  • You write your templates in your text editor within a single HTML file for each one. This means your editor can provide syntax highlighting – making life much easier.
  • You keep long winded HTML code out of your main plugin file meaning it is much easier to read.

The first thing to do to use this technique is to set up your directory structure within the ./inc/plugins folder as follows:

--inc
    --plugins
        --pluginName
            --templates
                // Template files will go here
            // Any classes or other files for your plugin will go here
        // Main plugin file will go here

As you can see, we have a folder named templates within a directory with the same name as our plugin. All of our templates will be stored in single HTML files within this directory.

Now all we have to do is iterate through that folder and store the contents of each template in an array for PluginLibrary to insert. This is where the DirectoryIterator comes in!

$dir = new DirectoryIterator(dirname(__FILE__).'/pluginName/templates'); // Change this to the path for your plugin
$templates = array();
foreach ($dir as $file) {
    if (!$file->isDot() AND !$file->isDir() AND pathinfo($file->getFilename(), PATHINFO_EXTENSION) == 'html') {
        $templates[$file->getBasename('.html')] = file_get_contents($file->getPathName());
    }
}

$PL->templates(
    'pluginname',
    'pluginName',
    $templates
);

As you can see from the above code, we define our path the templates are stored in then iterate through each file in the directory, adding its contents to an array. Pretty simple, eh?

Scheduled downtime for all my sites

Dear WebFaction customer,

This email is to inform you that on 18 Dec 2012 between 04:00 and 12:00 UTC our upstream service provider will be performing maintenance to their infrastructure.

This maintenance includes moving servers from the current facility to a new state-of-the-art facility.

Apart from the servers being physically moved nothing else will change (in particular the server’s IP addresses will remain the same).

Servers will be powered off before the move and powered back on after the move. The anticipated downtime for each server is between 30 and 60 minutes.

Relating to the above, all of my sites will be unavailable on the 18th of December 2012 for a period of up to an hour. This shouldn’t cause any issues for anybody but I like to keep people informed who may be using services I host such as the gamercards.

MyBB Conversation System

It’s been requested many times on the MyBB Community Forum and I’ve decided to finally make a start on it: a conversation system for MyBB to replace the core Private message feature with an IPB style discussion feature in which messages are threaded and multiple users can participate in the thread of messages. The system will also be fully integrated with MyAlerts (of course).

I only just started working on the system 2 or 3 days ago as a side project but I already have a pretty solid start and am hopeful for a beta before the end of December. As with MyAlerts during its initial development I’ll also likely be running the plugin on mybb.euantor.com for a while to test it. The code is also available on GitHub (as ever) for those wishing to contribute to the development or just play with the existing code base in a (non-production) MyBB forum of their own.

Xbox Live statistics fetching class released

I’m a big fan of Xbox Live and have had a plugin available for MyBB for a pretty long time now titled “MyXBL” that shows a user’s Xbox Live details in  their profile and provides a basic leader board of all your members. I’ve also had my own gamercard generator available at card.euantor.com for goodness knows how long. I today decided to release my code that I use for fetching statistics and wrap it all up into a simple PHP class people can use in their own projects. The class can be found on github and there’s a special page on-site dedicated to the project that gives a pretty basic implementation example along with the output.

Enjoy!

MyAlerts finally released

After a supremely long development cycle as far as MyBB plugins go, MyAlerts has finally been released into the wild. You can see the full details regarding the plugin either here at euantor.com or at MyBB.com.

Hopefully there should be no major bugs in the system but if you do stumble across any, I’d be thankful if you’d report them either at GitHub or in the comments section below this post.

During the course of developing this plugin there have been several large issues met, struggled against and finally overcame. I’ve learned a fairly large amount about the internals of how MyBB works and hopefully the quality of the plugin will reflect just how much effort has gone into it.

I also feel I must thank others without who’s help MyAlerts wouldn’t help. They know who they are and should give themselves a pat on the back. For those who aren’t sure, here’s a quick list. Please do forgive me if I miss you out:

  • Tierney (aka Bit ‘n bang) - thanks for all the great feature ideas!
  • Leefish - for the support with writing the Prototype version of the JavaScript
  • Omar G - for the various small code fix recommendations
  • Nathan Malcolm - for the great work in finding security issues as ever
  • Charlie Hadden - for the few small code fixes and the Pull request
  • Everybody who ever posted on my demo board – thanks guys, you really helped me out. Without your constant testing this plugin just wouldn’t exist.
  • Everybody who hassled me to get it finished. I know, I took ages. Sorry!