Laravel Eloquent ORM Tutorial

 

Eloquent is the very powerful and expressive ORM or Object Relational Mapper in Laravel. If you know how to work with Objects in PHP, then you know how to use Eloquent! Well, it’s not *quite* that simple, but we do have the most expressive syntax yet in PHP for working with Models by way of Eloquent. Eloquent is a massive topic, and to be fair, we should probably be going over some building blocks leading up to Eloquent, however, that is not how we roll in the good ol US of A. We’re going to jump in head first, hopefully we’ll swim!

note: In Laravel, sets that are returned as a result of an eloquent query return a collection. You can learn all about Laravel Collections over at our lengthy tutorial.
Database Table to Eloquent Model Mapping

In Laravel, each Eloquent model represents a single database table. It is important to note however, that even though a single Model maps to a single Table, we will most often be using combinations of Models in retrieving say an article, or a task, or a blog post. By way of relationships, we can query several tables to get the desired result.
From DB class to Eloquent

In the last tutorial, we covered how to do basic CRUD with Laravel by using the DB class right out of the box. Now remember, we didn’t even create any Models for that, the functionality was there right out of the box. Quite impressive! Moving on, we can now define some Models and this will be by Extending Eloquent.
Let’s build our first Eloquent Model!

We’re going to be dealing with Painters and Paintings, so we’ll create our Painter model first, but before we create our models, let’s set up our database tables with migrations like you see here:

PHP
<?php
//  painters table

use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;

class CreatePaintersTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('painters', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('username')->unique();
            $table->text('bio');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('painters');
    }

}

<?php
//  paintings table

use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;

class CreatePaintingsTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('paintings', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->integer('painter_id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('paintings');
    }

}

   
<?php
//  painters table

use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;

class CreatePaintersTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('painters', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('username')->unique();
            $table->text('bio');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('painters');
    }

}

<?php
//  paintings table

use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;

class CreatePaintingsTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('paintings', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('title');
            $table->text('body');
            $table->integer('painter_id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('paintings');
    }

}

Let’s run our migrations using php artisan migrate.

Awesome! Now we can create a Model and populate some data into our database. The following snippet will create a Painter Model which will map to the painters database table:

PHP
class Painter extends Eloquent {}
1
   
class Painter extends Eloquent {}

Ok we have our Eloquent Model created, yes I know it was painful how much we had to type! Let’s see what that one little line of code buys us by using reflection to inspect our newly created object!

PHP
Route::get('/', function()
{

$reflection = new ReflectionClass('Painter');  //  inspect the methods and constants of any class!

print_r($reflection->getMethods());
   
});

   
Route::get('/', function()
{

$reflection = new ReflectionClass('Painter');  //  inspect the methods and constants of any class!

print_r($reflection->getMethods());
   
});

The above code will output the 164 methods you find at Laravel Eloquent API – This is a bit overwhelming! But as they say, CALM YOURSELF GRASSHOPPER! We’re only going to look at a few of them to get us started. Since we already covered how to set up CRUD In Laravel 4 with the DB class, why don’t we now whip up some CRUD with Eloquent. Since we’re learning we will use:

PHP
//  listen to the queries and output them to learn!
Event::listen('illuminate.query', function($sql) {
    var_dump($sql);
});

   
//  listen to the queries and output them to learn!
Event::listen('illuminate.query', function($sql) {
    var_dump($sql);
});

This will allow us to view all queries that Laravel creates for us! This helps us put it all together.
Create

save() We can insert new records into the database a few ways in Eloquent, but my favorite syntax is here using the save method:

PHP
Route::get('/', function()
{
    $painter = new Painter; 
    $painter->username = 'Leonardo Da Vinci';
    $painter->bio = 'Renaissance painter, scientist, inventor, and more. Da Vinci is one of most famous painters for his iconic Mona Lisa and Last Supper.';
    $painter->save();   
});

   
Route::get('/', function()
{
    $painter = new Painter; 
    $painter->username = 'Leonardo Da Vinci';
    $painter->bio = 'Renaissance painter, scientist, inventor, and more. Da Vinci is one of most famous painters for his iconic Mona Lisa and Last Supper.';
    $painter->save();   
});

string ‘insert into painters (username, bio, updated_at, created_at) values (?, ?, ?, ?)’ (length=90)
Retrieve (Select)

