Note: All example data interactions in this Reference guide will be using a model named Post with an associated table named posts. Both the name of the model and the table are not limited to these names, but there ARE naming conventions associated with them. The name of the model should be the name of the table in the singular form, spelled with a capital first letter. The name of the table should always be plural. All class names (models, controllers, migrations, etc) should be in PascalCase. Table names should always be in snake_case (All lowercase with underscores between words).
Use the following to create a model in the appropriate directory.
php artisan make:model {name}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
// The table associated with the model
protected $table = 'posts';
}
name: the name of the model.
You can also add -m
to the end to create a respective migration connected to it.
Example model:
Generally the name of the model is the name of the table in the singular form, spelled with a capital first letter.
Within the model, there should be a line that looks like use App*Name*;. This is required in any class that needs to access that model. For example, if the Posts model needs to be accessed within Routes, then use App\Posts; needs to be present at the top of the Routes file.
use App\Post
$posts = Post::function();
return $posts;
Because Post extends the functions of Model, all of the Eloquent functionality will be available for this model. Simply use the name of the model along with the Scope Resolution Operator (: and a function to execute a database interaction. Multiple functions can be chained using the object operator
(->)
.
Example:
$adminPost = Post::where('is_admin', 1)
->orderBy('id', 'desc')
->first()
->get();
return $adminPost->title;
Useful functions for retrieving data:
Function | Description |
---|---|
all() | Retrieves all data from table. From here you can use a foreach to go through each result. Example below. |
find(id#) | Fetch one or more rows based on their Primary Key(s). Note that the find() function does not use the get() function to execute. |
findOrFail(id#) | Fetch one or more rows based on their Primary Key(s). If the result is null an exception will be thrown instead of an error. Note that the findOrFail() function does not use the get() function to execute. |
where('column', 'value') | Filter results based on a WHERE clause. The first parameter indicates the column and the second indicates the value of said column. I.e: WHERE column = value. |
orderBy('column', 'DESC/ASC') | Sort the results based on the column and its direction (DESC/ASC). |
take(number) | Limit the amount of results to a certain number. You can also use first() if you only need the first record. |
first() | Only return the first result. Equivalent to take(1). |
get() | Execute the query command. This is the final function called after filtering the results. |
Using a foreach
loop to cycle through all data:
$posts = Post::all();
foreach($posts as $post)
{
echo $post->title . " " . $post->content;
}
$post = new Post;
$post->title = "Post Title";
$post->content = "Post Content";
$post->save();
By simply creating a new object from the associated model, you are able to assign values to the different columns using the object operator (->)
. The save()
function will execute the appropriate queries to insert the data.
You can also create data using Mass Assign. To do that, you will need allow the desired columns to have permission to insert data. This can be done using the model's $fillable
property. See the example below in the Post model class.
$fillable = [
'title',
'content',
];
Once the desired columns have permission, you can create data using the create()
function.
Post::create(['title'=>'Post Title', 'content'=>'Post Content']);
The create()
function uses an associative array to insert the desired columns with the desired content.
Basic updating in Eloquent is the same as data creation. The only difference is that instead of setting a variable as a new instance of the Model, you set it as a result from a selection. This way the variable will be instantiated as an existing row. Like creating data, the save()
function will execute the updates.
$post = find(1);
$post->title = "New Post Title";
$post->content = "new Post Content";
$post->save();
You can also use Mass Assign to update data in a single statement. Ensure that the columns you wish to change are $fillable
. View Creating Data if you are unsure on what that means.
Post::where('id', 1)->update(['title'=>'New Post Title', 'content'=>'New Post Content']);
There are two common ways to delete data using Eloquent. To quickly delete a record whilst allowing callbacks and filters, you can use the destroy()
function. It takes the Primary Key or an array of Primary keys as its parameter.
Post::destroy(1);
Alternatively, you can use the delete()
function, which also takes the Primary Key or an array of Primary keys as its parameter. This function requires that the data is retrieved first.
$post = Post::find(1);
$post->delete();
Eloquent has a feature called Soft Deleting which uses a column in a model called deleted_at
to store a timestamp of when a delete function was executed. This allows for data to remain existent until an Eloquent forceDelete()
function is executed. All data retrieval functions will ignore any data that has been soft deleted unless the withTrashed()
function is used.
If you haven't already, add a deleted_at
column to the model that you wish to support soft delete. Then in the model class file, import the SoftDeletes class stored in Illuminate\Database\Eloquent\SoftDeletes
. In the class itself, write use SoftDeletes;
to use the trait. Then give the deleted_at
column permission to be accessed by adding deleted_at
to your $dates
property.
The example below is a Post model that supports Soft Delete.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Post extends Model
{
use SoftDeletes;
protected $table = 'posts';
protected $dates = ['deleted_at'];
protected $fillable = [
'title',
'content'
];
}
Useful functions when using Soft Delete:
Function | Description |
---|---|
forceDelete() | This will permanently remove the record from the database. It will also bypass Soft Delete if this is used before the record is "Trashed". |
restore() | This will remove the deleted_at timestamp from the record, allowing it to be retrievable through Eloquent functions. |
withTrashed() | This is used in data retrieval when you want to include all records with the deleted_at timestamp as well. |
onlyTrashed() | This is used in data retrieval when you only want records with the deleted_at timestamp. |
You can also check if a record has a deleted_at
timestamp using the trashed() function:
$post = Post::find(1);
if ($post->trashed())
{
$post->restore();
}
To empty the trash:
Post::onlyTrashed()->forceDelete();
Eloquent can create relationships between tables using several functions available in the model class. Within a model, simply create a method for establishing a relationship and return one of Eloquent's functions as part of the current model.
hasOne('App\Model')
This model Has One record in App\Model. This is used for a One to One relationship where only a single record is returned.
Example:
// Method within Users model
public function post()
{
return $this->hasOne('App\Post')
}
// Function call
$post = User::find(1)->post;
belongsTo('App\Model')
This model has one record that Belongs To App\Model. This is used for a One on One relationship where only a single record is returned.
Example:
// Method within Post model
public function user()
{
return $this->belongsTo('App\User')
}
// Function call
$user = Post::find(1)->user->name;
hasMany('App\Model')
This model Has Many records in App\Model. This is used for a One to Many relationship where several records can be returned.
Example:
// Method within User model
public function posts()
{
return $this->hasMany('App\Post');
}
// Function call
$user = User::find(1);
foreach($user->posts as $post)
{
return $post->title . '<br>';
}
belongsToMany('App\Model')
This model Belongs To Many records in App\Model. This is used for a Many to Many relationships where several records can be returned.
Example:
// Method within Post model
public function users()
{
return $this->belongsToMany('App\User')
}
// Function call
$post = Post::find(1);
foreach($post->users as $user)
{
return $user->name . '<br>';
}
hasManyThrough('App\FinalModel', 'App\IntermediateModel')
This is a shortcut to access information "through" an intermediate table. This model Has Many records in the Final Model that need to be accessed through the Intermediate Model.
Example:
// Method within User model
public function posts()
{
return $this->hasManyThrough('App\Post', 'App\User');
}
// Function call
$country = Country::find(1);
foreach ($country->posts as $post)
{
return $post->title . '<br>';
}
Many times you may have a table designed to store data for two or more separate tables. To have this, you will need to use polymorphism to relate said table to the others. An example of this would be a comments table that can be used for both videos and articles.
Laravel has standards on how table columns should be named to relate to one another. Because the comments table relates to both articles and videos. The table should have both a column named commentable_id and a column named commentable_type. The naming standard is the singular name of the table with "able" at the end.
Example table with random data:
id | message | commentable_id | commentable_type | created_at | updated_at |
---|---|---|---|---|---|
1 | Example comment for a video | 3 | App\Video | 2018-07-31 21:18:54 | 2018-07-31 21:18:54 |
2 | Example comment for an article | 5 | App\Article | 2018-07-31 21:18:54 | 2018-07-31 21:18:54 |
The commentable_id column refers to the id of the video or article. The commentable_type column indicates whether the comment is for a video or an article. The first row is a comment for the video with id 3 and the the second row is a comment for the article with id 5.
To allow the comments table to be morphed, a function needs to be created named with the prefix of the id and type columns (i.e: commentable) inside the Comment model. This will then use an Eloquent function morphTo() to allow for polymorphism.
Inside Comment Model:
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
}
Inside the Video and Article models, a function named comments() can be created to retrieve all of the comments for a particular video or article. Within the comments() function, the Eloquent function morphMany() should be used to find the data. If you use belongsTo() you will retrieve comments for both articles and videos at the same time.
Inside the Video and Article model:
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
To retrieve the data, just use a foreach loop that references the comments method with the correct model. For example:
// Find comments for article id 1
$article = Article::find(1);
foreach($article->comments as $comment)
{
echo $comment->message . '<br>';
}
Useful Links:
Eloquent - Relationships (Many to Many Polymorphic Relationships)
Sometimes you may have a table that can have records that can apply to multiple tables. An example of this is tags. You could have a tag that applies to both articles and videos. This relationship is a type of polymorphism called Many to Many. It allows you to have a single list of unique records that are shared across several tables.
For this to work, you will need an intermediate table to link the tags to the other models. The laravel standard is to name it with the name of the original model (i.e: tags) form with "able" suffix added to the end. In this case, it would be named "tagables" or "taggables", the model being named "Taggable" accordingly. Like the comment model, it requires both a taggable_id and a taggable_type, as well as a tag_id to identify the particular tag to link.
Example table with random data:
id | tag_id | taggable_id | taggable_type |
---|---|---|---|
1 | 4 | 8 | App\Video |
2 | 9 | 7 | App\Article |
In this example, a tag with id 4 is associated with a video with id 8 and a tag with id 9 is associated with an article with id 7.
To access the tags associated to a post or video, use the morphToMany() function within each model.
class Article extends Model
{
public function tags()
{
return $this->morphToMany('App\Tag', 'taggable');
}
}
Then use a foreach loop calling the tags() function to access the associated tags:
// Find tags with article id 1
$article = Article::find(1);
foreach($article->tag as $tag)
{
echo $tag->name . '<br>';
}
To use the inverse of the polymorphic relationship, create an articles and a videos function in the tag model. Within each function, use morphByMany() to access the associated articles/videos.
class Tag extends Model
{
// Return posts
public function articles()
{
return $this->morphedByMany('App\Article', 'taggable');
}
// Return videos
public function videos()
{
return $this->morphedByMany('App\Video', 'taggable');
}
}
Now you can use a foreach loop to find all articles/videos that use a specific tag:
// Find articles with tag id 1
$tag = Tag::find(1);
foreach($tag->article as $article)
{
echo $article->title . '<br>';
}