Laravel Lösungen: Fortgeschrittene Patterns, Debugging und Interview-Fragen 2026
Fortgeschrittene Laravel-Lösungen mit Service-Klassen, Repository-Pattern, Telescope-Debugging und Interview-Fragen für erfahrene PHP-Entwickler.

Laravel-Lösungen für Produktionsanwendungen erfordern mehr als grundlegende CRUD-Operationen. Der Unterschied zwischen Junior- und Senior-Laravel-Entwicklern zeigt sich in der Codestrukturierung, dem Debugging von Problemen und den Antworten auf architektonische Fragen in Vorstellungsgesprächen.
Senior-Laravel-Positionen erwarten, dass Kandidaten den Service Container erklären, Debugging-Workflows mit Telescope oder Debugbar demonstrieren und begründen können, wann Patterns wie Repository vs. direkte Eloquent-Queries angewendet werden sollten.
Service-Klassen: Geschäftslogik aus Controllern extrahieren
Controller in Laravel behandeln HTTP-Aspekte: Anfragen empfangen, Eingaben validieren und Antworten zurückgeben. Geschäftslogik gehört in dedizierte Service-Klassen, was den Code testbar und wiederverwendbar über Controller, Commands und Jobs hinweg macht.
// Service class encapsulating order business logic
namespace App\Services;
use App\Models\Order;
use App\Models\User;
use App\Exceptions\InsufficientStockException;
use App\Jobs\SendOrderConfirmationEmail;
use Illuminate\Support\Facades\DB;
class OrderService
{
public function __construct(
private InventoryService $inventory,
private PaymentService $payment
) {}
/**
* Create an order with full validation and side effects
*
* @throws InsufficientStockException
*/
public function createOrder(User $user, array $items, string $paymentMethod): Order
{
// Validate stock availability before starting transaction
foreach ($items as $item) {
if (!$this->inventory->hasStock($item['product_id'], $item['quantity'])) {
throw new InsufficientStockException($item['product_id']);
}
}
return DB::transaction(function () use ($user, $items, $paymentMethod) {
// Create order record
$order = $user->orders()->create([
'status' => 'pending',
'total' => $this->calculateTotal($items),
]);
// Attach order items
foreach ($items as $item) {
$order->items()->create($item);
$this->inventory->decrementStock($item['product_id'], $item['quantity']);
}
// Process payment
$this->payment->charge($user, $order->total, $paymentMethod);
$order->update(['status' => 'paid']);
// Queue confirmation email
SendOrderConfirmationEmail::dispatch($order);
return $order;
});
}
private function calculateTotal(array $items): int
{
return collect($items)->sum(fn($item) => $item['price'] * $item['quantity']);
}
}// Controller delegating to service class
namespace App\Http\Controllers;
use App\Http\Requests\CreateOrderRequest;
use App\Services\OrderService;
use Illuminate\Http\JsonResponse;
class OrderController extends Controller
{
public function __construct(
private OrderService $orderService
) {}
public function store(CreateOrderRequest $request): JsonResponse
{
$order = $this->orderService->createOrder(
$request->user(),
$request->validated('items'),
$request->validated('payment_method')
);
return response()->json(['order_id' => $order->id], 201);
}
}Service-Klassen können überall in Laravel injiziert werden: Controller, Commands, andere Services oder Job-Klassen. Die Service Container Dokumentation behandelt automatische Auflösung und Binding.
Repository Pattern: Wenn direktes Eloquent nicht ausreicht
Das Repository-Pattern fügt eine Abstraktionsschicht zwischen Geschäftslogik und Datenzugriff hinzu. Dieses Pattern erweist sich als wertvoll, wenn Anwendungen Datenquellen wechseln, Query-Ergebnisse transparent cachen oder komplexe Query-Logik isolieren müssen.
Kandidaten werden oft gefragt, ob sie das Repository-Pattern mit Laravel verwenden. Die richtige Antwort hängt vom Kontext ab: Repositories bieten Mehrwert für große Anwendungen mit komplexen Datenanforderungen, erzeugen aber unnötige Abstraktion für einfache CRUD-Anwendungen.
// Interface defining the contract
namespace App\Repositories\Contracts;
use App\Models\User;
use Illuminate\Support\Collection;
interface UserRepositoryInterface
{
public function findById(int $id): ?User;
public function findByEmail(string $email): ?User;
public function getActiveUsers(): Collection;
public function getUsersWithRecentOrders(int $days = 30): Collection;
public function create(array $data): User;
public function update(User $user, array $data): User;
}// Eloquent implementation of the repository
namespace App\Repositories;
use App\Models\User;
use App\Repositories\Contracts\UserRepositoryInterface;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
class EloquentUserRepository implements UserRepositoryInterface
{
public function findById(int $id): ?User
{
return Cache::remember(
"user.{$id}",
now()->addMinutes(10),
fn() => User::find($id)
);
}
public function findByEmail(string $email): ?User
{
return User::where('email', $email)->first();
}
public function getActiveUsers(): Collection
{
return User::where('status', 'active')
->orderBy('name')
->get();
}
public function getUsersWithRecentOrders(int $days = 30): Collection
{
return User::whereHas('orders', function ($query) use ($days) {
$query->where('created_at', '>=', now()->subDays($days));
})
->with(['orders' => fn($q) => $q->latest()->limit(5)])
->get();
}
public function create(array $data): User
{
$user = User::create($data);
Cache::forget("user.{$user->id}");
return $user;
}
public function update(User $user, array $data): User
{
$user->update($data);
Cache::forget("user.{$user->id}");
return $user->fresh();
}
}// Binding interface to implementation
namespace App\Providers;
use App\Repositories\Contracts\UserRepositoryInterface;
use App\Repositories\EloquentUserRepository;
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->bind(
UserRepositoryInterface::class,
EloquentUserRepository::class
);
}
}Die Repository-Implementierung behandelt Caching intern und hält Service-Klassen auf Geschäftsregeln fokussiert, anstatt sich um Cache-Invalidierung zu kümmern.
Bereit für deine Laravel-Interviews?
Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.
Laravel-Anwendungen mit Telescope debuggen
Laravel Telescope bietet einen Debug-Assistenten, der Anfragen, Exceptions, Datenbankabfragen, Jobs und mehr aufzeichnet. Produktions-Debugging erfordert das Verständnis, welche Metriken wichtig sind und wie man Rauschen filtert.
// Telescope configuration for different environments
return [
'enabled' => env('TELESCOPE_ENABLED', true),
// Only record slow queries in production
'query' => [
'slow' => env('TELESCOPE_SLOW_QUERY_THRESHOLD', 100), // milliseconds
],
// Prune old entries to manage database size
'storage' => [
'database' => [
'connection' => env('DB_CONNECTION', 'mysql'),
'chunk' => 1000,
],
],
];// Custom filtering for Telescope entries
namespace App\Providers;
use Laravel\Telescope\IncomingEntry;
use Laravel\Telescope\Telescope;
use Laravel\Telescope\TelescopeApplicationServiceProvider;
class TelescopeServiceProvider extends TelescopeApplicationServiceProvider
{
public function register(): void
{
Telescope::night();
$this->hideSensitiveRequestDetails();
// Filter out noise in production
Telescope::filter(function (IncomingEntry $entry) {
// Always record exceptions and slow queries
if ($entry->isException()) {
return true;
}
if ($entry->isSlowQuery()) {
return true;
}
// Skip health check endpoints
if ($entry->isRequest() && str_starts_with($entry->content['uri'] ?? '', '/health')) {
return false;
}
// Skip static asset requests
if ($entry->isRequest() && preg_match('/\.(css|js|png|jpg|svg)$/', $entry->content['uri'] ?? '')) {
return false;
}
// Record everything in local environment
if ($this->app->environment('local')) {
return true;
}
// Production: only record failures and slow operations
return $entry->isFailedRequest()
|| $entry->isFailedJob()
|| $entry->hasMonitoredTag();
});
}
protected function hideSensitiveRequestDetails(): void
{
// Hide sensitive data from Telescope UI
Telescope::hideRequestParameters(['password', 'password_confirmation', 'token']);
Telescope::hideRequestHeaders(['authorization', 'cookie']);
}
}Die Methode isSlowQuery() markiert Datenbankabfragen, die den konfigurierten Schwellenwert überschreiten. Die Analyse langsamer Queries deckt fehlende Indizes und N+1-Probleme auf, die auch Profiling-Tools wie Debugbar erkennen.
Häufige Interview-Fragen und starke Antworten
Technische Interviews für Laravel-Positionen folgen Mustern. Die folgenden Fragen erscheinen häufig, und die Antworten demonstrieren die Tiefe, die Interviewer erwarten.
Was ist der Service Container und warum ist er wichtig?
Der Service Container ist Laravels Dependency Injection Container. Er verwaltet Klassenabhängigkeiten und führt Dependency Injection automatisch durch. Wenn ein Controller-Konstruktor OrderService als Type-Hint hat, löst der Container eine Instanz auf und injiziert sie.
// Automatic resolution: container reads type hints and builds dependencies
public function __construct(OrderService $service)
{
// $service is automatically instantiated and injected
}
// Manual binding for interfaces or complex setup
$this->app->bind(PaymentGateway::class, function ($app) {
return new StripeGateway(
config('services.stripe.key'),
config('services.stripe.secret')
);
});
// Singleton: same instance throughout the request
$this->app->singleton(MetricsCollector::class, function ($app) {
return new MetricsCollector(
$app->make(Cache::class)
);
});Der Container ermöglicht lose Kopplung: Klassen hängen von Abstraktionen (Interfaces) ab statt von konkreten Implementierungen, was Testing und das Austauschen von Implementierungen vereinfacht.
Wie behandelt Laravel Datenbank-Transaktionen?
Laravel umschließt Datenbankoperationen mit der Methode DB::transaction() in Transaktionen. Transaktionen gewährleisten Atomarität: Entweder sind alle Operationen erfolgreich, oder alle werden zurückgerollt.
// Simple transaction with automatic rollback on exception
DB::transaction(function () {
$user = User::create(['email' => 'test@example.com']);
$user->profile()->create(['bio' => 'New user']);
// If profile creation fails, user creation rolls back
});
// Manual transaction control for complex flows
DB::beginTransaction();
try {
$order = Order::create($data);
PaymentGateway::charge($order->total);
DB::commit();
} catch (PaymentFailedException $e) {
DB::rollBack();
throw $e;
}
// Nested transactions use savepoints
DB::transaction(function () {
User::create(['email' => 'outer@test.com']);
DB::transaction(function () {
// This creates a savepoint
Profile::create(['user_id' => 1]);
});
// Inner failure only rolls back to savepoint
});Interviewer fragen oft nach Deadlocks. Die Antwort: Laravel wiederholt Transaktionen, die aufgrund von Deadlocks fehlschlagen (konfigurierbar über das zweite Argument von DB::transaction()).
Middleware erklären und einen praktischen Anwendungsfall nennen
Middleware filtert HTTP-Anfragen, die in die Anwendung eingehen. Jede Middleware kann Anfragen untersuchen, modifizieren oder ablehnen, bevor sie Controller erreichen.
// Custom middleware checking team membership
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class EnsureTeamMember
{
public function handle(Request $request, Closure $next, string $role = 'member'): Response
{
$team = $request->route('team');
if (!$request->user()->belongsToTeam($team)) {
abort(403, 'You are not a member of this team.');
}
if ($role === 'admin' && !$request->user()->isTeamAdmin($team)) {
abort(403, 'Admin access required.');
}
return $next($request);
}
}// Applying middleware to routes
Route::middleware(['auth', 'team.member:admin'])->group(function () {
Route::get('/teams/{team}/settings', [TeamController::class, 'settings']);
Route::put('/teams/{team}/settings', [TeamController::class, 'updateSettings']);
});Middleware wird in Reihenfolge ausgeführt. Authentifizierungs-Middleware sollte vor Autorisierungs-Middleware laufen, und Logging-Middleware umschließt typischerweise alles.
Das N+1-Query-Problem lösen
Das N+1-Problem erzeugt eine Query für die initiale Collection plus eine Query pro Element beim Zugriff auf Beziehungen. Eine Liste von 100 Artikeln mit Autoren produziert 101 Queries statt 2.
// Problem: 101 queries for 100 articles
$articles = Article::all();
foreach ($articles as $article) {
echo $article->author->name; // Each access triggers a query
}
// Solution: eager load with 2 queries total
$articles = Article::with('author')->get();
foreach ($articles as $article) {
echo $article->author->name; // No additional queries
}
// Nested eager loading for complex relationships
$articles = Article::with([
'author.profile',
'comments' => fn($query) => $query->latest()->limit(5),
'comments.user',
'tags',
])->get();Laravel kann Lazy Loading verhindern in der Entwicklung, um N+1-Probleme früh zu erkennen:
use Illuminate\Database\Eloquent\Model;
public function boot(): void
{
Model::preventLazyLoading(!$this->app->isProduction());
}Mit dieser Einstellung wirft der Zugriff auf eine nicht geladene Beziehung in der Entwicklung eine Exception und erzwingt explizites Eager Loading.
Bereit für deine Laravel-Interviews?
Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.
Action-Klassen für Einzelzweck-Operationen
Action-Klassen kapseln einzelne Operationen, die von mehreren Einstiegspunkten aufgerufen werden können. Im Gegensatz zu Service-Klassen, die verwandte Methoden gruppieren, behandeln Actions eine Aufgabe mit klaren Ein- und Ausgaben.
// Single-purpose action class
namespace App\Actions;
use App\Models\User;
use App\Notifications\WelcomeNotification;
use Illuminate\Support\Facades\Hash;
class CreateUserAction
{
public function execute(array $data): User
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
$user->notify(new WelcomeNotification());
return $user;
}
}// Usage in controller
public function store(RegisterRequest $request, CreateUserAction $action)
{
$user = $action->execute($request->validated());
return redirect()->route('dashboard');
}
// Usage in command
public function handle(CreateUserAction $action)
{
$user = $action->execute([
'name' => $this->argument('name'),
'email' => $this->argument('email'),
'password' => $this->argument('password'),
]);
$this->info("Created user: {$user->id}");
}
// Usage in test
public function test_user_creation(): void
{
$action = new CreateUserAction();
$user = $action->execute([
'name' => 'Test User',
'email' => 'test@example.com',
'password' => 'password',
]);
$this->assertDatabaseHas('users', ['email' => 'test@example.com']);
}Action-Klassen funktionieren gut mit Laravels Job-System: Die Action enthält die Logik, und der Job behandelt Queueing und Retry-Verhalten.
Event-getriebene Architektur mit Events und Listeners
Events entkoppeln den Moment, in dem etwas passiert, von den Reaktionen auf dieses Event. Wenn eine Bestellung aufgegeben wird, wird das OrderPlaced-Event ausgelöst. Listeners behandeln E-Mail-Versand, Analytics-Updates und Lagerbenachrichtigungen unabhängig voneinander.
// Event class carrying order data
namespace App\Events;
use App\Models\Order;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class OrderPlaced
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(
public Order $order
) {}
}// Queued listener for email
namespace App\Listeners;
use App\Events\OrderPlaced;
use App\Notifications\OrderConfirmationNotification;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendOrderConfirmation implements ShouldQueue
{
public function handle(OrderPlaced $event): void
{
$event->order->user->notify(
new OrderConfirmationNotification($event->order)
);
}
}// Another listener for the same event
namespace App\Listeners;
use App\Events\OrderPlaced;
use App\Services\AnalyticsService;
use Illuminate\Contracts\Queue\ShouldQueue;
class UpdateInventoryAnalytics implements ShouldQueue
{
public function __construct(
private AnalyticsService $analytics
) {}
public function handle(OrderPlaced $event): void
{
foreach ($event->order->items as $item) {
$this->analytics->recordSale(
$item->product_id,
$item->quantity,
$event->order->created_at
);
}
}
}// Dispatching the event
OrderPlaced::dispatch($order);
// Or using the event helper
event(new OrderPlaced($order));Listeners, die ShouldQueue implementieren, laufen asynchron und verhindern, dass langsame Operationen die HTTP-Antwort blockieren.
Erkenntnisse für Laravel-Entwickler
- Service-Klassen extrahieren Geschäftslogik aus Controllern, verbessern die Testbarkeit und ermöglichen Wiederverwendung über HTTP-, CLI- und Queue-Kontexte hinweg
- Das Repository-Pattern bietet Mehrwert, wenn Anwendungen Caching, Datenquellenabstraktion oder komplexe Query-Kapselung benötigen, erzeugt aber Overhead für einfaches CRUD
- Telescope-Filter reduzieren Rauschen in der Produktion, indem nur Exceptions, langsame Queries und fehlgeschlagene Operationen aufgezeichnet werden
- Der Service Container verwaltet Dependency Injection automatisch durch Type-Hints, mit expliziten Bindings für Interfaces und komplexe Setups
- N+1-Probleme verschwinden mit Eager Loading via
with(), undModel::preventLazyLoading()erkennt fehlende Eager Loads während der Entwicklung - Action-Klassen behandeln Einzelzweck-Operationen, die von Controllern, Commands, Tests und Jobs aufrufbar sind
- Events entkoppeln "was passiert ist" von "was als nächstes passieren soll", wobei Queued Listeners Seiteneffekte asynchron behandeln
- Interview-Antworten sollten Verständnis für Trade-offs demonstrieren: wann Patterns helfen versus wann sie unnötige Komplexität hinzufügen
Fang an zu üben!
Teste dein Wissen mit unseren Interview-Simulatoren und technischen Tests.
Findest du den Bug in Laravel?
Ein echter Codeausschnitt, ein versteckter Bug, ein Versuch pro Tag. Zum Ausprobieren ohne Konto.

