Laravel 12: Der definitive Guide für moderne Webentwicklung
Nach 10 Jahren intensiver Laravel-Entwicklung teile ich mein Expertenwissen über Laravel 12. Von den revolutionären neuen Features bis zu bewährten Architektur-Patterns – alles was du für professionelle Laravel-Projekte brauchst.
Laravel Experte seit 2014
10 Jahre Erfahrung • 200+ Laravel-Projekte • Enterprise-Architekturen
Ich habe Laravel von Version 4.2 bis zur aktuellen Version 12 begleitet und dabei alles erlebt: von kleinen Startups bis zu Enterprise-Anwendungen mit Millionen von Nutzern. In diesem Guide teile ich die wichtigsten Erkenntnisse und Best Practices.
📚 Inhaltsverzeichnis
1. Laravel 12: Die Game-Changer Features
Laravel 12 bringt einige der bedeutendsten Verbesserungen seit Jahren. Als jemand, der jede Laravel-Version in Production eingesetzt hat, kann ich sagen: Diese Features werden deine Entwicklungsgeschwindigkeit und Code-Qualität revolutionieren.
🚀 Native Type Declarations
Endlich vollständige PHP 8.3+ Integration mit nativen Typ-Deklarationen in allen Framework-Komponenten.
class UserController extends Controller
{
public function store(
UserRequest $request,
UserService $service
): JsonResponse {
return $service->create($request->validated());
}
}
⚡ Enhanced Query Builder
Der Query Builder wurde komplett überarbeitet und ist jetzt bis zu 40% schneller bei komplexen Abfragen.
// Neue upsertMany() Methode
User::upsertMany([
['email' => 'john@example.com', 'name' => 'John'],
['email' => 'jane@example.com', 'name' => 'Jane']
], ['email'], ['name', 'updated_at']);
🎯 Meine Top 3 Laravel 12 Features
sometimes_required_with
und conditional_array
lösen komplexe Business-Logic elegant. 2. Installation & Setup: Der Profi-Weg
Nach hunderten von Laravel-Installationen habe ich einen bewährten Workflow entwickelt, der Zeit spart und von Anfang an für Skalierbarkeit sorgt.
🛠️ Mein Standard-Setup
Schritt 1: Laravel Installer (empfohlen)
# Laravel Installer global installieren
composer global require laravel/installer
# Neues Projekt erstellen
laravel new my-project --git --branch=main
# Mit zusätzlichen Optionen
laravel new my-project \
--git \
--branch=main \
--database=mysql \
--cache=redis \
--session=redis
Profi-Tipp: Ich verwende immer den Laravel Installer statt Composer create-project, da er optimierte Konfigurationen und die neuesten Abhängigkeiten liefert.
Schritt 2: Umgebung konfigurieren
# .env Datei anpassen
APP_NAME="My Laravel App"
APP_ENV=local
APP_DEBUG=true
APP_TIMEZONE=Europe/Berlin
# Datenbank (MySQL 8.0+)
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_laravel_app
# Cache & Sessions (Redis)
CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
Schritt 3: Entwicklungsumgebung mit Sail
# Laravel Sail installieren
php artisan sail:install
# Services auswählen: mysql,redis,meilisearch,mailpit
# Container starten
./vendor/bin/sail up -d
# Alias für einfachere Nutzung
alias sail='./vendor/bin/sail'
# Datenbank migrieren
sail artisan migrate
# NPM Dependencies installieren
sail npm install && sail npm run dev
3. Bewährte Architektur-Patterns
In 10 Jahren habe ich verschiedene Architektur-Ansätze getestet. Hier sind die Patterns, die sich in der Praxis bewährt haben und auch bei großen Teams funktionieren.
🏗️ Service-Repository Pattern
Repository Interface
<?php
namespace App\Contracts;
use App\Models\User;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
interface UserRepositoryInterface
{
public function findById(int $id): ?User;
public function findByEmail(string $email): ?User;
public function create(array $data): User;
public function update(User $user, array $data): bool;
public function paginate(int $perPage = 15): LengthAwarePaginator;
}
Repository Implementation
<?php
namespace App\Repositories;
use App\Contracts\UserRepositoryInterface;
use App\Models\User;
class UserRepository implements UserRepositoryInterface
{
public function __construct(
private User $model
) {}
public function findById(int $id): ?User
{
return $this->model
->with(['profile', 'roles'])
->find($id);
}
public function create(array $data): User
{
return $this->model->create($data);
}
}
🎯 Service Layer
<?php
namespace App\Services;
use App\Contracts\UserRepositoryInterface;
use App\Events\UserCreated;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
class UserService
{
public function __construct(
private UserRepositoryInterface $userRepository
) {}
public function createUser(array $data): User
{
// Business Logic
$data['password'] = Hash::make($data['password']);
// Repository aufrufen
$user = $this->userRepository->create($data);
// Event auslösen
event(new UserCreated($user));
return $user;
}
}
💡 Warum Service-Repository Pattern?
- • Testbarkeit: Services lassen sich perfekt mocken und testen
- • Wiederverwendbarkeit: Business Logic ist von Controllern entkoppelt
- • Skalierbarkeit: Neue Features lassen sich einfach hinzufügen
- • Team-Entwicklung: Klare Verantwortlichkeiten für verschiedene Entwickler
4. Eloquent Advanced: Performance & Best Practices
Eloquent ist mächtig, aber auch gefährlich. Hier sind die Techniken, die ich in High-Traffic-Anwendungen verwende, um Performance-Probleme zu vermeiden.
🚀 Query Optimization
❌ N+1 Problem
// Schlecht: N+1 Queries
$users = User::all();
foreach ($users as $user) {
echo $user->profile->bio; // +1 Query!
}
✅ Eager Loading
// Gut: 2 Queries total
$users = User::with('profile')->get();
foreach ($users as $user) {
echo $user->profile->bio; // Kein Query!
}
🎯 Advanced Relationships
<?php
// Model: User.php
class User extends Model
{
// Conditional Eager Loading
public function posts(): HasMany
{
return $this->hasMany(Post::class);
}
// Nur veröffentlichte Posts
public function publishedPosts(): HasMany
{
return $this->posts()->where('status', 'published');
}
// Count Relationship
public function postsCount(): Attribute
{
return Attribute::make(
get: fn () => $this->posts()->count()
);
}
}
⚡ Query Scopes für Wiederverwendbarkeit
<?php
class Post extends Model
{
// Local Scope
public function scopePublished(Builder $query): void
{
$query->where('status', 'published')
->where('published_at', '<=', now());
}
// Dynamic Scope
public function scopeByAuthor(Builder $query, User $author): void
{
$query->where('user_id', $author->id);
}
// Global Scope (automatisch angewendet)
protected static function booted(): void
{
static::addGlobalScope(new ActiveScope);
}
}
// Verwendung:
$posts = Post::published()
->byAuthor($user)
->with(['comments', 'tags'])
->paginate(10);
5. Professionelle API-Entwicklung
APIs sind das Herzstück moderner Anwendungen. Hier zeige ich dir, wie ich APIs entwickle, die auch bei Millionen von Requests pro Tag stabil laufen.
🛡️ API Resources & Transformations
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->when(
$request->user()->can('view-email', $this->resource),
$this->email
),
'avatar' => $this->whenNotNull($this->avatar_url),
'posts_count' => $this->whenCounted('posts'),
'posts' => PostResource::collection($this->whenLoaded('posts')),
'created_at' => $this->created_at->toISOString(),
];
}
}
🔐 API Authentication mit Sanctum
<?php
// AuthController.php
class AuthController extends Controller
{
public function login(LoginRequest $request): JsonResponse
{
$credentials = $request->validated();
if (!Auth::attempt($credentials)) {
return response()->json([
'message' => 'Invalid credentials'
], 401);
}
$user = Auth::user();
$token = $user->createToken(
'api-token',
['read', 'write'], // Abilities
now()->addDays(30) // Expiration
);
return response()->json([
'user' => new UserResource($user),
'token' => $token->plainTextToken,
'expires_at' => $token->accessToken->expires_at
]);
}
}
📊 Rate Limiting & Throttling
<?php
// RouteServiceProvider.php
protected function configureRateLimiting(): void
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)
->by($request->user()?->id ?: $request->ip());
});
// Spezielle Limits für verschiedene Endpunkte
RateLimiter::for('login', function (Request $request) {
return Limit::perMinute(5)->by($request->ip());
});
RateLimiter::for('uploads', function (Request $request) {
return Limit::perHour(100)->by($request->user()->id);
});
}
6. Performance-Optimierung: Meine bewährten Techniken
Performance ist entscheidend. Hier sind die Optimierungen, die in meinen Projekten die größten Verbesserungen gebracht haben.
🎯 Meine Performance-Checkliste
Database
- • Query-Optimierung mit EXPLAIN
- • Proper Indexing
- • Database Connection Pooling
- • Read Replicas für Skalierung
Caching
- • Redis für Session & Cache
- • Query Result Caching
- • HTTP Response Caching
- • CDN für Static Assets
⚡ Caching Strategien
<?php
// Repository mit Cache
class UserRepository
{
public function findById(int $id): ?User
{
return Cache::remember(
"user.{$id}",
3600, // 1 Stunde
fn() => User::with(['profile', 'roles'])->find($id)
);
}
public function update(User $user, array $data): bool
{
$updated = $user->update($data);
// Cache invalidieren
Cache::forget("user.{$user->id}");
return $updated;
}
}
🔄 Queue Jobs für Heavy Tasks
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class ProcessUserDataJob implements ShouldQueue
{
use Queueable, InteractsWithQueue;
public int $tries = 3;
public int $timeout = 300; // 5 Minuten
public function __construct(
private User $user,
private array $data
) {}
public function handle(): void
{
// Heavy processing hier
sleep(10); // Simuliert schwere Arbeit
$this->user->update($this->data);
}
public function failed(Throwable $exception): void
{
// Fehler-Behandlung
Log::error('Job failed', [
'user_id' => $this->user->id,
'exception' => $exception->getMessage()
]);
}
}
10. Enterprise-Patterns: Skalierung für Millionen
Diese Patterns verwende ich in Enterprise-Anwendungen, die Millionen von Requests verarbeiten. Sie sind das Ergebnis von Jahren der Optimierung und Skalierung.
🏢 Domain-Driven Design (DDD)
// Domain Structure
app/
├── Domain/
│ ├── User/
│ │ ├── Models/
│ │ │ └── User.php
│ │ ├── Repositories/
│ │ │ └── UserRepositoryInterface.php
│ │ ├── Services/
│ │ │ └── UserService.php
│ │ └── Events/
│ │ └── UserCreated.php
│ └── Order/
│ ├── Models/
│ ├── Services/
│ └── ValueObjects/
├── Infrastructure/
│ ├── Repositories/
│ └── Services/
└── Application/
├── Http/
└── Console/
🎯 CQRS (Command Query Responsibility Segregation)
<?php
// Command (Write)
class CreateUserCommand
{
public function __construct(
public readonly string $name,
public readonly string $email,
public readonly string $password
) {}
}
// Command Handler
class CreateUserHandler
{
public function handle(CreateUserCommand $command): User
{
// Validation, Business Logic
return User::create([
'name' => $command->name,
'email' => $command->email,
'password' => Hash::make($command->password)
]);
}
}
// Query (Read)
class GetUserQuery
{
public function __construct(
public readonly int $userId
) {}
}
🚀 Warum Enterprise-Patterns?
Skalierbarkeit: Code bleibt wartbar auch bei 100+ Entwicklern
Testbarkeit: Jede Komponente lässt sich isoliert testen
Performance: Read/Write können separat optimiert werden
Flexibilität: Business Logic ist von Framework entkoppelt
Fazit: Laravel 12 in der Praxis
Nach 10 Jahren Laravel-Entwicklung kann ich sagen: Laravel 12 ist die bisher beste Version. Die Performance-Verbesserungen, neuen Features und die verbesserte Developer Experience machen es zur idealen Wahl für moderne Webentwicklung.
Die in diesem Guide gezeigten Patterns und Techniken sind in der Praxis erprobt und haben sich in Produktionsumgebungen bewährt. Nutze sie als Grundlage für deine eigenen Laravel-Projekte und passe sie an deine spezifischen Anforderungen an.