Build Web Apps from Scratch with Laravel - The Eloquent ORM

In this Nettuts+ mini-series, we’ll build a web application from scratch, while diving into a great new PHP framework that’s rapidly picking up steam, called Laravel.

In this lesson, we'll be working on an integral part of any web application: the Models. Along the way, we'll learn about Laravel’s amazing ORM implementation: Eloquent.

Review

Welcome back to our Web Applications from Scratch with Laravel series! In the first tutorial of the series, we learned a lot about Laravel and its philosophy:

What Laravel is

What makes Laravel different from other PHP frameworks

Where to download Laravel

How to setup Laravel

How Laravel's Routing system works

Some other features in Laravel's Routing system

How to create your first Laravel Controller

Some additional features with Laravel's Controllers

How to create your first Laravel View

How to use Laravel's Blade Templating Engine

If you haven't read it yet, you should take a look at the previous tutorial and give it a read - this will make it easier to understand the philosophy behind Laravel and most of what we discuss in this tutorial.

In this second part of the Laravel series, we'll be building a crucial part of our test web application, Instapics, which is the Model implementation. Without furhter ado, let's get started!

Models are representatives of the Database, and should be where all the business logic of an application resides

Controllers communicate with Models and ask them to retrieve information they need

This information is then passed by a Controller to the View and is rendered

It's very rare that a Model directly interacts with a View, but sometimes it may happen when necessary

Models can talk with other Models and aren't self-contained. They have relationships that intertwine with each other

These relationships make it easier and quicker for a Controller to get information, since it doesn't have to interact with different Models - the Models can do that themselves

Models in Laravel, or in most frameworks, are developed the same way. The difference is that Laravel give us an easy way of building these models, by providing us with general-purpose methods that most models would need - the Eloquent ORM.

The Eloquent ORM

An ORM is an object-relational mapper, and Laravel has one that you will absolutely love! It is named "Eloquent," because it allows you to work with your database objects and relationships using an eloquent and expressive syntax.

The Eloquent ORM is Laravel's built-in ORM implementation. In my opinion, it's one of the best ORM implementations I've seen so far - rivaling even Doctrine ORM. It's incredibly elegant, making use of industry-standard conventions to lessen configuration.

Conventions

For example, using an Eloquent model assumes that the table the model is representing has an id field. The id is the primary key for any record, and is used by most of Eloquent's methods.

Another thing that Eloquent correctly assumes is that your table name is the plural form of your model. For example, your User model will reference the users table. As this might not always be the standard for some, Laravel provides a way to override this: simply use the $table flag:

class User extends Eloquent {
public static $table = 'my_users';
}

This will instruct Laravel not to use the convention and instead use the specified table.

Lastly, Laravel can also automate the creation and updating of timestamps for us. To do so, add a created_at and/or updated_at column in the table, and set the $timestamp flag in the model:

class User extends Eloquent {
public static $timestamps = true;
}

Eloquent will see the flag, and automatically set the created_at field on creation, and update the updated_at field each time that a record is updated. Pretty cool, huh?

Quick Retrieval

Retrieving records is a snap with Eloquent's retrieval methods. For example, you need to find a specific user record? Just do:

$user = User::find($user_id);

This returns a User model that you can do operations on! Need to use conditionals? Let's imagine that you want to retrieve a user by email address. To accomplish this task, you might do something like:

$user = User::where('email', '=', $email)->first();

Alternatively, you could use Laravel's dynamic methods:

$user = User::where_email($email)->first();

Easy Inserts & Updates

Inserting and updating models using Eloquent can be accomplished in three steps.

To define a relationship between models, you'll need to create a method in both models that "describes" their relationships. For example, let's say a Userhas_oneUser_Profile. You can do that by defining a user_profile method in the User model:

/*
Get the User_Profile object of a User
This executes two SQL queries:
SELECT * FROM `users` WHERE `id` = $user_id
SELECT * FROM `user_profiles` WHERE `user_id` = $user_id
*/
$user = User::find($user_id);
$user_profile = $user->user_profile;
/*
We can also do it the other way around
*/
$user_profile = User_Profile::where('user_id', '=', $user_id)->first();
$user = $user_profile->user;

One thing worth noting here is another convention: Eloquent assumes that the foreign key used in User_Profile is the referenced table's name + _id. Again, if you want to change this behaviour, you can override it:

Let's say that we want to define the relationship between a User and his Photo uploads. This is a One-to-Many relationship, unlike the User-to-User Profile relationship which was One-to-One. We know that one Userhas_manyPhoto uploads, so:

The main difference here with has_one is that the function we'll use to retrieve a User's photos will now return an array of Photo objects. So, if we wanted to fetch all of a User's photos, we could do:

Nope, referring to photos as a property isn't a typo. Laravel gives us this nice bit of sugar. We could also do:

$photos = User::find($user_id)->photos()->get();

Mant-to-Many Relationships