all() and first() Let’s have a look at our newly created record by selecting data now:
PHP
Route::get('/', function()
{
    $painters = Painter::all()->first();

    echo $painters->username.'<br>';
    echo $painters->bio;
   
});

   
Route::get('/', function()
{
    $painters = Painter::all()->first();

    echo $painters->username.'<br>';
    echo $painters->bio;
   
});

string ‘select * from painters‘ (length=24)

Leonardo Da Vinci
Renaissance painter, scientist, inventor, and more. Da Vinci is one of most famous painters for his iconic Mona Lisa and Last Supper.
Update

Let’s move on to an update. I think we’ll add a hypen in the last name. Note that there is not a specific update method per se, but rather we retrieve it, change an attribute, and use the save method like so:

PHP
Route::get('/', function()
{
    $painters = Painter::all()->first();
    $painters->username = 'Leonardo Da-Vinci';
    $painters->save();   
});

   
Route::get('/', function()
{
    $painters = Painter::all()->first();
    $painters->username = 'Leonardo Da-Vinci';
    $painters->save();   
});

string ‘select * from painters‘ (length=24)
string ‘update painters set username = ?, updated_at = ? where id = ?’ (length=69)
Delete

delete With eloquent, deleting a record is super easy. Have a look:

PHP
Route::get('/', function()
{
    $painters = Painter::all()->first();
    $painters->delete();   
});

   
Route::get('/', function()
{
    $painters = Painter::all()->first();
    $painters->delete();   
});

string ‘select * from painters‘ (length=24)
string ‘delete from painters where id = ?’ (length=37)

and just like that, POOF!, Leonardo is no longer with us in the database.
Relationships in Eloquent

Relationships are a key component in Eloquent but first, we need some more painters! Let’s add them:

PHP
Route::get('/', function()
{
    $painter = new Painter; 
    $painter->username = 'Leonardo Da Vinci';
    $painter->bio = 'Renaissance painter, scientist, inventor, and more. Da Vinci is one of most famous painters for his iconic Mona Lisa and Last Supper.';
    $painter->save();   

    $painter = new Painter; 
    $painter->username = 'Vincent Van Gogh';
    $painter->bio = 'Dutch post-impressionist painter. Famous paintings include: Sunflowers, The Starry night, Cafe Terrace at Night.';
    $painter->save();   

    $painter = new Painter; 
    $painter->username = 'Rembrandt';
    $painter->bio = 'One of greatest painters, admired for his vivid realism. Famous paintings include The Jewish Bride, The Storm of the sea of Galilee';
    $painter->save();   
});

   
Route::get('/', function()
{
    $painter = new Painter; 
    $painter->username = 'Leonardo Da Vinci';
    $painter->bio = 'Renaissance painter, scientist, inventor, and more. Da Vinci is one of most famous painters for his iconic Mona Lisa and Last Supper.';
    $painter->save();   

    $painter = new Painter; 
    $painter->username = 'Vincent Van Gogh';
    $painter->bio = 'Dutch post-impressionist painter. Famous paintings include: Sunflowers, The Starry night, Cafe Terrace at Night.';
    $painter->save();   

    $painter = new Painter; 
    $painter->username = 'Rembrandt';
    $painter->bio = 'One of greatest painters, admired for his vivid realism. Famous paintings include The Jewish Bride, The Storm of the sea of Galilee';
    $painter->save();   
});

string ‘insert into painters (username, bio, updated_at, created_at) values (?, ?, ?, ?)’ (length=90)
string ‘insert into painters (username, bio, updated_at, created_at) values (?, ?, ?, ?)’ (length=90)
string ‘insert into painters (username, bio, updated_at, created_at) values (?, ?, ?, ?)’ (length=90)

Great! Now, we know that Painters will likely have created some Paintings. For Brevity, I will show just one snippet of how we can insert a Painting. Just note that for our purposes Leonardo Da Vinci is painter_id 2, Vincent Van Gogh is id painter_id 3, and Rembrandt is id painter_id 4. It is by this very field, painter_id, which is in the paintings table, that facilitates our relationships. We’ll need to remember this when constructing methods to select data from our database using relationships!

