Introduction to Laravel

Laravel is an open-source PHP web framework built around the MVC (Model-View-Controller) architectural pattern. Created by Taylor Otwell in 2011, it has grown into the most popular PHP framework in the world, with over 80,000 GitHub stars and millions of applications running in production across every industry.

Laravel's appeal comes from its philosophy: make common tasks — routing, authentication, sessions, caching, queues, testing — as painless as possible, without sacrificing power or flexibility. The framework ships with an expressive query builder, a world-class ORM (Eloquent), a template engine (Blade), first-party authentication scaffolding, real-time WebSocket support via Reverb, and now in version 13, a native AI SDK.

This guide is written for beginner to intermediate developers who want a practical, no-fluff understanding of Laravel 13 — what it is, what's new, how to install it, and how to use its key features. If you already know Laravel 12, the "What's New" section is the one to jump to first.

Release Context

Laravel 13 was released on March 17, 2026. It requires PHP 8.3 or newer and follows the framework's annual Q1 release schedule. Bug fixes are supported until Q3 2027; security fixes until Q1 2028.

What's New in Laravel 13

Laravel 13 is officially described as a "relatively minor upgrade in terms of breaking changes, while still delivering substantial new capabilities." In practice, this means most applications upgrade in under 10 minutes — but there are genuinely significant additions that change how you write Laravel code going forward.

PHP Attributes for Model Configuration

This is the biggest quality-of-life improvement in three versions. Previously, every Eloquent model started with a wall of protected arrays — $fillable, $hidden, $guarded, $table, $connection. Laravel 13 replaces all of this with native PHP 8 Attributes. The change is entirely non-breaking — the old syntax still works.

app/Models/User.php · Laravel 13 Attributes
use Illuminate\Database\Eloquent\Attributes\Table;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Attributes\Hidden;

// Before (Laravel 12 and earlier)
class User extends Model {
  protected $table    = 'users';
  protected $fillable = ['name', 'email'];
  protected $hidden   = ['password'];
}

// After (Laravel 13 — clean attributes)
#[Table('users')]
#[Fillable('name', 'email')]
#[Hidden('password')]
class User extends Model {
  // Your actual business logic lives here now
  public function posts(): HasMany { ... }
}

Attributes are also available for Commands, Form Requests, Mailables, Listeners, Notifications, API Resources, and Factories. Every class that previously used property-based configuration now has an attribute alternative.

Typed Eloquent Properties

For years, model properties were magic. $user->email could be a string, could be null — your IDE just returned mixed. Laravel 13 adds support for fully typed Eloquent properties, which immediately improves IDE autocomplete and lets PHPStan catch type errors at development time rather than in production.

app/Models/User.php · Typed Properties
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;

class User extends Model {
  public int     $id;
  public string  $name;
  public string  $email;
  public ?Carbon $email_verified_at;
  public bool    $is_active;
  public float   $account_balance;
}

First-Party Laravel AI SDK

The biggest platform addition in Laravel 13 is the first-party AI SDK. It provides a unified, provider-agnostic API for text generation, tool-calling agents, embeddings, image generation, audio synthesis, and vector-store integrations — all with a clean Laravel-native developer experience.

Laravel AI SDK — Quick Examples
use App\Ai\Agents\SalesCoach;
use Laravel\Ai\Audio;
use Illuminate\Support\Facades\DB;

// Text generation via a custom agent
$response = SalesCoach::make()
  ->prompt('Analyze this sales transcript...');

// Audio synthesis from text
$audio = Audio::of('I love coding with Laravel.')->generate();

// Semantic vector similarity search (PostgreSQL + pgvector)
$docs = DB::table('documents')
  ->whereVectorSimilarTo('embedding', 'Best wineries in Napa Valley')
  ->limit(10)
  ->get();

First-Party JSON:API Resources

Laravel 13 ships native JSON:API resources. If you build APIs for mobile apps or third-party clients, this eliminates the need to assemble JSON:API-shaped responses by hand. The new JsonApiResource handles resource objects, relationships, sparse fieldsets, includes, links, and the correct application/vnd.api+json response header automatically.

Enhanced CSRF — PreventRequestForgery

Laravel's CSRF middleware has been formalized as PreventRequestForgery. In modern browsers, it first checks the Sec-Fetch-Site header to verify same-origin requests, then falls back to normal CSRF token validation. This is a genuine security improvement, not just a rename.

Cache::touch() — Extend TTL Without Fetch

A small but highly impactful addition: Cache::touch($key, $seconds) extends a cached item's time-to-live without fetching or re-storing its value. This eliminates the old get-then-put pattern in high-traffic systems.

