Skip to main content
Eloquent is Laravel’s ActiveRecord implementation that provides a beautiful, simple way to interact with your database. Each database table has a corresponding “Model” that is used to interact with that table.

Defining Models

Models are stored in the app/Models directory.

Creating Models

Generate a new model using Artisan:
php artisan make:model User
Generate a model with a migration:
php artisan make:model Post -m

The User Model

Here’s the complete User model from a fresh Laravel installation:
app/Models/User.php
namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    /** @use HasFactory<\Database\Factories\UserFactory> */
    use HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var list<string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var list<string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }
}
The User model extends Authenticatable instead of the base Model class because it’s used for authentication.

Model Conventions

Table Names

By convention, the “snake case”, plural name of the class is used as the table name:
  • User model → users table
  • BlogPost model → blog_posts table
Override the table name:
protected $table = 'my_users';

Primary Keys

Eloquent assumes each table has a primary key column named id:
protected $primaryKey = 'user_id';
For non-incrementing or non-numeric keys:
public $incrementing = false;
protected $keyType = 'string';

Timestamps

Eloquent expects created_at and updated_at columns:
// Disable timestamps
public $timestamps = false;

// Customize timestamp format
protected $dateFormat = 'U';

Mass Assignment

Define which attributes can be mass-assigned:

Fillable Attributes

app/Models/User.php
protected $fillable = [
    'name',
    'email',
    'password',
];

Guarded Attributes

protected $guarded = ['admin', 'role'];

// Guard all attributes
protected $guarded = ['*'];

// Unguard all attributes (not recommended)
protected $guarded = [];
Always define $fillable or $guarded to prevent mass assignment vulnerabilities.

Retrieving Models

Basic Queries

$users = User::all();

foreach ($users as $user) {
    echo $user->name;
}

Aggregates

$count = User::count();
$max = User::max('votes');
$min = User::min('votes');
$avg = User::avg('votes');
$sum = User::sum('votes');

Creating & Updating Models

Creating Models

$user = new User;
$user->name = 'John Doe';
$user->email = '[email protected]';
$user->save();

Updating Models

$user = User::find(1);
$user->name = 'Jane Doe';
$user->save();

// Mass update
User::where('active', 1)
    ->update(['status' => 'verified']);

Deleting Models

$user = User::find(1);
$user->delete();

// Delete by primary key
User::destroy(1);
User::destroy([1, 2, 3]);

// Mass delete
User::where('votes', '>', 100)->delete();

Attribute Casting

Cast attributes to common data types:
app/Models/User.php
protected function casts(): array
{
    return [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
    ];
}
Available cast types:
  • array, collection
  • boolean
  • date, datetime, timestamp
  • decimal:<precision>
  • integer, float, double, real
  • string
  • hashed (automatically hashes values)
The hashed cast automatically hashes passwords when setting them, eliminating the need to manually call Hash::make().

Hidden Attributes

Hide attributes from JSON serialization:
app/Models/User.php
protected $hidden = [
    'password',
    'remember_token',
];
Or define visible attributes:
protected $visible = ['name', 'email'];

Model Factories

Generate fake data for testing:
database/factories/UserFactory.php
namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class UserFactory extends Factory
{
    protected static ?string $password;

    public function definition(): array
    {
        return [
            'name' => fake()->name(),
            'email' => fake()->unique()->safeEmail(),
            'email_verified_at' => now(),
            'password' => static::$password ??= Hash::make('password'),
            'remember_token' => Str::random(10),
        ];
    }

    public function unverified(): static
    {
        return $this->state(fn (array $attributes) => [
            'email_verified_at' => null,
        ]);
    }
}

Using Factories

// Create a single user
$user = User::factory()->create();

// Create multiple users
$users = User::factory(10)->create();

// Create with attributes
$user = User::factory()->create([
    'name' => 'John Doe',
]);

// Create unverified user
$user = User::factory()->unverified()->create();
Use the HasFactory trait in your models to enable factory functionality:
use HasFactory, Notifiable;

Relationships

Define relationships between models:

One to Many

class User extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

class Post extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

Many to Many

class User extends Model
{
    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }
}

Accessing Relationships

$user = User::find(1);

// Access as property
foreach ($user->posts as $post) {
    echo $post->title;
}

// Access as method (allows chaining)
$posts = $user->posts()->where('active', 1)->get();

Build docs developers (and LLMs) love