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!


What are “Models”?

I've already talked a bit about what Models are in one of my previous articles, Zend Framework from Scratch - Models and Integrating Doctrine ORM, so to avoid repeating myself, I'll write the gist of what I wrote before here. Feel free to refer to the other tutorial and read more about what Models are there.

Summary:

  • 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:

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:

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:

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:

Alternatively, you could use Laravel's dynamic methods:

Easy Inserts & Updates

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

  • Step 1 - Get/Create the model.

  • Step 2 - Set the data

  • Step 3 - Save

  • Done!

And finally, Defining Relationships.

Eloquent makes the process of defining relationships and retrieving related models simple and intuitive.

Damn right it does! Eloquent supports three types of relationships:

  1. One-to-One
  2. One-to-Many
  3. Many-to-Many

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 User has_one User_Profile. You can do that by defining a user_profile method in the User model:

Because User is our "dominant" model here (i.e. a user has a profile, and not a profile has a user), we define that a User_Profile belongs_to a User:

Once we've defined these relationship, we can then do:

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 User has_many Photo 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:

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:

With this in place, we can then take advantage of Eloquent's relationship functions:


Step 1 - Creating the Instapics Database

Instapics

Continuing with our web application, Instapics, let's start off by creating the database of our application. To do so, let's write down the desired functionalities of the application:

  • Users can login and register for an account
  • Users can follow other users to see photos they have uploaded
  • Users can upload their own photo and apply a filter to it
  • Users can comment and like photos

From this, we can deduce the database tables we'll need:

  • users

    • id (One-to-One with user_profiles.user_id, Many-to-Many with self using intermediate table relationships.follower_id and followed_id, One-to-Many with photos.user_id and photo_comments.user_id)
    • email
    • password
    • created_at
    • updated_at
  • user_profiles

    • id
    • user_id (One-to-One with users.id)
    • name
    • profile_photo
  • relationships

    • id
    • follower_id (One-to-One with users.id)
    • followed_id (One-to-One with users.id)
    • created_at
    • updated_at
  • photos

    • id (One-to-Many with photo_comments.user_id)
    • user_id (One-to-One with users.id)
    • location
    • description
    • created_at
    • updated_at
  • photo_comments

    • id
    • user_id (One-to-One with users.id)
    • photo_id (One-to-One with photos.id)
    • message
    • created_at
    • updated_at

Let's go ahead and create these tables. For this project, I'll be using MySQL; feel free to copy and paste these commands.

Alternatively, you could use migrations, but we'll review those in a future lesson.


Step 2 - Setup Laravel's Database Configuration

Before doing anything with Laravel models, we need to setup our Laravel installation's database configuration. Open application/config/database.php, to find some of these settings:

  • profile - setting this to true will log all SQL querie times into the Laravel logs. Leave this as true for now.
  • fetch - the type of returned data from PDO. Default value is PDO::FETCH_CLASS and should be left like so.
  • default - this is the name of the connection settings used by the application. The name refers to the index in the $connections array just below
  • connections - an associative array of the possible connections for your application.

    • driver - the database server type. This can be pgsql, sqlite, mysql or sqlsrv
    • host - the host name of your database server
    • database - the database name
    • username - username to use on the database server
    • password - password to use on the database server
    • charset - charset to use on the database server
    • prefix - table prefix on the database, if any
  • redis - if you plan on using Laravel's Redis library, you can set up the server information here.

For the purposes of this tutorial, we'll be using MySQL. Your database.php file should look something like this (I removed the comments, but they should be fine to keep):


Step 3 - Creating Your First Laravel Model

Begin by creating a Laravel model inside the application/models folder. Create user.php inside, and add the following code:

Now, based on our review of what the User's relationships are, we need to code the relationship methods for all of them:

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:

  • application/models/photo.php
  • application/models/photo_comment.php
  • application/models/relationship.php
  • application/models/user.php
  • application/models/user_profile.php

These files will be in the tutorial's Git repository, so if you prefer to download them, you can find them here: https://github.com/nikkobautista/laravel-tutorial


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:

Open application/views/home/index.blade.php and look for the login form. Update the form on Line 18 to submit to the action_authenticate() method:

Going back to the User_Controller, let's place some code in action_authenticate():

Let's break-down what we've done here so far:

  • We use the Input library to get the inputs from the submitted form
  • 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.

You can read more about the Input library here: http://laravel.com/docs/input#input

The Auth library

Laravel comes with its own authentication mechanism, the Auth library. It can do the following features with regards to user authentication.

Creating a hashed password

We can make use of the Hash library like so:

This method creates a salted and hashed password for a user, using the encryption key we set in the configuration file. To check if a hash is correct, you can use:

Logging in a user

For this, we use the Auth library's attempt method. Before that, though, we build a $credentials array, which is an associative array with a username and password indexes:

It's important to keep in mind that once an attempt is "successful", the user is automatically logged in.

Loggin a user in/out

Sometimes, we'll need to login a user without using the attempt method (such as when logging in a user from a link inside an email, or post-registration). We can do that with the Auth::login method:

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

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:

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:

Now we need to create the Dashboard's index page. Create application/views/dashboard/index.blade.php and append the following:

Refresh the dashboard page, you should see this:

Instapics Dashboard

Looking a bit bare? Add this to the Dashboard controller, and run it by accessing dashboard/insert_test_data on your browser:

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

Instapics Dashboard w Sample Data

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!

Tags:

Comments

Related Articles