Cache::touch() — Before vs After
// Before — get value, then re-store it just to extend TTL
$value = Cache::get('session:123');
Cache::put('session:123', $value, now()->addMinutes(30));

// After (Laravel 13) — one line, no fetch required
Cache::touch('session:123', now()->addMinutes(30));

Queue Routing by Job Class

Laravel 13 adds Queue::route(), which lets you define default queue and connection routing rules for specific job classes centrally — instead of scattering onQueue() calls throughout your codebase.

AppServiceProvider.php · Queue Routing
use App\Jobs\ProcessPodcast;
use Illuminate\Support\Facades\Queue;

Queue::route(ProcessPodcast::class, connection: 'redis', queue: 'media');
Queue::route(SendWelcomeEmail::class, queue: 'emails');
Breaking Changes to Watch

Dropping PHP 8.2 support is the main breaking change. Additionally review: PreventRequestForgery if you have custom CSRF logic, cache serializable_classes (Laravel now hardens cache unserialization by default), and MySQL DELETE queries with JOIN + ORDER BY which may now throw errors on unsupported engines.

Installation and Setup

Before installing Laravel 13, make sure your system meets the requirements. PHP 8.3 is the minimum — there is no way around this for Laravel 13.

System Requirements

  • PHP 8.3, 8.4, or 8.5
  • Composer 2.x
  • A database: MySQL 8+, PostgreSQL 13+, SQLite 3.26+, or SQL Server 2017+
  • Node.js 18+ and npm (for frontend assets with Vite)
1

Install via Laravel Installer

The Laravel installer is the fastest way to scaffold a new project.

Terminal
# Install the Laravel installer globally
composer global require laravel/installer

# Create a new Laravel 13 project
laravel new my-project

# Or use Composer directly
composer create-project laravel/laravel my-project "^13.0"
2

Configure Your Environment

Copy .env.example to .env and fill in your database credentials.

.env
APP_NAME=MyProject
APP_ENV=local
APP_KEY=  # generated by php artisan key:generate
APP_DEBUG=true
APP_URL=http://localhost

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_project
DB_USERNAME=root
DB_PASSWORD=
3

Run Migrations and Start the Server

Laravel ships with starter migrations for users and sessions. Run them, then start the dev server.

Terminal
php artisan key:generate
php artisan migrate

# Start built-in dev server
php artisan serve

# Or use Laravel Herd (macOS/Windows) for zero-config local dev
# https://herd.laravel.com

Project Structure

A fresh Laravel 13 project follows a well-organised folder layout. Understanding this is fundamental before writing any code. Laravel uses the MVC pattern — Models handle data, Views handle presentation, Controllers handle the logic between them.

Project Root Structure
my-project/
├── app/
│   ├── Http/
│   │   ├── Controllers/    # Handle requests, return responses
│   │   └── Middleware/     # Filter HTTP requests
│   ├── Models/             # Eloquent models (database layer)
│   ├── Providers/          # Service container bindings
│   └── Ai/                 # NEW in L13: AI agents & tools
├── routes/
│   ├── web.php             # Browser routes (session, CSRF)
│   └── api.php             # API routes (stateless)
├── resources/
│   ├── views/              # Blade templates (.blade.php)
│   └── js/                 # Frontend JS (Vite bundled)
├── database/
│   ├── migrations/         # Schema version control
│   ├── factories/          # Test data generators
│   └── seeders/            # Database seeders
├── config/                 # All framework configuration
├── storage/                # Logs, cache, uploaded files
└── tests/                  # Unit and feature tests

Routing

In Laravel, all routes are defined in the routes/ directory. Web routes go in web.php, API routes in api.php. Routes map a URL + HTTP method to a controller action or a closure.

routes/web.php
use App\Http\Controllers\JobController;
use Illuminate\Support\Facades\Route;

// Basic route — closure
Route::get('/', fn() => view('welcome'));

// Route with parameter
Route::get('/jobs/{id}', [JobController::class, 'show']);

// Named route — reference by name anywhere
Route::get('/jobs', [JobController::class, 'index'])->name('jobs.index');

// Route group with middleware
Route::middleware('auth')->group(function () {
  Route::get('/dashboard', [DashboardController::class, 'index']);
  Route::resource('jobs', JobController::class);  // full CRUD
});

Blade Templating Engine

Blade is Laravel's built-in templating engine. Unlike some template systems, Blade does not restrict you from using plain PHP in your views — every Blade template is compiled to plain PHP and cached, so there is no performance penalty.

resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html>
<head>
  <title>{{ $title ?? 'My App' }}</title>
  @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
  @include('partials.navbar')

  <!-- Child views render here -->
  @yield('content')

  @stack('scripts')
</body>
</html>

<!-- resources/views/jobs/index.blade.php -->
@extends('layouts.app')

@section('content')
  @foreach($jobs as $job)
    <div>{{ $job->title }} — {{ $job->company }}</div>
  @endforeach
@endsection

Database and Eloquent ORM

Eloquent is Laravel's ORM (Object-Relational Mapper). Each database table has a corresponding Model class, and you interact with the table through that model rather than writing raw SQL. Migrations act as version control for your database schema.

database/migrations/create_jobs_table.php
return new class extends Migration {
  public function up(): void {
    Schema::create('jobs', function (Blueprint $table) {
      $table->id();
      $table->string('title');
      $table->string('company');
      $table->text('description');
      $table->decimal('salary', 10, 2)->nullable();
      $table->foreignId('user_id')->constrained();
      $table->timestamps();
    });
  }
};
app/Models/Job.php · Eloquent Model
#[Fillable('title', 'company', 'description', 'salary')]
class Job extends Model {
  public int    $id;
  public string $title;
  public string $company;

  // Relationships
  public function user(): BelongsTo {
    return $this->belongsTo(User::class);
  }

  // Scope — reusable query filter
  public function scopePublished($query) {
    return $query->where('is_published', true);
  }
}

// CRUD operations
Job::create(['title' => 'Laravel Dev', 'company' => 'Acme']);
$jobs = Job::published()->with('user')->latest()->paginate(20);
Job::find(1)->update(['title' => 'Senior Laravel Dev']);
Job::destroy(1);

Authentication and Authorization

Laravel 13 ships with multiple starter kits for authentication. Laravel Breeze is the minimal option — it scaffolds login, registration, password reset, and email verification using Blade views or Inertia.js. Jetstream adds two-factor authentication, API token management, and team support.

Terminal — Install Breeze
composer require laravel/breeze --dev
php artisan breeze:install   # choose: blade / react / vue / api
npm install && npm run dev
php artisan migrate

For authorization (what a logged-in user is allowed to do), Laravel provides Policies and Gates:

app/Policies/JobPolicy.php
class JobPolicy {
  public function update(User $user, Job $job): bool {
    return $user->id === $job->user_id;
  }
}

// In a controller
$this->authorize('update', $job);  // throws 403 if not authorized

API Development

Laravel is an excellent choice for building RESTful APIs. API routes live in routes/api.php, are stateless by default (no session, no CSRF token), and are prefixed with /api. Use Resource Controllers for standard CRUD endpoints and API Resources to control exactly what JSON shape is returned.

routes/api.php + JobController.php
// routes/api.php
Route::middleware('auth:sanctum')->apiResource('jobs', JobController::class);

// app/Http/Controllers/JobController.php
class JobController extends Controller {
  public function index(): JsonResponse {
    return JobResource::collection(
      Job::with('user')->latest()->paginate(20)
    );
  }
  public function store(StoreJobRequest $request): JsonResponse {
    $job = Job::create($request->validated());
    return (new JobResource($job))->response()->setStatusCode(201);
  }
}

// app/Http/Resources/JobResource.php
class JobResource extends JsonResource {
  public function toArray($request): array {
    return [
      'id'      => $this->id,
      'title'   => $this->title,
      'company' => $this->company,
      'author'  => $this->whenLoaded('user', fn() => $this->user->name),
    ];
  }
}

Security Features

Laravel has security built into its foundation. Most common web vulnerabilities are handled automatically, so you are protected by default without writing any security-specific code.

  • CSRF Protection: Every form submitted to a web route must include a CSRF token via @csrf. In Laravel 13, this is enhanced with origin-aware verification via PreventRequestForgery.
  • Input Validation: Use Form Requests to validate all incoming data before it reaches your controller. The validated() method returns only the data that passed your rules — nothing else.
  • Password Hashing: Passwords are hashed with bcrypt by default. Never store plain-text passwords. Use Hash::make($password) to hash and Hash::check($input, $hash) to verify.
  • SQL Injection: Eloquent and the Query Builder use PDO parameter binding. As long as you use the ORM or where() methods, injection is prevented automatically.
  • XSS Prevention: Blade's {{ }} syntax automatically escapes output. Use {!! !!} only when you intentionally render trusted HTML.

Performance Optimization

A default Laravel install is not automatically optimized for production. These are the techniques that have the biggest real-world impact:

Caching

Cache your configuration, routes, views, and events for production. One command does all four:

