Tous les articles
LaravelPHPBackend

Laravel 13: PHP Attributes, AI SDK, and Native pgvector Support

//
·8 min de lecture

Laravel 13 ships with PHP 8.3 as the minimum, first-party PHP Attributes for models and jobs, a built-in AI SDK supporting OpenAI and Anthropic, and native pgvector semantic search.

Laravel 13 arrived on March 17, 2026, raising the PHP floor to 8.3 and shipping what the team calls “the most developer-experience-forward release since Laravel 5.5”. The three flagship features — PHP Attributes on models, a first-party AI SDK, and native vector search — are fully opt-in and backward-compatible. Upgrading from Laravel 12 is described as the smoothest major version bump in the framework's history.

>PHP 8.3 minimum

⚠ BREAKINGPHP 8.2 is no longer supported. Update your server and CI pipeline to PHP 8.3 before upgrading to Laravel 13.

bash
# Verify before upgrading
php --version   # must be >= 8.3

# composer.json
"require": {
  "php": "^8.3",
  "laravel/framework": "^13.0"
}

>PHP Attributes — declarative model configuration

Laravel 13 introduces first-party PHP 8 Attributes as an alternative to array-based model properties. They are entirely opt-in — existing code keeps working unchanged.

php
<?php

use IlluminateDatabaseEloquentAttributes{
    Table, Fillable, Hidden, Cast, ObservedBy, ScopedBy
};

#[Table('users', key: 'user_id', keyType: 'string', incrementing: false)]
#[Fillable(['name', 'email', 'avatar'])]
#[Hidden(['password', 'remember_token'])]
#[Cast('preferences', 'array')]
#[Cast('email_verified_at', 'datetime')]
#[ObservedBy([UserObserver::class])]
class User extends Model
{
    // No more $table, $fillable, $hidden, $casts arrays
}

// Attributes also work on Jobs, Commands, Listeners, Mailables
use IlluminateQueueAttributes{Queue, Connection, WithoutOverlapping};

#[Queue('payments')]
#[Connection('redis')]
#[WithoutOverlapping(expiresAt: 300, releaseOnSignal: true)]
class ProcessPayment implements ShouldQueue
{
    public function handle(): void { /* ... */ }
}

>Laravel AI SDK (first-party)

laravel/ai is a stable first-party package shipping with Laravel 13 starter kits. It provides a unified fluent API over OpenAI and Anthropic, covering text generation, tool-calling agents, embeddings, audio transcription, image generation and vector stores.

bash
composer require laravel/ai
php
<?php

use LaravelAIFacadesAI;

// Text generation
$response = AI::text('Summarise this invoice: ' . $invoice->text);

// Streaming
AI::text('Write a product description for: ' . $product->name)
    ->stream(fn (string $chunk) => print($chunk));

// Tool-calling agent
$result = AI::agent()
    ->tools([new SearchInventoryTool, new PriceCalculatorTool])
    ->run('What is the total price for 3 units of SKU-42?');

// Embeddings → pgvector
$vector = AI::embed('Best wineries in Napa Valley');
$docs   = Document::whereVectorSimilarTo('embedding', $vector)->limit(5)->get();

// Switch provider per call
AI::using('anthropic')->text('Classify this support ticket: ' . $ticket->body);

NOTEProvider credentials live in .env: OPENAI_API_KEY and ANTHROPIC_API_KEY. The default provider is configured in config/ai.php.

>Native pgvector — semantic search

Laravel 13 ships first-party pgvector support via the query builder and Eloquent, no external packages required.

bash
# Migration
php artisan make:migration add_embedding_to_documents_table
php
<?php

// Migration
Schema::table('documents', function (Blueprint $table) {
    $table->vector('embedding', dimensions: 1536); // OpenAI ada-002
});

// Model cast
class Document extends Model
{
    #[Cast('embedding', 'vector')]
    // or via array: protected $casts = ['embedding' => 'vector'];
}

// Storing an embedding
$doc->embedding = AI::embed($doc->content);
$doc->save();

// Semantic search — cosine similarity (default)
$results = Document::whereVectorSimilarTo('embedding', 'climate change solutions')
    ->limit(10)
    ->get();

// Euclidean distance
$results = Document::whereVectorSimilarTo(
    'embedding',
    'climate change solutions',
    distance: 'euclidean',
)->get();

>Cache::touch()

Extends a cache entry's TTL without fetching or re-storing the value — a single atomic database operation.

php
// Before — two round-trips
$value = Cache::get('report:123');
Cache::put('report:123', $value, now()->addHours(2));

// Laravel 13 — one round-trip, value unchanged
Cache::touch('report:123', now()->addHours(2));

>Centralised Queue routing

php
<?php
// AppServiceProvider::boot()

use IlluminateSupportFacadesQueue;

Queue::route(ProcessPayment::class, connection: 'redis',    queue: 'payments');
Queue::route(SendInvoice::class,    connection: 'database', queue: 'mail');
Queue::route(GenerateReport::class, connection: 'sqs',      queue: 'reports');

// Overrides #[Queue] and #[Connection] attributes
// One place for all routing decisions

>Upgrade from Laravel 12

bash
# 1. Update PHP to 8.3+
# 2. Update composer.json
composer require laravel/framework:^13.0 --no-update

# 3. Run
composer update

# Laravel Shift for automated migration
# https://laravelshift.com/laravel-12-to-13-upgrade-guide

php artisan about          # confirms version 13.x
php artisan config:clear
php artisan cache:clear

NOTEThe upgrade guide lists zero code-breaking changes in application code for the 12→13 path. All new APIs are additive and opt-in.