Laravel Çözümleri: Gelişmiş Desenler, Hata Ayıklama ve Mülakat Soruları 2026

Laravel'de gelişmiş mimari desenler, Telescope ile hata ayıklama teknikleri ve Laravel geliştiricileri için en sık sorulan mülakat sorularını kapsayan kapsamlı rehber.

PHP 8.4 ile Laravel gelişmiş hata ayıklama ve mimari desenler

Üretim uygulamaları için Laravel çözümleri, basit CRUD işlemlerinden çok daha fazlasını gerektirir. Junior ve senior Laravel geliştiricileri arasındaki fark, kodun nasıl yapılandırıldığı, sorunların nasıl ayıklandığı ve mülakatlar sırasında mimari sorulara nasıl yanıt verildiğinde ortaya çıkar.

Mülakatçıların Aradıkları

Senior Laravel pozisyonları, adayların Service Container'ı açıklamasını, Telescope veya Debugbar ile hata ayıklama iş akışlarını göstermesini ve Repository deseni ile doğrudan Eloquent sorgularının ne zaman kullanılacağını gerekçelendirmesini bekler.

Servis Sınıfları: İş Mantığını Controller'lardan Çıkarma

Laravel'deki controller'lar HTTP işlerini yönetir: istekleri alma, girdiyi doğrulama ve yanıt döndürme. İş mantığı, kodu test edilebilir ve controller'lar, komutlar ve job'lar arasında yeniden kullanılabilir hale getiren özel servis sınıflarında yer almalıdır.

app/Services/OrderService.phpphp
// 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']);
    }
}
app/Http/Controllers/OrderController.phpphp
// 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);
    }
}

Servis sınıfları Laravel'de herhangi bir yere enjekte edilebilir: controller'lar, komutlar, diğer servisler veya job sınıfları. Service Container dokümantasyonu otomatik çözümleme ve bağlamayı kapsar.

Repository Deseni: Doğrudan Eloquent Yeterli Olmadığında

Repository deseni, iş mantığı ile veri erişimi arasına bir soyutlama katmanı ekler. Bu desen, uygulamaların veri kaynaklarını değiştirmesi, sorgu sonuçlarını şeffaf bir şekilde önbelleğe alması veya karmaşık sorgu mantığını izole etmesi gerektiğinde değerli olur.

Mülakat Bağlamı

Adaylara genellikle Laravel ile repository deseni kullanıp kullanmadıkları sorulur. Doğru yanıt bağlama bağlıdır: repository'ler karmaşık veri gereksinimleri olan büyük uygulamalar için değer katar, ancak basit CRUD uygulamaları için gereksiz soyutlama oluşturur.

app/Repositories/Contracts/UserRepositoryInterface.phpphp
// 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;
}
app/Repositories/EloquentUserRepository.phpphp
// 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();
    }
}
app/Providers/RepositoryServiceProvider.phpphp
// 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
        );
    }
}

Repository implementasyonu önbelleğe almayı dahili olarak yönetir, servis sınıflarının önbellek geçersiz kılma yerine iş kurallarına odaklanmasını sağlar.

Laravel mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

Laravel Uygulamalarını Telescope ile Hata Ayıklama

Laravel Telescope, istekleri, istisnaları, veritabanı sorgularını, job'ları ve daha fazlasını kaydeden bir hata ayıklama asistanı sağlar. Üretim ortamında hata ayıklama, hangi metriklerin önemli olduğunu ve gürültünün nasıl filtreleneceğini anlamayı gerektirir.

config/telescope.phpphp
// 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,
        ],
    ],
];
app/Providers/TelescopeServiceProvider.phpphp
// 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']);
    }
}

isSlowQuery() metodu, yapılandırılmış eşiği aşan veritabanı sorgularını işaretler. Yavaş sorgu analizi, Debugbar gibi profil araçlarının da tespit ettiği eksik indeksleri ve N+1 sorunlarını ortaya çıkarır.

Yaygın Mülakat Soruları ve Güçlü Yanıtlar

Laravel pozisyonları için teknik mülakatlar belirli kalıpları takip eder. Aşağıdaki sorular sıkça karşılaşılır ve yanıtlar mülakatçıların beklediği derinliği gösterir.

Service Container Nedir ve Neden Önemlidir?

Service Container, Laravel'in bağımlılık enjeksiyon konteyneri'dir. Sınıf bağımlılıklarını yönetir ve bağımlılık enjeksiyonunu otomatik olarak gerçekleştirir. Bir controller constructor'ı OrderService tip belirteci kullandığında, konteyner bir örneği çözümler ve enjekte eder.

php
// 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)
    );
});

Konteyner gevşek bağlantıyı etkinleştirir: sınıflar somut implementasyonlar yerine soyutlamalara (interface'lere) bağımlıdır, bu da test etmeyi ve implementasyonları değiştirmeyi kolaylaştırır.

Laravel Veritabanı Transaction'larını Nasıl Yönetir?

Laravel, veritabanı işlemlerini DB::transaction() metoduyla transaction'lara sarar. Transaction'lar atomikliği sağlar: ya tüm işlemler başarılı olur ya da hepsi geri alınır.

php
// 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
});