This one is a bit tricky, but once implemented, it makes it easy to handle Many-to-Many relationships between models. Let's imagine, for example, that you, again, have a User model, and each of these Users can have multiple Groups. A Group can also have multiple Users. We'll use three tables to represent these particular relationships:

Users - table where all our users are

Groups - table where all our groups are

Group User - table which lists down all users in a group

The table structure convention Eloquent will look for will be something like this:

users

id

...other columns

groups

id

...other columns

group_user

id

user_id

group_id

...other columns

One other convention to note here is that the intermediate table, group_user, is the singular names of the two tables that it is connecting, arranged alphabetically with an underscore. Like always, we're free to override this.

Here's how the code will look inside each of the models for these three tables:

Noticeably, we make use of some advanced Many-to-Many functionality here, due to the table structure of our follower model (i.e. the users table references the relationships table which references the users table again). The has_many_and_belongs_to function has the following method signature:

This actually lets us create a model that has a Many-to-Many relationship with itself (i.e. Users follow other Users). We use followers and following method names on the User model to enable us to get a User's followers or get all the users that a single User is following, respectively.

Following the User model, create the other models. When you finish, you should have:

Step 4 - Create the User Functions for Instapics

Let's begin using our models by creating some of the user functions we'll be needing in the application. First up: user registration. From the previous tutorial, we've already created a Registration/Login Form on the home page. Right now, it's not doing anything, but let's hook it up to a User controller, authenticate action. Create application/controllers/user.php with the following code:

If the $new_user flag was checked, we create a new User, using the Hash library to generate an encrypted password.

Log in the new User with the Auth library

If the $new_user flag was unchecked, we create a $credentials array, and use it with the Auth library.

If Auth::attempt is true, it means the credentials were correct and we're logged in

Else, it means the credentials were wrong.

In both scenarios, redirect to the Dashboard controller, index action when successful, and echo a failure message if not.

The Input library

The basic function of the Input library is to enable retrieval of form data. For example, in the User controller, we used Input::get('email'); to get the email value from the form. It's important to note that the get method is used for all types of requests and not just the $_GET array.

On the other hand, we also have an Auth::logout method for logging users out:

Auth::logout();

This will terminate the user's session.

Retrieving the logged in user's data

The Auth::user method allows us to retrieve the logged in user object, as well as any information attached to it:

$email = Auth::user()->email;
$created_at = Auth::user()->created_at;

Configuring the Auth library

The Auth library has to be configured before using it (though the defaults will work with most projects, like this one). The configuration variables are:

driver - this can be either eloquent or fluent. Developers can write their own drivers by extending the Driver class in laravel/auth/drivers.

username - this is the column name of whatever represents your user's "username" in the database table.

model - when using Eloquent, this is the model class that the Auth library uses

table - when using the Fluent authentication driver, this determines the database table for the users in the application

Our project, Instapics, uses the default values in the auth.php configuration file, so we don't need to change anything in it.

Going back to the project, try testing out the login/registration features of Instapics! Pretty nifty, huh? You'll notice though that we don't have anything in the Dashboard controller yet, so let's work on that next.

Step 5 - Create the Instapics Dashboard

The first thing we need to do is create the Dashboard controller, with the index action. Create the file application/controllers/dashboard.php and put in the following code:

When you refresh the page, you'll see what it looks like with the sample data inserted:

Conclusion

In the second part of our Laravel series, we learned:

Some background on what "Models" are

What the Eloquent ORM is

How to set up Laravel's database configuration

How to create your first Laravel Model

The basic functions of the Auth and Input libraries

Making use of the Eloquent ORM in a view

Eloquent really is an awesome ORM implementation - it's fast and has tons of features that make database interactions in any application as simple as possible.

Next in our Web Applications from Scratch with Laravel series, we'll learn more about using Laravel's filters, Laravel's Validation library, and how to work with files in Laravel!

What do you think about Laravel's Eloquent ORM? Is it something that you find useful? Let me know in the comments! And, if you're a Tuts+ Premium member, stay tuned for our upcoming Laravel Essentials course!

I'm Nikko Bautista. By day, I work as a software engineer at Bright.com, where we make hiring smarter, faster, and cheaper. By night, I develop web applications and write tutorials for Tuts+.
I was born and raised in the Pearl of the Orient, the Philippines. In 2012, I moved halfway across the world and ended up in the heart of downtown San Francisco, where the culture and energy are unparalleled. It is, without a doubt, the best place to be an engineer.
I specialize in PHP and PHP frameworks. I have experience with Symfony, Zend Framework, CodeIgniter, FuelPHP, and Laravel. I like creating and maintaining developer-friendly APIs. I also have expertise in third-party APIs from Facebook, Twitter, Google, and other platforms. I often explore new technologies, frameworks, and web services by building web applications that use them. Tuts+ allows me to share what I've learned with the world.
In my free time, I love learning and reading about new technologies, innovations and the web. I also enjoy trying new restaurants, taste testing whiskies, taking long walks, and cooking new recipes.