cult3

What is Object-Relational Mapping?

Feb 11, 2013

Table of contents:

  1. Object-Relational Mapping in action
  2. Conclusion

You might have come across the term Object-Relational Mapping (ORM) if you have ever worked with a framework or on a codebase of a large project. ORM is simply a way to convert data into Objects for use in Object-Oriented Programming.

I can appreciate that the last sentence probably made no sense, so I’ll try to explain it a bit better.

As you know, as a good programmer, you should be using Object-Oriented Programming for developing your applications. Object-Oriented Programming (OOP) is simply where concepts are represented as Objects and have certain methods and attributes associated with them.

For example if we wanted to represent a User within the system, we could use something like this (in PHP):

class User {
    // Declare properties
    public $name;
    protected $email;

    // Create user on instantiation
    public function __construct($name, $email) {
        // Set name
        $this->name = $name;
        // Set email
        $this->email = $email;
    }
}

// Create new User
$philip = new User("Philip", "name@domain.com");

Whenever we create a new User, we would create a new Object to represent this user:

$elon = new User("Elon", "elon@spacex.com");

I won’t get into why you should be using an OOP approach as it is out of the scope of this tutorial. But as you can see, this is how we represent things within our code.

Now, what happens when we want to save the details of the user to a database? Databases (like MySQL for example) do not store data as Objects, but rather, as relational bits of data. This means every time you want to store or retrieve data from a database, you must convert the Object either back or forth.

Object-Relational Mapping is a technique that handles this conversion for you. An ORM will abstract all of that conversion for you so you don’t have to worry about it. This means you no longer have to write SQL statements and you have a simpler interface for working with the data.

Object-Relational Mapping in action

To really see how ORMs work, we’ll actually get in amongst some code to see it in action. Writing an ORM from scratch is obviously quite complex, especially when there are already perfect solutions available to us.

So to not re-invent the wheel, I’m going to be using Idiorm and Paris which are two minimilistic ORM implementations for PHP. Paris is “A lightweight Active Record implementation for PHP5”, whilst Idiorm is “A lightweight nearly-zero-configuration object-relational mapper and fluent query builder for PHP5”.

Installing via Composer

To install Idiorm and Paris I will be using Composer. If you are unfamiliar with Composer, take a look at my previous tutorial What is Composer?. You could manually download the files and include them, but Composer makes it so much easier.

So first, create a new directory to keep all the files together and create a Composer file with the following requirements:

{
    "require": {
        "j4mie/paris": "*"
    }
}

Next, run the following command from the Terminal to install Paris and Idiorm. Idiorm is a dependency of Paris, so it will automatically be included.

$ composer install

This should download all the required files into a new Vendors folder.

Setting up

Next we need to set up a database and make a connection. Go to phpMyAdmin and create a new database.

Next, run the following SQL statement to quickly create some fields.

CREATE TABLE IF NOT EXISTS `user` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `first` varchar(100) NOT NULL,
    `second` varchar(200) NOT NULL,
    `email` varchar(200) NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Now that the database is all set up, we need to create a PHP file to start using the ORM.

Create a new index.php file within the directory you set up earlier.

The first thing we need to do is to include the autoloader that comes with Composer. This will autoload the required files so we don’t have to include or require them:

// Include the autoloader
include "vendor/autoload.php";

Next we need to configure the database. Replace the following with your database type, database name, username and password:

ORM::configure("mysql:host=localhost;dbname=NAME");
ORM::configure("username", "USERNAME");
ORM::configure("password", "PASSWORD");

Setting up the Models

Next we can set up the Models that we are going to be using. Each entity in your project should be represented by a model. So the Users of an application should have a user table and a user model.

We already have the User table, so let’s create the User model by extending the Model Object that is available to us. We extend the Model Object because our User model will come already set up with the methods that we will need.

class User extends Model
{
}

Creating a new User

To create a new user, we can do the following:

$user = Model::factory("User")->create();
$user->first = "Philip";
$user->second = "Brown";
$user->email = "name@domain.com";
$user->save();

Here we are creating a new User object using the Create method. Next we assign the first name, second name and email, and then we save it. If you check your database, you should see the new record has saved.

This is a good example of how using an ORM completely simplifies common jobs such as creating a new User. We didn’t have to write a single line of SQL to achieve this and we didn’t have to convert the Object into a relational format for the database.

Querying

Making common queries is also very simple when you are using an ORM as everything is abstracted away.

For example, to find a user by Id we could use the following:

// Find User with the Id of 1
$user = Model::factory("User")->find_one(1);
// The User's data is now available as properties of the object
echo $user->first; // Returns 'Philip'
echo $user->second; // Returns 'Brown'
echo $user->email; // Returns 'name@domain.com'

You can also add methods to your Models, like this:

// Create the User Model
class User extends Model
{
    // Create a method to return the User's full name
    public function full_name()
    {
        return $this->first . " " . $this->last;
    }
}

// Find User with the Id of 1
$user = Model::factory("User")->find_one(1);
echo $user->full_name(); // Returns 'Philip Brown'

Conclusion

I won’t go through every possible use of Paris and Idiorm because this was an introduction to Object-Relational Mapping rather than any one particular ORM. Hopefully by using Idiorm and Paris you can see the benefits of using ORM within your project.

Philip Brown

@philipbrown

© Yellow Flag Ltd 2024.