Geschrieben von
Anthony Fillion-MailletGründer von SharpSkill
Seit über 10 Jahren Fullstack-Entwickler. Er leitet SharpSkill und verantwortet alles, was hier erscheint.
Aktualisiert am 25. August 2026
Tags
Teilen
Verwandte Artikel

Laravel 12 im Jahr 2026: Neue Features, Starter Kits und Interview-Fragen
Laravel 12 bringt komplett überarbeitete Starter Kits mit React 19, Vue 3, Livewire 4 und WorkOS AuthKit. Ein umfassender Leitfaden zu neuen Features, dem Upgrade-Pfad und wichtigen Interview-Fragen für 2026.

Laravel Testing mit Pest 5 in 2026: TIA, Mocking und Interviewfragen
Laravel Testing Best Practices mit Pest 5, Test Impact Analysis, Mockery, Facade Fakes und Architektur-Tests. Unit Tests, Feature Tests, Mocking-Strategien und Interviewfragen fuer Laravel-Entwickler.

Laravel und PHP Interviewfragen: Die Top 25 in 2026
Die 25 haeufigsten Laravel- und PHP-Interviewfragen. Eloquent ORM, Middleware, Artisan, Queues, Tests und Architektur mit ausfuehrlichen Antworten und Codebeispielen.