Eloquent ORM Basics
Eloquent is Laravel's built-in ORM (Object-Relational Mapper), and it's the tool you'll use for the overwhelming majority of database work in a Laravel application. It follows the ActiveRecord pattern: every database table gets a corresponding PHP class (a "model"), and every row in that table is represented, at runtime, as an instance of that model class. Instead of writing raw SQL strings, you work with objects and method calls, and Eloquent translates that into SQL behind the scenes.
Generating a Model
Like most things in Laravel, models are scaffolded with Artisan rather than created by hand:
# From your project's terminal
php artisan make:model Article
This creates app/Models/Article.php, an empty class extending Eloquent's base
Model class. A commonly used shortcut adds the -m flag, which generates a
matching database migration file at the same time — migrations are covered fully in the next
lesson, Migrations & Seeders, but it's worth knowing
this shortcut exists since you'll use it constantly:
# Generates both the model AND a migration for the "articles" table
php artisan make:model Article -m
Eloquent's Naming Conventions
Eloquent leans heavily on convention over configuration — as long as you follow its naming rules, you never have to manually tell a model which table it maps to.
| Convention | Example |
|---|---|
| Table name | A model named Article (singular, StudlyCase) automatically maps to a table named articles (plural, snake_case). A model named OrderItem maps to order_items. |
| Primary key | Assumed to be a column named id, auto-incrementing, unless you override it. |
| Timestamps | created_at and updated_at columns are set and updated automatically by Eloquent whenever a row is created or saved — you never set these yourself unless you explicitly disable this behavior with public $timestamps = false; on the model. |
protected $table = 'blog_posts'; property, for instance, points a model at a differently-named table — but sticking with the defaults keeps your codebase predictable and is strongly recommended unless you have a real reason not to.Basic CRUD with Eloquent
Reading and writing rows through a model reads almost like plain English:
<?php
// Read all rows from the "articles" table
$articles = Article::all();
// Find one row by its primary key (returns null if not found)
$article = Article::find(1);
// Create a new row in one call
$article = Article::create([
'title' => 'Getting Started With Eloquent',
'body' => 'Eloquent makes database work feel natural...',
]);
Mass Assignment and $fillable
That Article::create([...]) call is called mass assignment — passing
an entire array of column values at once, instead of setting each property individually. Eloquent
requires you to explicitly opt in to which fields are allowed to be mass-assigned, via a
$fillable property on the model:
<?php
// app/Models/Article.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
protected $fillable = ['title', 'body'];
}
$fillable, a form that blindly passes
$request->all() into create() would let an attacker submit
any field name they like in their form data — including something like
is_admin or role — and have it silently written straight to the database,
even though your actual form never intended to expose that field. Listing only the genuinely safe,
user-editable columns in $fillable closes that door: anything not listed is simply
ignored during mass assignment.
Saving via an Instance
Mass assignment isn't the only way to create a row — you can also build up a new model instance
property by property and call save() when it's ready:
<?php
$article = new Article();
$article->title = 'Getting Started With Eloquent';
$article->body = 'Eloquent makes database work feel natural...';
$article->save();
This form doesn't need $fillable at all — mass assignment protection only applies
when you're passing an array into methods like create() or fill(), not
when setting individual properties directly.
Updating and Deleting
<?php
// Update an existing row
$article = Article::find(1);
$article->update([
'title' => 'An Updated Title',
]);
// Delete a row
$article->delete();
Like create(), the array passed to update() is also mass assignment, so
it's governed by the same $fillable rules on the model.
A Full Worked Example: A Controller Action
Putting several of these together, a typical controller method that stores a new article looks like this:
<?php
// app/Http/Controllers/ArticleController.php
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required|max:255',
'body' => 'required',
]);
$article = Article::create($validated);
return redirect('/articles/' . $article->id);
}
Validation (from the previous lesson) protects against bad or missing data; $fillable
on the Article model protects against unwanted fields sneaking into the mass-assigned
array; and create() does the actual insert, timestamps included automatically,
returning the freshly created model — complete with its new id — ready to use
immediately, as shown in the redirect above.