Terminal — Production Optimization
php artisan config:cache    # merge all config files into one
php artisan route:cache     # compile route definitions
php artisan view:cache      # pre-compile all Blade templates
php artisan event:cache     # cache event-listener discovery

# Or run all at once
php artisan optimize

Eager Loading — Preventing the N+1 Problem

The single most common performance bug in Laravel applications is the N+1 query problem. If you loop over 100 jobs and access $job->user inside the loop without eager loading, you trigger 101 separate SQL queries. Use with() to fix this:

N+1 Problem — Fix with Eager Loading
// BAD — 1 query to get jobs + 1 query per job for user = N+1
$jobs = Job::all();
foreach ($jobs as $job) {
  echo $job->user->name;  // queries the DB on every iteration
}

// GOOD — 2 queries total: one for jobs, one for all users
$jobs = Job::with('user')->all();

Testing

Laravel ships with PHPUnit pre-configured and adds its own expressive testing helpers on top. Every new Laravel project contains a tests/Unit and tests/Feature directory. Feature tests are the most valuable in Laravel — they test real HTTP requests against your application's routes, middleware, and database.

tests/Feature/JobApiTest.php
use Illuminate\Foundation\Testing\RefreshDatabase;

class JobApiTest extends TestCase {
  use RefreshDatabase;  // fresh DB for each test

  public function test_unauthenticated_cannot_create_job(): void {
    $this->postJson('/api/jobs', ['title' => 'Test'])
         ->assertStatus(401);
  }

  public function test_authenticated_user_can_create_job(): void {
    $user = User::factory()->create();

    $this->actingAs($user)
         ->postJson('/api/jobs', [
           'title'       => 'Laravel Developer',
           'company'     => 'Acme Corp',
           'description' => 'Remote position',
         ])
         ->assertStatus(201)
         ->assertJsonPath('data.title', 'Laravel Developer');

    $this->assertDatabaseHas('jobs', ['title' => 'Laravel Developer']);
  }
}

# Run tests
php artisan test
php artisan test --parallel  # faster — runs suites in parallel

Deployment

Laravel applications can be deployed on shared hosting, a VPS, or a cloud platform. For serious production workloads, a VPS with Nginx + PHP-FPM or a managed platform like Laravel Forge is the standard choice.

Deployment Checklist
# 1. Set production environment
APP_ENV=production
APP_DEBUG=false

# 2. Install production dependencies only
composer install --optimize-autoloader --no-dev

# 3. Run migrations
php artisan migrate --force

# 4. Optimize framework
php artisan optimize

# 5. Build frontend assets
npm ci && npm run build

# 6. Set correct file permissions
chmod -R 755 storage bootstrap/cache

Laravel 12 vs Laravel 13

Feature Laravel 12 Laravel 13
Min PHP Version PHP 8.2 PHP 8.3
AI SDK Not included First-party, stable
PHP Attributes for Models Not available Full support
Typed Eloquent Properties Not available Supported
JSON:API Resources Third-party only First-party
CSRF Middleware VerifyCsrfToken PreventRequestForgery
Cache::touch() Not available Available
Queue Routing by Class Not available Queue::route()
Vector Similarity Search Not available Native support
Breaking Changes Minimal (~10 min upgrade)

Conclusion

Laravel 13 does not reinvent the wheel — and that is exactly the right call. The framework has matured to a point where stability and developer experience improvements compound more value than disruptive new paradigms. PHP Attributes clean up model code that every Laravel developer has written for years. Typed Eloquent properties bring IDE and static-analysis support that should have existed a long time ago. The AI SDK positions Laravel as the first PHP framework with a genuine, production-ready path for building AI-powered features.

If you are starting a new project in 2026, Laravel 13 with PHP 8.3 is the clear choice. If you are on Laravel 12, the upgrade path is intentionally smooth — plan an afternoon, run your test suite, and you will be on 13 by end of day.

Final Verdict

Use Laravel 13 for all new PHP projects. The AI SDK alone makes it worth adopting for any team building modern web applications. The PHP Attributes syntax reduces model boilerplate significantly, typed properties dramatically improve IDE experience, and the framework-wide security improvements in PreventRequestForgery are meaningful for production applications.

For existing Laravel 12 applications: upgrade is low-risk and the main prerequisite is PHP 8.3. Audit your third-party packages for compatibility, run your test suite in a staging environment, then deploy. Most teams complete this in well under a day.

👨‍💻
Sonu Sahani
Full Stack Developer · CodeCraft Systems

6+ years building production Laravel APIs, Vue.js SPAs, and cloud SaaS products. Currently working with Lifelancer (UK). Writing about real-world patterns used in live projects every day.