Six things you need to know to master Laravel Eloquent

Share this Post

Laravel is an open-source and easy-to-use PHP framework. One of its most powerful features is Eloquent, an object-relational mapper (ORM) that simplifies database record handling.

Eloquent speeds create, read, update, and delete operations on a database from an application. When using Eloquent, you create models that mirror database tables and use those models to create your queries.

This article examines six elements of Eloquent’s most potent functionality: query scopes, relationships, mutators and accessors, collections, model deletion, and factories. It covers what each feature does using practical examples. We hope you can use these examples to jump-start your mastery of Laravel Eloquent.

1. Eloquent query scopes

When building an application, you sometimes run into situations where you use conditions more than once. Rewriting code in each case can increase the chance of errors and make your code untidy. Laravel solves this problem by wrapping such conditions in reusable statements called scopes.

Query scopes are methods for adding database logic to a model and reusing query logic.

Below is an example of a query scope. Assume you want to create a software development platform for your team that tracks completed and ongoing features. You can use this condition to retrieve just ongoing features:

$onGoing = Project::where('ongoing', 1)->get();

You may need this condition on other application pages, such as the stats page. Query scopes allow a page to reuse the condition above, simplifying your query and making your code cleaner.

Here’s how you can use a query scope for this scenario:

class Features extends Model
{
    public function scopeOngoing($query)
    {
        return $query->where('ongoing', 0);
    }
}

Then use the code below to execute that scope:

$onGoing = Feature::ongoing()->get();

There are two types of scopes: global and local.

Global scopes

Global scopes allow the addition of constraints to all queries within a model. For instance, you can add a condition to filter features based on the team leader’s name in all queries within your model.

Local scopes

Local scopes allow for the definition of common constraints for reusability. For instance, you may want the application to return the features that have bugs. Your code might implement a local scope like this:

namespace AppModels;
use IlluminateDatabaseEloquentModel;

class User extends Model
{
    public function scopeBugged($query)
    {
        return $query->where('bugged', '>', 1);
    }
}

The code above returns all the features that have unfixed bugs.

2. Eloquent relationships

Relationships in Eloquent allow you to relate different tables easily. For instance, a product on an ecommerce website may have inventory, price, views, and reviews listed. With Eloquent, you can easily manage these relationships even when their records are in different tables.

You can define relationships as methods on model classes, just like you would an Eloquent model. Some commonly used Eloquent relationships include one-to-one, inverse, and polymorphic.

One-to-one

Here’s an example of a basic one-to-one relationship that associates a product model with an inventory.

public function Inventory()
{
    return $this->hasOne('AppInventory');
}

In the code above, the Inventory() method calls the hasOne() method on the product model. This checks whether the product is currently available.

Inverse

Eloquent also allows you to create an inverse relationship. For instance, when you want to fetch products based on their views count. Inverse relationships can give you the products that elicit the most interest from a website’s visitors. You can use the belongsTo() method, which is the inverse of hasOne(). The code below illustrates this.

public function product()
{
    return $this->belongsTo('AppProduct');
}

In the code above, Eloquent matches the product_id to the number of views passed. The product_id can then help fetch other parameters, such as price and inventory.

Polymorphic

In application development, relationships are not always simple. Sometimes, you have a model that belongs to more than one model type. For instance, product and inventory models can both have polymorphic relationships to an image model.

Polymorphic relationships would allow you to use the same list of images for both the inventory and the products. Below is a code snippet implementing a polymorphic relationship.

class Image extends Model
{
    /**
     * Getting the shared image.
     */
    public function myimage()
    {
        return $this->morphTo();
    }
}

class Product extends Model
{
    /**
     * Get the image to use on the product's page.
     */
    public function image()
    {
        return $this->morphOne(Image::class, 'myimage');
    }
}

class Inventory extends Model
{
    /**
     * Get the image to use on the inventory page.
     */
    public function image()
    {
        return $this->morphOne(Image::class, 'myimage');
    }
}

The code above uses the morphTo() method to retrieve the parent of the polymorphic model.

That’s just the tip of the iceberg on this topic. For more, see our advanced guide to Laravel Eloquent relationships.

3. Eloquent mutators and accessors

Mutators and accessors allow you to alter data while storing and retrieving it. Mutators modify data before saving it, while accessors modify data while retrieving it.

If you want to store names in lowercase in your database, you can create a mutator to execute that transformation. If you want to display the user’s first name and last name as one name on your app pages, you can create an accessor to accomplish that.

Below is an example of a mutator that capitalizes names before saving them.

class User extends Model
{
    /**
     * Mutators capitalizing first and last name.
     */
    public function setFirstNameAttribute($value)
    {
        $this->attributes['first_name'] = ucfirst($value);
    }

    public function setLastNameAttribute($value)
    {
        $this->attributes['last_name'] = ucfirst($value);
    }
}

Below is an example of an accessor that combines the first name and last name of the user.

class User extends Model
{
    /**
     * Accessor combining both names.
     */
    public function getFullNameAttribute()
    {
        return ucfirst($this->first_name) . ' ' . ucfirst($this->last_name);
    }
}

4. Eloquent collections

Eloquent collections handle methods that return multiple model results. This class is found in IlluminateDatabaseEloquentCollection.

As with arrays, it’s possible to iterate through collections. Below is a simple iteration.

use AppModelsProduct;

$products = Product::where('availability', 1)->get();

foreach ($products as $product) {
   echo $product->name;
}

Collections are more powerful than arrays because you can perform more complex operations on them. For instance, you can display the list of all the available products and skip all that are not “active.”

$names = Product::all()->reject(function ($product) {
   return $product->active === false;
})->map(function ($product) {
   return $product->name;
});

Below are some of the methods that the collections class provides.

source