Laravel has evolved dramatically in recent years. Laravel 11 and 12 deliver a slimmer skeleton, explicit bootstrapping, powerful query improvements, native modern starter kits, and first-party high-performance tools that let you write cleaner, more maintainable, and lightning-fast applications. This guide dives into very advanced, modern, and often lesser-known practices every serious Laravel developer should master in 2026.
Laravel 12+ Features You Should Use Right Now
nestedWhere() – Clean Complex Queries Without Closures (Laravel 12)
No more ugly nested closures for mixed AND/OR conditions.
<?php
// Laravel 12+
$products = DB::table('products')
->where('status', 'active')
->nestedWhere('price', '<', 1000, 'or', 'discount', '>', 30)
->where('stock', '>', 0)
->get();
// Equivalent to the old messy version:
$products = DB::table('products')
->where('status', 'active')
->where(function ($query) {
$query->where('price', '<', 1000)
->orWhere('discount', '>', 30);
})
->where('stock', '>', 0)
->get();
nestedWhere() dramatically improves readability for real-world filtering logic (price ranges + discounts + stock). Chain as many as you need.
UUID / ULID Primary Keys (Built-in Since Laravel 9, Perfected in 11+)
Stop using auto-increment IDs in distributed systems.
<?php
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Concerns\HasUlids;
class Order extends Model
{
use HasUuids; // or HasUlids for lexicographically sortable
// Optional: ordered UUIDs
public function newUniqueId(): string
{
return (string) Str::orderedUuid();
}
}
ULIDs are perfect for sharded databases and time-based sorting without exposing sequential IDs.
Prunable & MassPrunable Models – Automatic Database Cleanup
<?php
use Illuminate\Database\Eloquent\Prunable;
use Illuminate\Database\Eloquent\MassPrunable;
use Illuminate\Database\Eloquent\Builder;
class TemporaryUpload extends Model
{
use MassPrunable; // faster, no events fired
public function prunable(): Builder
{
return static::where('created_at', '<=', now()->subDays(7));
}
}
Schedule it:
// app/Console/Kernel.php or routes/console.php
Schedule::command('model:prune')->daily();
Attribute-Based Local Scopes (Laravel 10.20+ / 11+)
<?php
use Illuminate\Database\Eloquent\Attributes\Scope;
use Illuminate\Database\Eloquent\Builder;
class Post extends Model
{
#[Scope]
public function published(Builder $query): void
{
$query->where('published_at', '<=', now())
->where('is_draft', false);
}
}
// Usage
Post::published()->get();
Model Replication (Lesser-Known Gem)
$order = Order::find(1);
$copy = $order->replicate(['total', 'paid_at']); // exclude sensitive fields
$copy->save();
Modern Architecture Patterns in Laravel 12+
Repository + Service Layer (Still King in 2026)
<?php
// app/Repositories/OrderRepository.php
interface OrderRepositoryInterface
{
public function createWithItems(CreateOrderDTO $dto): Order;
}
// app/Services/OrderService.php
class OrderService
{
public function __construct(
private readonly OrderRepositoryInterface $repository,
private readonly InventoryService $inventory,
) {}
public function create(CreateOrderDTO $dto): Order
{
return DB::transaction(fn () => $this->repository->createWithItems($dto));
}
}
Data Transfer Objects (DTOs) with Constructor Property Promotion + Readonly
<?php
namespace App\Data;
readonly class CreateOrderDTO
{
public function __construct(
public readonly int $userId,
public readonly Collection $items, // collection of OrderItemDTO
public readonly ?string $notes = null,
) {}
public static function fromRequest(Request $request): self
{
return new self(
userId: $request->user()->id,
items: OrderItemDTO::collect($request->validated('items')),
notes: $request->validated('notes'),
);
}
}
Combine with Spatie's laravel-data package for even more power (validation, casting, pagination) – the de-facto standard in 2026.
Testing Best Practices – Pest is Default in Laravel 11+
Pest Unit Tests (Clean & Expressive)
<?php
// tests/Unit/OrderServiceTest.php
it('creates order and decrements stock', function () {
$user = User::factory()->create();
$product = Product::factory()->create(['stock' => 10]);
$dto = new CreateOrderDTO(
userId: $user->id,
items: collect([new OrderItemDTO($product->id, 2)])
);
$order = app(OrderService::class)->create($dto);
expect($order)
->toBeInstanceOf(Order::class)
->and($product->fresh()->stock)->toBe(8);
});
it('throws when stock insufficient')->throws(InsufficientStockException::class, function () {
// ...
});
Feature Tests with RefreshDatabase
<?php
// tests/Feature/OrdersApiTest.php
it('allows authenticated user to create order', function () {
$user = User::factory()->create();
$product = Product::factory()->create(['stock' => 5]);
$response = $this->actingAs($user)
->postJson('/api/orders', [
'items' => [['product_id' => $product->id, 'quantity' => 2]],
]);
$response->assertCreated();
expect($product->fresh()->stock)->toBe(3);
});
Performance Optimization – Octane Changes Everything
Laravel Octane (Swoole / RoadRunner / FrankenPHP)
composer require laravel/octane
php artisan octane:install
php artisan octane:start --server=frankenphp --watch
Concurrent Tasks (True Parallelism)
use Laravel\Octane\Facades\Octane;
[$users, $products, $orders] = Octane::concurrently([
fn () => User::with('orders')->get(),
fn () => Product::where('featured', true)->get(),
fn () => Order::recent()->get(),
]);
Octane Cache & Tables (In-Memory, Shared Across Workers)
// config/octane.php
'tables' => [
'leaderboard:5000' => ['user_id' => 'int', 'score' => 'int'],
],
// Usage
Octane::table('leaderboard')->set('user:123', ['user_id' => 123, 'score' => 9999]);
// Interval cache (auto-refreshes)
Cache::store('octane')->interval('daily-stats', fn () => calculateStats(), seconds: 86400);
Ticks for Background Work
Octane::tick('cleanup', fn () => TemporaryUpload::prune())
->seconds(60)
->immediate();
Octane + FrankenPHP is the 2026 gold standard – HTTP/3, zero-config HTTPS, and 10-100x throughput compared to traditional PHP-FPM.
Conclusion
Modern Laravel (v10–12) is no longer "just an MVC framework." It’s a full-stack powerhouse with explicit bootstrapping, first-party real-time (Reverb), page-based routing (Folio), functional components (Volt), and production-grade performance (Octane).
Key Takeaways:
- Use
nestedWhere(), UUID/ULID, Prunable models, and attribute scopes - Embrace DTOs + Service Layer + Repository for maintainable code
- Write tests in Pest – it’s faster and more enjoyable
- Deploy with Octane (FrankenPHP recommended) for production
- Leverage new starter kits with Volt + Flux + shadcn/ui for rapid full-stack development
Start upgrading today. Laravel 12+ is the most developer-friendly version yet – and the performance gains with Octane will make you wonder how you ever lived without it.
Top comments (0)