This post is a continuation of our series about the My Health Skills online platform project we're working on. Here I'll be delving into the dark and mysterious world of backend development.
Backend? That sounds dodgy…
Well it's certainly not. For those non-web dev readers out there, backend development refers to the 'behind the scenes' work that goes into a website. This can include the design, build and maintenance of the database that contains all the website content, validation of user-generated content and generally keeping the website error-free and running smoothly. Basically, it's the part that makes a web app like this actually work.
A project of this scope contained a varied list of requirements including:
- A simple, reliable login system
- The ability for users to register
- The ability for users to create groups within the platform
- The ability for other users to join these groups
- An area where group owners can approve members and invite other users to join
- The ability for users to create news stories and discussions within groups
- The ability for users to upload files and images and attach them to articles
- An area where global administrators can manage groups and users within the network
- The ability for global administrators and group owners to create announcement messages
- A notification system that logs all actions on the site and emails users when certain events occur
Of course, the functionality behind these requirements could all be built entirely from scratch but that would be extremely time consuming, so we looked to a framework to help speed up the development time.
Framewhat?
A framework provides you with a solid, well thought out starting foundation from which to build your application. This will generally include a predefined directory structure as well as a bunch of functions which will make coding your application much less of a headache.
Pretty much every coding language out there has frameworks available for them. The PHP language has more than its fair share — Codeigniter, CakePHP, Zend, Yii and Symfony to name but a few. Each has its advantages and drawbacks. For this particular project we chose Laravel.
As far as frameworks go, Laravel is a bit of a new kid on the block. It combines some of the best features of other frameworks around, including Ruby On Rails, ASP.NET MVC and Sinatra, and is rapidly gaining a large and vibrant community. There are too many great features in Laravel worth mentioning, so I'll single out a few of my favourites:
Migrations & Seeding
To quote the Laravel docs:
“Migrations are a type of version control for your database.”
It allows all members of a development team to ensure that they are using the most up to date database schema. Every time the structure of the database is altered a new timestamped migration can be created, so we have a record of every version of the database structure during the project's lifecycle. These migrations are used in conjunction with Laravel's brilliant Schema Builder to generate the relevant database tables.
For example — The migration to create the users table might look something like this:
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->string('email');
$table->string('password');
$table->timestamps();
$table->softDeletes();
});
Then, all we need to do is run the following from the command line…
php artisan migrate
…and Laravel will automatically create the table in our database! No more manually creating tables in phpMyAdmin or other database management tools. This really helped us in the early stages of the project when the database structure was changing on a regular basis and needed frequent updating.
Laravel also grants us the ability to 'seed' our database with data. If some of your database tables need to contain predefined records, or you want to populate it with test data, we can use the DatabaseSeeder class.
For example, we add the following to the DatabaseSeeder.php file…
class DatabaseSeeder extends Seeder {
public function run()
{
$this->call('UsersTableSeeder');
}
}
class UsersTableSeeder extends Seeder {
public function run()
{
$user = new User;
$user->email = 'john.doe@example.com';
$user->password = 'xxxxxxxx';
$user->save();
}
}
…and then run the following from the command line…
php artisan db:seed
…Laravel will save the user record into the users table of the database for us. We used this feature extensively during the project to help rapidly prototype the initial layouts and check how they worked with varying amounts of information.
Eloquent ORM
Laravel ships with the Eloquent ORM, which makes interacting with the database a breeze. For those not in the know, ORM (Object Relational Mapping) allows us to automatically map a 'model' class to a specific table in the database.
For example, if I create User.php in my models directory and add the following code…
class User extends Eloquent {}
…Laravel now automatically knows that the User class points to the users table in the database. So to get all records from the users table we can simply use:
$users = User::all();
…or to find a specific user by their ID…
$user = User::find(1);
No more manually writing long complicated database queries! The ORM does all the hard work for us.
A feature that has been particularly useful during this project are Model Events. In simple terms, a Model Event allows us to trigger a certain action when a database record is inserted, updated or deleted. One of the requirements of this project was that every important action executed (e.g. when a new user joins, when a group is created, when someone comments on a news story) needed to be recorded and stored in the database. This allows the administrators of the site to see a complete history of all actions that have occurred within the application.
By using Model Events we can trigger a separate record to be saved in our database every time a model is interacted with. For example, in our User model that we created earlier we can add:
User::created( function( $user )
{
// Code to record that a new user was created
});
User::updated( function( $user )
{
// Code to record that a user updated their profile
});
User::deleted( function( $user )
{
// Code to record that a user deleted their profile
});
With this code in place, whenever a user record is inserted, updated or deleted anywhere in the application, a record of that action will also be saved into a separate table in the database. Swanky.
Environment Configuration
When developing websites/applications it's common practice to have multiple environments. For example, you'll probably have a local version of the application on your machine that you make any changes to, a staging version on a development server where you can test the application and a production version that is accessible by the public.
It's also common practice that you wouldn't want these environments to all behave exactly the same as each other. For example, you would want your local and staging versions to display errors on screen so that you can debug any problems but you wouldn't want users on the production environment to be able to see these errors as this could pose a security risk.
Laravel makes it super easy to change configuration options between environments. In our bootstrap/start.php file we can define what domains correspond to which environments:
$env = $app->detectEnvironment(array(
'local' => array( 'mywebsite.local' ),
'staging' => array( 'staging.mywebsite.com' ),
'production' => array( 'www.mywebsite.com' )
));
We can then create directories with matching names in our config directory (e.g. config/staging) that contain the configuration options we need. Laravel automatically detects which environment we are currently viewing based on the domain.
This really is the tip of the iceberg when it comes to this framework and I could quite easily ramble on for hours about the other excellent features but I'm sure you're quite geeked out by now. If you're a backend developer I would heartily recommend downloading Laravel and having a play with it. You'll be wondering how you ever lived without it!
We're currently building up to the launch of My Health Skills in the first half of November. The platform will be at www.myhealthskills.com once it's launched.
We'll be following this post shortly, where Hamish will be talking about some of the front-end development challanges and how we overcame them. Check out the first part of the series here.