Module 3: Database & Eloquent

Advanced ORM, Relationships, and Performance

Migrations & Schema

Laravel 11 compresses default migrations into fewer files.

Schema::create('orders', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained()->cascadeOnDelete();
    $table->integer('total_cents');
    $table->string('status')->default('pending')->index();
    $table->json('metadata')->nullable();
    $table->timestamps();
});

Relationships

Defining relationships correctly is key to leveraging Eloquent.

Polymorphic Relationships

Allow a model to belong to more than one other model on a single association.

class Comment extends Model {
    public function commentable() {
        return $this->morphTo();
    }
}

class Post extends Model {
    public function comments() {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

class Video extends Model {
    public function comments() {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

Performance Optimization

The N+1 query problem is the most common performance bottleneck.

Eager Loading

// Bad (N+1 problem)
$books = Book::all();
foreach ($books as $book) {
    echo $book->author->name; // Triggers a query for each book
}

// Good (Eager Loading)
$books = Book::with('author')->get(); // 2 queries total

Preventing N+1 in Development

Strict mode helps catch these issues early.

// AppServiceProvider.php
public function boot(): void
{
    Model::shouldBeStrict(! $this->app->isProduction());
}

This enables: preventLazyLoading, preventSilentlyDiscardingAttributes, and preventAccessingMissingAttributes.

Scopes

Encapsulate common query logic.

// Local Scope
public function scopeActive(Builder $query): void
{
    $query->where('active', 1);
}

// Usage
$users = User::active()->get();

Accessors & Mutators

New syntax using Attribute class.

use Illuminate\Database\Eloquent\Casts\Attribute;

protected function amount(): Attribute
{
    return Attribute::make(
        get: fn (int $value) => $value / 100,
        set: fn (float $value) => $value * 100,
    );
}