Introduction to Elquent
Eloquent is an ActiveRecord ORM. It’s a database abstraction layer that provides a single interface to interact with multiple database types.
Creating and Defining Eloquent Models
First, we can create a model like this:
1 | php artisan make:model User |
This is what we’ll get in app/User.php
1 |
|
If you want to automatically create a migration when you create the model, pass -m or –migration flag
1 | php artisan make:model User -m |
Table name
The default behavior for the table names is that Laravel ‘snake cases’ and pluralizes your class name, so SecondaryUser will access a table named secondary_users.
If you want to customize the name, set the $table
property on the model:
1 | protected $table = 'users_secondary'; |
Primary key
Laravel assumes, by default, each table will have an autoincrementing integer primary key, and it will be named id
If you want to customize the name of primary key, change the $primaryKey
property
1 | protected $primaryKey = 'contact_id'; |
And if you want to set it to be nonincrementing, use
1 | public $incrementing = false; |
Timestamps
Eloquent expects every table to have created_at
and updated_at
timestamp columns. If your table wont’ have them, disable the $timestamps
functionality
1 | public $timestamps = false; |
Retrieving Data with Eloquent
Most of the time we pull data from database with Eloquent, we’ll use static calls on Eloquent model
Everything we can do on DB
facade we can do on our Eloquent objects.
Get all
1 | Users::all(); // return all users in database |
Get one
we can use first()
to return only the first record from a query, or find()
to pull just the record with the provided ID. For either, we can append orFail
to the method name
1 | User::where('is_verified',true)->first(); |
Any single return will return an instance of the Eloquent class.
Get Many
1 | User::where('vip',true)->get(); |
It will return collections.
Chunking responses with chunk()
If you’ve need to deal with a large amount of records at a time. Laravel makes it possible to break your requests into maller pieces( chunks) and process them in batches.
1 | User::chunk(100, function($users){ |
Aggregates
1 | User::where('vip',true)->count(); |
Inserts and Updates with Eloquent
Inserts
1 | $user = new User; |
Until we save()
, this instance has never been saved to the database.
This means it doesn’t have an id. But when you use Model::create()
1 | $user = User::create([ |
You don’t need to call save()
, as it’s part of the Model::create()
function.
Updates
We can call the update()
method to updte one or more record
1 | $user = User::find(1); |
When we use the Model::update()
we don’t need to call save()
Mass assignment
When you define a model’s fillable or guarded properties, we can create or update a record like this:
1 | public function update(User $user, Request $request) |
firstOrCreate() and firstOrNew()
The firstOr*()
function is used to tell Laravel that ‘give me an instance with these properties or if ti doesn’t exist, create it’.
Those two methods take an array of keys and values as their first parameter
1 | $user = User::firstOrCreate(['name'=>'hello','email'=>'world']); |
They’ll both look for and retrieve the first record matching those parameters, and if there are no matching records, they’ll create an instance with thsoe properties;
The different is firstOrCreate()
will persist that instance to the database and then return it, while firstOrNew()
will return it without saving it.
Deleting with Eloquent
Normal deletes
1 | $contact = Contact::find(1); |
Soft deletes
Soft deletes mark databse row as deleted without actually deleting them from the database. In Laravel, every query will be scoped to ignore the soft deleted data, unless you explicitly ask to bring them back.
Eloquent’s soft delete functionality requires a deleted_at
column to be added to the table.
Enabling soft deletes
There are three things to do to enable soft deletes
Adding the deleted_at column in a migration using
softDeletes()
method.1
2
3Schema::create('Users', function(Blueprint $table){
$table->softDeletes()
});Importing the
SoftDeletes
trait in the model.Adding teh
deleted_at
column to your$dates
property.1
2
3
4
5
6
7
8
9
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Contact extends Model
{
use SoftDeletes; // use the trait
protected $dates = ['deleted_at']; // mark this column as a date
}
Once you make these changes, every delete()
and destory()
call will now set the delete_at
column on your row to be the current data and time instead deleting that row.
Querying with soft deletes
First, you can add soft-deleted items to a query
1 | $users = User::withTrashed()->get(); |
Next, you can use trashed()
method to see if a particular instance has been soft deleted
1 | if($user->trashed()) |
Finally, you can get only soft-deleted items
1 | $user = User::onlyTrashed()->get(); |
Restoring soft-deleted items
If you want to resotre a soft-deleted item, you can run resotre()
method on an instance or a query
1 | $user->restore(); |
Force deleting soft-deleted entities
1 | User::onlyTrashed()->forceDelete(); |
Scopes
Local and global scopes in Eloquent allow you to define prebuilt ‘scopes’ that you can use either every time a model is queried(‘global’) or every time you query it with a particular method chain(‘local’)
Local scopes
Local scopes are the simplest to understand
1 | $vips = User::where('vip',true)->where('trial',false)->get(); |
To avoid writing above code again and again to fetch the ‘active vip’, we can define a scope like this in our Model
1 | class User |
You can also define scope with parameters
1 | class User |
To define a local scope, we add a method to the Eloquent class that begins with “scope” and then contains the title-cased version of the scope name. This method is passed a query builder and needs to return a query builder, but of course you can modify the query before returning—that’s the whole point.
Global scopes
The global scope will be applied on every query made from a given model.
There are two way to define a global scope:
Using an closure
1
2
3
4
5
6
7
8
9class User
{
protected static function boot(){
parent::boot();
static::addGlobalScope('active',function(Illuminate\Database\Eloquent\Builder $builder){
$builder->where('active',true);
})
}
}Using an entire class
Create a class that implements Illuminate\Database\Eloquent\Scope, that mean it will have an
apply()
method that takes an instance of a query builder and an instance of the model.1
2
3
4
5
6
7
8
9
10
11
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class ActiveScope extends Scope{
public function apply(Builder $builder, Model $model){
return $builder->where('active',true);
}
}To apply this scope to a model, once again override the parent’s
boot()
method and calladdGlobalScope()
on the call usingstatic
1
2
3
4
5
6
7class User
{
public static function boot(){
parent::boot();
static::addGlobalScope(new ActiveScope);
}
}
Removing global scopes
1 | // remove global scope added by a closure |
Customizing Field Interactions with Accessors, Mutators, and Attribute Casting
Accessor
Accessors allow you to define custom attributes on your Eloquent models for when you are reading data from the model instance.
You can define an accessor by writing a method on your moel with the following structure: get{PascalCasedPropertyName}Attribute. So, if you property name is first_name, the accessor method would be named getFirstNameAttribute
1 | class User extends Model |
But we can also use accessors to define attributes that never existed in the database
1 | class User extends Model |
Mutators
Mutators work the same way as accessor, except they’re for determining how to process setting the data instead of getting it
You define a mutator by writing a method on your model with the following structure: set{PascalCasedPropertyName} attribute.
1 | class User extends Model |
But we can also use mutators to define attributes that never existed in the database
1 | class Order extends Model |
Attribute casting
It allows you to define that any of your columns should always be treated, both on read and on write, as if you are of a particular data type
1 | class Contact |
Date mutators
You can choose for particular columns to be mutated as timestamp columns by adding them to the dates array
1 | class Contact |
Eloquent Collection
When you make any query call in Eloquent that has the potential to return multiple row, instead of an array they’ll come packaged in an Eloquent collection, which is a specialized type of collection.
Eloquent Serializtion
Returning models difrectly from route methods
If you return the result of an Eloquent call in a controller, it will be automatically cast to a string, and therefore returned as JSON.
1 | Route::get('api/contacts',function(){ |
Hiding attributes from JSON
You can either blacklist attributes, hiding the ones you list:
1 | class Contact extends Model |
or whitelist attributes, showing only the ones you list:
1 | class Contact extends Model |
This also works for relationships
1 | class User extends Model |
Eloquent Relationships
In a relational database model, it’s expected that you will have tables that are related to each other—hence the name. Eloquent provides simple and powerful tools to make the process of relating your database tables easier than ever before.
One to One
Let’s start simple: a Contact has one PhoneNumber