Sample Painting insert:
PHP
Route::get('/', function()
{
    $painter = Painter::find(4);
   
    $painting = new Painting;
    $painting->title = 'The Storm on the Sea of Galilee';
    $painting->body = 'The Storm on the Sea of Galilee is a painting from 1633 by the Dutch Golden Age painter Rembrandt van Rijn that was in the Isabella Stewart Gardner Museum of Boston, Massachusetts, United States, prior to being stolen on March 18, 1990.';
    $painting->painter_id = $painter->id;
    $painting->save();
});

   
Route::get('/', function()
{
    $painter = Painter::find(4);
   
    $painting = new Painting;
    $painting->title = 'The Storm on the Sea of Galilee';
    $painting->body = 'The Storm on the Sea of Galilee is a painting from 1633 by the Dutch Golden Age painter Rembrandt van Rijn that was in the Isabella Stewart Gardner Museum of Boston, Massachusetts, United States, prior to being stolen on March 18, 1990.';
    $painting->painter_id = $painter->id;
    $painting->save();
});

note: We execute variations on the above code a few times in order to give each Painter at least 2 Paintings each in the database.
hasMany

A Painter will typically have many Paintings just like an Author may have many Books, or a Chicken may have many eggs. In Laravel, we can define relationships like this in our Model like so:

PHP
<?php
class Painter extends Eloquent {
   
    public function paintings()
    {
        return $this->hasMany('Painting');
    }
   
}

   
<?php
class Painter extends Eloquent {
   
    public function paintings()
    {
        return $this->hasMany('Painting');
    }
   
}

Here is a great trick to help you remember how this works! Start with the $this keyword, followed by the class name of the file, followed by the $this method, followed by the Model passed in. So in this case it would read like: This Painter hasMany Painting. See how that works?!
belongsTo

The inverse of this is that all Paintings must have been Painted by a Painter. We could also say that a Painting belongsTo a Painter. Let’s see this model!

PHP
<?php
class Painting extends Eloquent {
   
    public function painter()
    {
        return $this->belongsTo('Painter');
    }
   
}

   
<?php
class Painting extends Eloquent {
   
    public function painter()
    {
        return $this->belongsTo('Painter');
    }
   
}

We can use the same trick here! (this|name of class file|name of method|name of model passed in) So in this case we would have This Painting belongsTo Painter.

Nice work 🙂
Dynamic Methods, Oh My!

Now that we have set up our models to represent both the hasMany and belongsTo relationships, we can start querying the database in very clever ways. For example, by using dynamic methods and the relationships we just created, we can tell the database to go get Leonardo Da Vinci’s paintings and return them to us. Let’s see it:

PHP
Route::get('/', function()
{
    $painter = Painter::whereUsername('Leonardo Da Vinci')->first();
   
    foreach($painter->paintings as $painting){
        echo $painting->title.'<br>';
        echo $painting->body.'<br><br>';
    }

});

   
Route::get('/', function()
{
    $painter = Painter::whereUsername('Leonardo Da Vinci')->first();
   
    foreach($painter->paintings as $painting){
        echo $painting->title.'<br>';
        echo $painting->body.'<br><br>';
    }

});

string ‘select * from painters where username = ? limit 1′ (length=53)
string ‘select * from paintings where paintings.painter_id = ?’ (length=60)

Mona Lisa
The Mona Lisa is a half-length portrait of a woman by the Italian artist Leonardo da Vinci, which has been acclaimed as “the best known, the most visited, the most written about, the most sung about, the most parodied work of art in the world

Last Supper
The Last Supper is a late 15th-century mural painting by Leonardo da Vinci in the refectory of the Convent of Santa Maria delle Grazie, Milan. The work is presumed to have been commenced around 1495 and was commissioned as part of a scheme of renovations to the church and its convent buildings by Leonardos patron Ludovico Sforza, Duke of Milan.

Notice the whereUsername method, I haven’t seen that one before! No you haven’t friend, that’s because with Laravel you can combine a where clause with the table name and pass in the string you are looking for! Mind Blown! There is your dynamic method. Now with regard to the relationship, this one works since in our Painter model, we told it that This Painter hasMany Painting!

Let’s now do the inverse, we’ll ask the database something like “Who Painted The Potato Eaters?” With our relation set in the Painting model such that This Painting belongsTo Painter, we should also be able to do this in reverse:

