Eloquent Model vs Model in Laravel: Understanding the Fundamental Difference

An Eloquent model extends Illuminate\Database\Eloquent\Model and provides active-record database interaction, while a plain Laravel model is any PHP class representing domain data without ORM coupling or built-in persistence logic.

When working with the laravel/framework repository, developers encounter two distinct interpretations of the term "model." Understanding the difference between an Eloquent model and a model in the context of a Laravel model setup is crucial for architecting maintainable applications. While both represent data structures, their coupling to the database layer and available functionality differ fundamentally.

What Is an Eloquent Model in Laravel?

An Eloquent model is a PHP class that extends Illuminate\Database\Eloquent\Model, the core active-record base class located in src/Illuminate/Database/Eloquent/Model.php. This inheritance chain provides a robust ORM layer that maps database tables to objects, enabling developers to interact with relational data using expressive PHP syntax rather than raw SQL.

The Eloquent implementation leverages traits such as ForwardsCalls (from src/Illuminate/Support/Traits/ForwardsCalls.php) to delegate method calls to the underlying query builder, creating the fluent interface developers expect when chaining methods like where() and first().

What Is a Plain Laravel Model?

A plain Laravel model—often implemented as a Data Transfer Object (DTO) or value object—is simply a PHP class that does not extend the Eloquent base class. These classes represent domain concepts or data structures without assuming database persistence capabilities. Unlike Eloquent models, plain models contain no built-in query methods, relationship helpers, or active-record lifecycle hooks.

Developers typically use plain models when data originates from external APIs, configuration files, CSV imports, or when implementing domain-driven design patterns that require strict separation between business logic and data access layers.

Key Differences Between an Eloquent Model and a Model

Understanding the architectural distinctions helps determine which approach fits specific use cases.

Database Coupling and Active Record Pattern

Eloquent models implement the active-record pattern, meaning each object carries both data and database access logic. The class in src/Illuminate/Database/Eloquent/Model.php provides methods like save(), update(), and delete() that translate directly to SQL operations.

Plain models remain persistence-agnostic. They hold state but delegate storage operations to repositories, services, or external APIs, maintaining strict separation of concerns.

Query Building and Relationships

Eloquent provides a fluent query API through method forwarding to the query builder. Relationships like hasOne(), hasMany(), and belongsTo() are defined as methods returning Illuminate\Database\Eloquent\Relations\Relation subclasses, enabling eager loading via with() and lazy loading through dynamic properties.

Plain models lack these capabilities. Implementing relationships requires manual foreign key management and query construction using the DB facade or query builder directly.

Built-in Functionality via Traits

Eloquent models leverage a rich trait ecosystem:

Plain models only include traits you explicitly import, keeping the class lightweight but requiring manual implementation of cross-cutting concerns.

Code Examples: Eloquent vs Plain Model

Eloquent Model Implementation

The following example extends Illuminate\Database\Eloquent\Model to create an active-record entity with relationships and soft deletes:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use SoftDeletes;

    protected $fillable = ['title', 'body', 'author_id'];

    public function author()
    {
        return $this->belongsTo(User::class, 'author_id');
    }
}

Usage demonstrates the active-record pattern:

// Create and persist in one operation
$post = Post::create([
    'title' => 'Laravel 12 Features',
    'body'  => 'New Eloquent improvements...',
    'author_id' => 1,
]);

// Query with eager loading
$posts = Post::with('author')
    ->where('title', 'like', '%Laravel%')
    ->get();

Plain Model Implementation

This Data Transfer Object represents the same domain concept without database coupling:

<?php

namespace App\DTO;

class PostData
{
    public string $title;
    public string $body;
    public int $authorId;

    public function __construct(string $title, string $body, int $authorId)
    {
        $this->title = $title;
        $this->body = $body;
        $this->authorId = $authorId;
    }
}

Persistence requires explicit service logic:

use App\DTO\PostData;
use App\Services\PostService;

$data = new PostData('Laravel 12 Features', 'Content...', 1);
$service = new PostService();
$posted = $service->store($data); // Handles API call or manual DB insert

When to Use Each Approach

  • Choose Eloquent when mapping database tables with relationships, requiring query scopes, soft deletes, or active-record convenience methods.
  • Choose Plain Models when integrating external APIs, implementing domain-driven design, or when strict separation between business logic and persistence is required.

Core Laravel Source Files

The Eloquent ORM implementation resides in specific files within the laravel/framework repository:

Summary

  • Eloquent models extend Illuminate\Database\Eloquent\Model and implement the active-record pattern, providing built-in database persistence, query building, and relationship management.
  • Plain Laravel models are standard PHP classes representing domain data without ORM coupling, requiring manual persistence logic but offering greater architectural flexibility.
  • The choice depends on data source requirements: use Eloquent for relational database mapping and plain models for external APIs, DTOs, or domain-driven design scenarios.
  • Core Eloquent functionality resides in src/Illuminate/Database/Eloquent/Model.php and related traits within the laravel/framework repository.

Frequently Asked Questions

Can I use a plain PHP class as an Eloquent model?

No, Eloquent requires classes to extend Illuminate\Database\Eloquent\Model located in src/Illuminate/Database/Eloquent/Model.php. However, you can use plain classes as Data Transfer Objects (DTOs) alongside Eloquent models, passing data between layers without database coupling.

Do I lose Eloquent features if I create a custom base model?

If your custom base model extends Illuminate\Database\Eloquent\Model, all Eloquent features remain available. You can add custom methods or override existing ones while retaining active-record capabilities, query building, and trait support like SoftDeletes and HasFactory.

When should I choose a DTO over an Eloquent model?

Choose a Data Transfer Object (plain model) when data originates from external APIs, configuration files, or CSV imports, or when implementing domain-driven design that requires strict separation between business logic and persistence. Eloquent models excel when mapping relational database tables with complex relationships and query requirements.

How do relationships work in plain models versus Eloquent?

Eloquent models define relationships using methods like hasOne(), hasMany(), and belongsTo() that return Illuminate\Database\Eloquent\Relations\Relation instances, enabling lazy loading, eager loading via with(), and relationship existence queries. Plain models lack these helpers; you must manually implement foreign key logic and query the database using the query builder or external API calls.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →