PHP Laravel Framework Interview-Fragen 2026: Eloquent, Queues und Architekturmuster

Bereiten Sie sich auf Laravel-Interviews 2026 vor: Eloquent ORM, Queue-Systeme, Service Container und moderne Architekturmuster mit praxisnahen Codebeispielen.

PHP Laravel Framework Interview-Fragen 2026: Eloquent, Queues und Architekturmuster

Das Laravel-Framework bleibt auch 2026 eines der beliebtesten PHP-Frameworks für Unternehmensanwendungen. Entwickler, die sich auf technische Interviews vorbereiten, müssen ein tiefes Verständnis von Eloquent ORM, Queue-Systemen und modernen Architekturmustern demonstrieren.

Dieser Leitfaden behandelt fortgeschrittene Laravel-Konzepte, die in Senior-Entwickler-Interviews häufig abgefragt werden. Jede Frage enthält praktische Codebeispiele und erklärt die zugrundeliegenden Prinzipien.

Eloquent ORM: Fortgeschrittene Konzepte

Was ist der Unterschied zwischen eager Loading und lazy Loading in Eloquent?

Eager Loading löst das N+1-Problem, indem es verwandte Modelle in einer einzigen Abfrage lädt. Lazy Loading lädt Beziehungen erst bei Zugriff, was zu Performance-Problemen führen kann.

php
// Lazy Loading - verursacht N+1 Queries
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->author->name; // Jeder Zugriff = 1 Query
}

// Eager Loading - nur 2 Queries insgesamt
$posts = Post::with('author')->get();
foreach ($posts as $post) {
    echo $post->author->name; // Keine zusätzliche Query
}

// Nested Eager Loading
$posts = Post::with(['author', 'comments.user'])->get();

// Conditional Eager Loading
$posts = Post::with(['comments' => function ($query) {
    $query->where('approved', true)->orderBy('created_at', 'desc');
}])->get();

Wie implementiert man polymorphe Beziehungen?

Polymorphe Beziehungen ermöglichen es einem Modell, zu mehreren anderen Modellen zu gehören. Ein typisches Beispiel sind Kommentare, die sowohl zu Posts als auch zu Videos gehören können.

php
// Migration für polymorphe Tabelle
Schema::create('comments', function (Blueprint $table) {
    $table->id();
    $table->text('body');
    $table->morphs('commentable'); // Erstellt commentable_type und commentable_id
    $table->timestamps();
});

// Comment Model
class Comment extends Model
{
    public function commentable(): MorphTo
    {
        return $this->morphTo();
    }
}

// Post Model
class Post extends Model
{
    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

// Video Model
class Video extends Model
{
    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

// Verwendung
$post->comments()->create(['body' => 'Toller Artikel!']);
$video->comments()->create(['body' => 'Großartiges Video!']);

Was sind Eloquent Accessors und Mutators in Laravel 11+?

Mit Laravel 11 verwendet man das Attribute Cast-Pattern für Accessors und Mutators, was eine klarere Syntax bietet.

php
use Illuminate\Database\Eloquent\Casts\Attribute;

class User extends Model
{
    // Accessor und Mutator kombiniert
    protected function firstName(): Attribute
    {
        return Attribute::make(
            get: fn (string $value) => ucfirst($value),
            set: fn (string $value) => strtolower($value),
        );
    }

    // Computed Attribute (nur Accessor)
    protected function fullName(): Attribute
    {
        return Attribute::make(
            get: fn () => "{$this->first_name} {$this->last_name}",
        );
    }

    // Mit Caching für teure Berechnungen
    protected function profileScore(): Attribute
    {
        return Attribute::make(
            get: fn () => $this->calculateProfileScore(),
        )->shouldCache();
    }
}

Queue-Systeme und Hintergrundverarbeitung

Wie funktioniert das Laravel Queue-System?

Laravel Queues ermöglichen die Auslagerung zeitintensiver Aufgaben in Hintergrundprozesse. Das System unterstützt verschiedene Treiber wie Redis, Database und Amazon SQS.

php
// Job-Klasse definieren
class ProcessPodcast implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        public Podcast $podcast,
    ) {}

    public function handle(AudioProcessor $processor): void
    {
        $processor->process($this->podcast);
    }

    // Retry-Konfiguration
    public int $tries = 3;
    public int $backoff = 60;

    // Timeout definieren
    public int $timeout = 120;

    // Fehlerbehandlung
    public function failed(Throwable $exception): void
    {
        // Benachrichtigung senden oder Logging
    }
}

// Job dispatchen
ProcessPodcast::dispatch($podcast);

// Mit Verzögerung
ProcessPodcast::dispatch($podcast)->delay(now()->addMinutes(10));

