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.
Contains
The contains()
method checks if the code contains a specified mode, as shown in the code below:
$products->contains(1);
$products->contains(Product::find(1));
All
The all()
method returns the models contained in the collection, as shown below:
$collection = Product::all();
Many other methods are supported by the collections class.
5. Delete Eloquent models
In Eloquent, you create models to help in building queries. However, sometimes you need to delete models to make an application more efficient. To do so, call delete
on the model’s instance.
use AppModelsStock;
$stock = Stock::find(1);
$stock->delete();
The code above removes the model Stock
from an application. This is a permanent removal that can’t be undone.
Soft delete
Another feature that Eloquent contains is model soft delete capability. When you soft delete a model, you don’t remove it from the database.
You flag it using deleted_at
to indicate the time and date of the soft delete. This is important when you want to exclude a portion of the database records, such as those that are incomplete, without permanently removing them. It helps in cleaning up Eloquent’s query results without adding extra conditions.
You enable soft delete by adding the softDeletes
trait to a model and adding a deleted_at
column on the related database table.
Adding soft delete to a model
You enable model soft deletes by adding the IlluminateDatabaseEloquentSoftDeletes
trait, as shown below.
namespace AppModels;
use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentSoftDeletes;
class Flight extends Model
{
use SoftDeletes;
}
How to add a delete_at column
Before you can start using soft delete, your database should have a delete_at
column. You add this column using a Laravel Schema
builder helper method, as shown below:
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
Schema::table('users', function (Blueprint $table) {
$table->softDeletes();
});
Schema::table('users', function (Blueprint $table) {
$table->dropSoftDeletes();
});
This adds a delete_at
column that is updated with the date and time, in case of a successful soft delete action.
How to include soft-deleted models
If you want query results to include soft-deleted models, you add the withTrashed()
method to the query. An example is shown below:
$stocks = Stock::withTrashed()->where('stock_id', 20)->get();
The query above will also include models with the deleted_at
attribute.
How to retrieve only soft-deleted models
Eloquent also allows you to retrieve soft-deleted models exclusively. You can do this by calling the onlyTrashed()
method, for example:
$Stock = Stock::onlyTrashed()->where('stock_id', 1)->get();
How to restore soft-deleted models
You can also restore soft-deleted models by calling the restore()
method.
$stocks = Stock::withTrashed()->where('stock_id', 20)->restore();
This changes the delete_at
field of a soft deleted model to null. If the model hasn’t been soft deleted, it leaves the field unchanged.
6. Eloquent Factories
Model factories in Laravel create dummy data that you can use to test your application or to seed your database. To implement this, you create a model in a factory class, as shown in the example below. The code snippet creates a model factory that can generate fake suppliers of a product and its prices.
namespace DatabaseFactories;
use IlluminateDatabaseEloquentFactoriesFactory;
use IlluminateSupportStr;
class StockFactory extends Factory
{
public function definition()
{
return [
'supplier_name' => fake()->name(),
'price' => fake()->numberBetween($min = 1500, $max = 6000),
];
}
}
The definition()
method in the example above returns a set of attribute values that Laravel uses when building the model. The fake helper helps the factory access PHP’s library, Faker.
Summary
Eloquent makes the tasks of developing applications in Laravel simpler. It is equally effective when building simple or complex queries, thanks to implementations such as relationships. The simplicity of generating functional dummy data using factories makes it perfect for developers who want to create robust tests for their applications. Additionally, Eloquent scopes help simplify complex queries in a way that leaves the code tidy.
While this article has covered just six of its major features, Eloquent has other powerful functionalities. The use of shareable and reusable models has made Eloquent a popular feature among developers, and the simplicity of Eloquent queries makes Laravel a developer-friendly framework — even for beginners.
Whatever your level of experience, Kinsta’s Web Application Hosting platform supports developers like you. Our Laravel quick start template shows how easy it is to get your application up and running on our servers within Google Cloud’s premium tier network.
Leave a Reply