Mülakatçılar genellikle deadlock'lar hakkında devam sorusu sorar. Yanıt: Laravel, deadlock nedeniyle başarısız olan transaction'ları yeniden dener (DB::transaction()'a ikinci argüman aracılığıyla yapılandırılabilir).

Middleware'i Açıklayın ve Gerçek Bir Kullanım Örneği Verin

Middleware, uygulamaya giren HTTP isteklerini filtreler. Her middleware, istekleri controller'lara ulaşmadan önce inceleyebilir, değiştirebilir veya reddedebilir.

app/Http/Middleware/EnsureTeamMember.phpphp
// 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);
    }
}
routes/web.phpphp
// 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'ler sırayla çalışır. Kimlik doğrulama middleware'i yetkilendirme middleware'inden önce çalışmalı ve loglama middleware'i genellikle her şeyi sarar.

N+1 Sorgu Sorununu Çözme

N+1 sorunu, ilk koleksiyon için bir sorgu artı ilişkilere erişildiğinde öğe başına bir sorgu üretir. 100 makalenin yazarlarıyla birlikte listesi 2 yerine 101 sorgu üretir.

php
// 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, N+1 sorunlarını erken yakalamak için geliştirme ortamında lazy loading'i engelleyebilir:

app/Providers/AppServiceProvider.phpphp
use Illuminate\Database\Eloquent\Model;

public function boot(): void
{
    Model::preventLazyLoading(!$this->app->isProduction());
}

Bu ayarla, yüklenmemiş bir ilişkiye erişmek geliştirme ortamında bir istisna fırlatır ve açık eager loading'i zorlar.

Laravel mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

Tek Amaçlı İşlemler İçin Action Sınıfları

Action sınıfları, birden çok giriş noktasından çağrılabilen tekil işlemleri kapsüller. İlgili metotları gruplandıran servis sınıflarının aksine, action'lar net girdiler ve çıktılarla tek bir görevi yönetir.

app/Actions/CreateUserAction.phpphp
// 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;
    }
}
php
// 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 sınıfları Laravel'in job sistemi ile iyi çalışır: action mantığı içerir ve job kuyruklama ve yeniden deneme davranışını yönetir.

Event'ler ve Listener'lar ile Event-Driven Mimari

Event'ler, bir şeyin olduğu anı o olaya verilen tepkilerden ayırır. Bir sipariş verildiğinde, OrderPlaced event'i tetiklenir. Listener'lar e-posta gönderme, analitik güncelleme ve depoları bilgilendirmeyi bağımsız olarak yönetir.

app/Events/OrderPlaced.phpphp
// 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
    ) {}
}
app/Listeners/SendOrderConfirmation.phpphp
// 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)
        );
    }
}
app/Listeners/UpdateInventoryAnalytics.phpphp
// 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
            );
        }
    }
}
php
// Dispatching the event
OrderPlaced::dispatch($order);

// Or using the event helper
event(new OrderPlaced($order));

ShouldQueue implemente eden listener'lar asenkron çalışır ve yavaş işlemlerin HTTP yanıtını engellemesini önler.

Laravel Geliştiricileri İçin Önemli Çıkarımlar

  • Servis sınıfları iş mantığını controller'lardan çıkarır, test edilebilirliği artırır ve HTTP, CLI ve kuyruk bağlamlarında yeniden kullanımı sağlar
  • Repository deseni, uygulamaların önbelleğe alma, veri kaynağı soyutlama veya karmaşık sorgu kapsülleme ihtiyacı olduğunda değer katar, ancak basit CRUD için yük oluşturur
  • Telescope filtreleri, yalnızca istisnaları, yavaş sorguları ve başarısız işlemleri kaydederek üretimde gürültüyü azaltır
  • Service Container, tip belirteçleri aracılığıyla bağımlılık enjeksiyonunu otomatik olarak yönetir, interface'ler ve karmaşık kurulumlar için açık bağlamalar kullanır
  • N+1 sorunları with() ile eager loading sayesinde ortadan kalkar ve Model::preventLazyLoading() geliştirme sırasında eksik eager load'ları yakalar
  • Action sınıfları, controller'lar, komutlar, testler ve job'lardan çağrılabilen tek amaçlı işlemleri yönetir
  • Event'ler "ne oldu"yu "ne olmalı"dan ayırır, kuyruğa alınmış listener'lar yan etkileri asenkron olarak yönetir
  • Mülakat yanıtları ödünleşimlerin anlaşıldığını göstermelidir: kalıpların ne zaman yardımcı olduğu ve ne zaman gereksiz karmaşıklık eklediği

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Günün meydan okuması

Laravel kodundaki hatayı bulabilir misin?

Gerçek bir kod parçası, gizli bir hata, günde bir deneme. Denemek için hesap gerekmez.

Anthony Fillion-Maillet

Yazan:

Anthony Fillion-Maillet

SharpSkill kurucusu

10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.

25 Ağustos 2026 tarihinde güncellendi

Etiketler

#laravel
#php
#debugging
#design-patterns
#interview

Paylaş

İlgili makaleler