// Auf bestimmte Queue
ProcessPodcast::dispatch($podcast)->onQueue('podcasts');

Was sind Job Batches und wie werden sie verwendet?

Job Batches ermöglichen die Gruppierung mehrerer Jobs mit gemeinsamer Fortschrittsverfolgung und Callbacks.

php
use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Bus;

$batch = Bus::batch([
    new ProcessPodcast($podcast1),
    new ProcessPodcast($podcast2),
    new ProcessPodcast($podcast3),
])->then(function (Batch $batch) {
    // Alle Jobs erfolgreich abgeschlossen
    Log::info('Batch completed successfully');
})->catch(function (Batch $batch, Throwable $e) {
    // Erster Fehler in der Batch
    Log::error('Batch failed', ['error' => $e->getMessage()]);
})->finally(function (Batch $batch) {
    // Batch abgeschlossen (mit oder ohne Fehler)
})->allowFailures()->dispatch();

// Batch-Status abfragen
$batch = Bus::findBatch($batchId);
echo $batch->progress(); // Fortschritt in Prozent
echo $batch->pendingJobs; // Ausstehende Jobs

Wie implementiert man Rate Limiting für Queues?

Rate Limiting verhindert die Überlastung externer APIs oder Ressourcen durch kontrollierte Job-Ausführung.

php
use Illuminate\Queue\Middleware\RateLimited;
use Illuminate\Support\Facades\RateLimiter;

// Rate Limiter definieren (in AppServiceProvider)
RateLimiter::for('api-requests', function (object $job) {
    return Limit::perMinute(60)->by($job->user->id);
});

class SendApiRequest implements ShouldQueue
{
    // Middleware anwenden
    public function middleware(): array
    {
        return [new RateLimited('api-requests')];
    }

    public function handle(): void
    {
        // API-Anfrage senden
    }

    // Job bei Rate Limit zurück in Queue
    public function retryUntil(): DateTime
    {
        return now()->addHours(1);
    }
}

Service Container und Dependency Injection

Wie funktioniert der Laravel Service Container?

Der Service Container ist das Herzstück von Laravel und verwaltet Klassenabhängigkeiten durch Dependency Injection.

php
// Interface definieren
interface PaymentGatewayInterface
{
    public function charge(int $amount): PaymentResult;
}

// Implementierung
class StripePaymentGateway implements PaymentGatewayInterface
{
    public function __construct(
        private string $apiKey,
    ) {}

    public function charge(int $amount): PaymentResult
    {
        // Stripe-Logik
    }
}

// Binding im ServiceProvider
public function register(): void
{
    // Simple Binding
    $this->app->bind(PaymentGatewayInterface::class, StripePaymentGateway::class);

    // Binding mit Konfiguration
    $this->app->bind(PaymentGatewayInterface::class, function ($app) {
        return new StripePaymentGateway(
            apiKey: config('services.stripe.secret'),
        );
    });

    // Singleton für einzelne Instanz
    $this->app->singleton(StripePaymentGateway::class);
}

// Verwendung in Controller
class PaymentController extends Controller
{
    public function __construct(
        private PaymentGatewayInterface $gateway,
    ) {}

    public function charge(Request $request): JsonResponse
    {
        $result = $this->gateway->charge($request->amount);
        return response()->json($result);
    }
}

Was ist Contextual Binding?

Contextual Binding ermöglicht unterschiedliche Implementierungen je nach Kontext der Verwendung.

php
// Verschiedene Implementierungen je nach Controller
$this->app->when(PhotoController::class)
    ->needs(Filesystem::class)
    ->give(function () {
        return Storage::disk('photos');
    });

$this->app->when(VideoController::class)
    ->needs(Filesystem::class)
    ->give(function () {
        return Storage::disk('videos');
    });

// Mit Primitiven
$this->app->when(ReportGenerator::class)
    ->needs('$format')
    ->give('pdf');

Architekturmuster und Best Practices

Wie implementiert man das Repository Pattern in Laravel?

Das Repository Pattern abstrahiert die Datenzugriffsschicht und verbessert Testbarkeit sowie Wartbarkeit.

php
// Interface
interface UserRepositoryInterface
{
    public function find(int $id): ?User;
    public function findByEmail(string $email): ?User;
    public function create(array $data): User;
    public function update(User $user, array $data): User;
    public function delete(User $user): bool;
}

// Eloquent-Implementierung
class EloquentUserRepository implements UserRepositoryInterface
{
    public function __construct(
        private User $model,
    ) {}

    public function find(int $id): ?User
    {
        return $this->model->find($id);
    }

    public function findByEmail(string $email): ?User
    {
        return $this->model->where('email', $email)->first();
    }

    public function create(array $data): User
    {
        return $this->model->create($data);
    }