PHP
Route::get('/', function()
{
    $painting = Painting::whereTitle('The Potato Eaters')->first();
   
    echo Painter::find($painting->painter_id)->username;

});

   
Route::get('/', function()
{
    $painting = Painting::whereTitle('The Potato Eaters')->first();
   
    echo Painter::find($painting->painter_id)->username;

});

string ‘select * from paintings where title = ? limit 1′ (length=51)
string ‘select * from painters where id = ? limit 1′ (length=47)
Vincent Van Gogh

Of Course! Vincent Van Gogh is the Painter that painted ‘The Potato Eaters’! The above code was the long hand way to do this. You see, when we create both relationships, we can combine the models to reach any field on either table by going through it! Since we created an instance of the Painting model in $painting, we can now go through the Painter model to reach any field in that table. How? Like this:

Route::get('/', function()
{
    $painting = Painting::whereTitle('The Potato Eaters')->first();
   
    echo $painting->painter->username.'<br>';
    echo $painting->painter->bio;

});

   
Route::get('/', function()
{
    $painting = Painting::whereTitle('The Potato Eaters')->first();
   
    echo $painting->painter->username.'<br>';
    echo $painting->painter->bio;

});

string ‘select * from paintings where title = ? limit 1′ (length=51)
string ‘select * from painters where painters.id = ? limit 1′ (length=58)
Vincent Van Gogh
Dutch post-impressionist painter. Famous paintings include: Sunflowers, The Starry night, Cafe Terrace at Night.

Notice the only Model that was instantiated is the Painting model, yet we are accessing fields in the painters table with ease since we are going through it!

Use your imagination and you can basically ask the database anything you want, it just takes a little bit of trial and error. Let’s tell the database to “Get me all the paintings you have and tell me who painted each one“! Eye eye Captain!

PHP
Route::get('/', function()
{
    $paintings = Painting::all();
   
    foreach($paintings as $painting){
        echo $painting->painter->username;
        echo ' painted the ';
        echo $painting->title;
    }

});

   
Route::get('/', function()
{
    $paintings = Painting::all();
   
    foreach($paintings as $painting){
        echo $painting->painter->username;
        echo ' painted the ';
        echo $painting->title;
    }

});

string ‘select * from paintings‘ (length=25)
string ‘select * from painters where painters.id = ? limit 1′ (length=58)
Leonardo Da Vinci painted the Mona Lisa
string ‘select * from painters where painters.id = ? limit 1′ (length=58)
Leonardo Da Vinci painted the Last Supper
string ‘select * from painters where painters.id = ? limit 1′ (length=58)
Vincent Van Gogh painted the The Starry Night
string ‘select * from painters where painters.id = ? limit 1′ (length=58)
Vincent Van Gogh painted the The Potato Eaters
string ‘select * from painters where painters.id = ? limit 1′ (length=58)
Rembrandt painted the The Night Watch
string ‘select * from painters where painters.id = ? limit 1′ (length=58)
Rembrandt painted the The Storm on the Sea of Galilee

Notice how many queries that is hitting our database with. This is probably not ideal. A better way to do this would be to use eager loading by way of the with method:

PHP
Route::get('/', function()
{
    $paintings = Painting::with('painter')->get();
   
    foreach($paintings as $painting){
        echo $painting->painter->username;
        echo ' painted the ';
        echo $painting->title;
        echo '<br>';
    }

});

   
Route::get('/', function()
{
    $paintings = Painting::with('painter')->get();
   
    foreach($paintings as $painting){
        echo $painting->painter->username;
        echo ' painted the ';
        echo $painting->title;
        echo '<br>';
    }

});

string ‘select * from paintings‘ (length=25)
string ‘select * from painters where painters.id in (?, ?, ?)’ (length=59)

Leonardo Da Vinci painted the Mona Lisa
Leonardo Da Vinci painted the Last Supper
Vincent Van Gogh painted the The Starry Night
Vincent Van Gogh painted the The Potato Eaters
Rembrandt painted the The Night Watch
Rembrandt painted the The Storm on the Sea of Galilee

Now that’s more like it boss. 2 queries, and we’re done!

Well, that’s enough for this one. There are many more things to learn in Laravel, but I hope this helped in some way!