Phase 6 · Laravel MasteryModule 36~62 min read

Eloquent, Migrations & Validation

Model, validate, query, relate, seed, and paginate application data with Laravel's database tools.

What you'll learn

Model data with Eloquent while preserving query awareness. You will evolve schemas, define relationships, eliminate N+1 queries, build realistic factories, and move request validation and authorization into Form Requests.

By the end of this lesson, you'll be able to:

  • Create Laravel migrations and Eloquent relationships
  • Use eager loading and pagination intentionally
  • Validate and authorize input with Form Requests

Core mental model

Professional PHP is less about memorizing APIs and more about choosing a clear boundary for each responsibility. Use this table as a decision guide while reading the examples.

ConceptWhat it protectsDecision rule
RelationshipExpressive related queriesDeclare cardinality and still inspect generated SQL.
Eager loadingBounded query countLoad known relations before looping or serializing.
Form RequestHTTP input contractCentralize route authorization and validation.

Professional workflow

Build the feature in small, verifiable steps. Each step leaves the system in a state you can test.

  1. Describe the Laravel data boundary boundary: its inputs, outputs, invariants, and expected failures.
  2. Implement the smallest happy path behind an explicit contract.
  3. Add validation and translate low-level failures into language the caller understands.
  4. Exercise the boundary with realistic data, then inspect output, logs, and resource cleanup.
  5. Refactor only after behavior is protected by a repeatable check.

Make the boundary visible

Name inputs, outputs, side effects, and failure cases before adding framework or infrastructure code. That habit keeps advanced PHP understandable as the application grows.

Guided code lab

Define schema and model relationship

The foreign key is enforced in SQL; Eloquent exposes the object traversal.

create_lessons_table.php
<?php
Schema::create('lessons', function (Blueprint $table): void {
    $table->id();
    $table->foreignId('course_id')->constrained()->cascadeOnDelete();
    $table->string('title', 180);
    $table->unsignedInteger('position');
    $table->timestamps();
    $table->unique(['course_id', 'position']);
});

// In Course.php
public function lessons(): HasMany
{
    return $this->hasMany(Lesson::class)->orderBy('position');
}

Authorize and validate one command

The controller receives only validated data after the request also checks permission.

StoreCourseRequest.php
<?php
final class StoreCourseRequest extends FormRequest
{
    public function authorize(): bool
    {
        return $this->user()?->can('create', Course::class) ?? false;
    }
    public function rules(): array
    {
        return [
            'title' => ['required', 'string', 'max:180'],
            'slug' => ['required', 'alpha_dash', 'max:190', 'unique:courses,slug'],
            'price_cents' => ['required', 'integer', 'min:0'],
        ];
    }
}

Production practice

Contract

Treat models as persistence-aware objects and keep multi-model business workflows in actions or services.

Verification

Refresh the database, use factories for intent-revealing data, and assert queries or relations where performance matters.

Operations

Review migration lock risk and enable production query monitoring for slow or unexpectedly repeated SQL.

Common failure mode

Serializing a model with lazy relationships can issue a query per row. Eager-load exactly what the representation needs.

Independent workshop

Add modules, lessons, tags, reviews, and publish validation to the Laravel catalog.

Your finished workshop must include:

  • Constrained migrations and model relationships
  • Factories, seeders, and eager-loaded queries
  • Form Requests covering create and update rules

Definition of done

Run the happy path and at least two failure paths, explain one design tradeoff in a short README, and leave the code formatted and ready for review.

Recap & quick check

Key takeaways

  • Database constraints remain essential with an ORM.
  • Eloquent relationships are query builders.
  • Eager loading prevents N+1 behavior.
  • Form Requests combine transport validation and authorization.

Quick check

1. What avoids repeated relation queries?

2. Where can route-level authorization accompany validation?

3. Should Eloquent replace foreign keys?

Keep the workshop: later phases deliberately build on these boundaries, so today's small example can become part of your portfolio architecture.