    public function update(User $user, array $data): User
    {
        $user->update($data);
        return $user->fresh();
    }

    public function delete(User $user): bool
    {
        return $user->delete();
    }
}

// Service-Klasse verwendet Repository
class UserService
{
    public function __construct(
        private UserRepositoryInterface $repository,
        private HashManager $hash,
    ) {}

    public function registerUser(array $data): User
    {
        $data['password'] = $this->hash->make($data['password']);
        return $this->repository->create($data);
    }
}

Was sind Actions und wie strukturiert man komplexe Geschäftslogik?

Actions sind Single-Responsibility-Klassen für komplexe Geschäftsoperationen. Sie verbessern die Testbarkeit und Wiederverwendbarkeit.

php
class CreateOrderAction
{
    public function __construct(
        private OrderRepository $orders,
        private InventoryService $inventory,
        private PaymentGatewayInterface $payment,
        private NotificationService $notifications,
    ) {}

    public function execute(User $user, Cart $cart, PaymentMethod $method): Order
    {
        // Inventar prüfen
        $this->inventory->checkAvailability($cart->items);

        // Zahlung verarbeiten
        $paymentResult = $this->payment->charge(
            amount: $cart->total,
            method: $method,
        );

        // Bestellung erstellen
        $order = $this->orders->create([
            'user_id' => $user->id,
            'total' => $cart->total,
            'payment_id' => $paymentResult->id,
            'items' => $cart->items->toArray(),
        ]);

        // Inventar aktualisieren
        $this->inventory->decrementStock($cart->items);

        // Benachrichtigungen senden
        $this->notifications->orderCreated($order);

        return $order;
    }
}

// Verwendung in Controller
class OrderController extends Controller
{
    public function store(
        StoreOrderRequest $request,
        CreateOrderAction $action,
    ): JsonResponse {
        $order = $action->execute(
            user: $request->user(),
            cart: $request->user()->cart,
            method: $request->paymentMethod(),
        );

        return response()->json($order, 201);
    }
}

Wie implementiert man Event Sourcing-Konzepte in Laravel?

Event Sourcing speichert Zustandsänderungen als Ereignisse, was vollständige Audit-Trails und Zeitreisen ermöglicht.

php
// Event definieren
class OrderPlaced
{
    public function __construct(
        public string $orderId,
        public array $items,
        public int $total,
        public Carbon $occurredAt,
    ) {}
}

// Event Store
class EventStore
{
    public function append(string $aggregateId, object $event): void
    {
        DB::table('events')->insert([
            'aggregate_id' => $aggregateId,
            'event_type' => get_class($event),
            'payload' => json_encode($event),
            'occurred_at' => now(),
        ]);
    }

    public function getEvents(string $aggregateId): Collection
    {
        return DB::table('events')
            ->where('aggregate_id', $aggregateId)
            ->orderBy('occurred_at')
            ->get()
            ->map(fn ($row) => unserialize($row->payload));
    }
}

// Aggregate rekonstruieren
class Order
{
    private array $items = [];
    private string $status = 'pending';

    public static function reconstitute(Collection $events): self
    {
        $order = new self();
        foreach ($events as $event) {
            $order->apply($event);
        }
        return $order;
    }

    private function apply(object $event): void
    {
        match (get_class($event)) {
            OrderPlaced::class => $this->applyOrderPlaced($event),
            OrderShipped::class => $this->applyOrderShipped($event),
            default => null,
        };
    }
}

Bereit für deine Laravel-Interviews?

Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.

Fazit

Laravel-Interviews 2026 erfordern tiefgreifendes Verständnis von Eloquent ORM mit seinen fortgeschrittenen Features wie polymorphen Beziehungen und dem neuen Attribute-Casting. Queue-Systeme mit Batches und Rate Limiting sind essentiell für skalierbare Anwendungen. Der Service Container und Dependency Injection bilden das Fundament für testbare, wartbare Architekturen. Repository Pattern, Action-Klassen und Event Sourcing-Konzepte demonstrieren architektonisches Denken auf Senior-Niveau. Die Beherrschung dieser Konzepte mit praktischen Codebeispielen unterscheidet erfolgreiche Kandidaten von der Masse.

Tägliche Challenge

Findest du den Bug in Laravel?

Ein echter Codeausschnitt, ein versteckter Bug, ein Versuch pro Tag. Zum Ausprobieren ohne Konto.

Anthony Fillion-Maillet

Geschrieben von

Anthony Fillion-Maillet

Gründer von SharpSkill

Seit über 10 Jahren Fullstack-Entwickler. Er leitet SharpSkill und verantwortet alles, was hier erscheint.

Aktualisiert am 16. September 2026

Teilen

Verwandte Artikel