Laravel Solutions: Pola Tingkat Lanjut, Debugging, dan Pertanyaan Interview 2026
Pelajari pola arsitektur Laravel tingkat lanjut, teknik debugging dengan Telescope, dan persiapan pertanyaan interview untuk posisi senior developer Laravel tahun 2026.

Solusi Laravel untuk aplikasi produksi membutuhkan lebih dari sekadar operasi CRUD dasar. Perbedaan antara developer Laravel junior dan senior terlihat dari cara mereka menyusun kode, men-debug masalah, dan menjawab pertanyaan arsitektur saat interview.
Posisi senior Laravel mengharapkan kandidat untuk menjelaskan Service Container, mendemonstrasikan workflow debugging dengan Telescope atau Debugbar, dan memberikan justifikasi kapan menggunakan pola seperti Repository versus query Eloquent langsung.
Service Classes: Mengekstrak Logika Bisnis dari Controllers
Controller di Laravel menangani urusan HTTP: menerima request, memvalidasi input, dan mengembalikan response. Logika bisnis seharusnya berada di class service khusus, membuat kode dapat diuji dan dapat digunakan kembali di seluruh controller, command, dan job.
// 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 classes dapat di-inject di mana saja dalam Laravel: controller, command, service lain, atau class job. Dokumentasi Service Container membahas resolusi otomatis dan binding.
Repository Pattern: Ketika Eloquent Langsung Tidak Cukup
Repository pattern menambahkan lapisan abstraksi antara logika bisnis dan akses data. Pola ini terbukti berharga ketika aplikasi perlu mengganti sumber data, meng-cache hasil query secara transparan, atau mengisolasi logika query yang kompleks.
Kandidat sering ditanya apakah mereka menggunakan repository pattern dengan Laravel. Jawaban yang tepat tergantung konteks: repository menambah nilai untuk aplikasi besar dengan kebutuhan data yang kompleks, tetapi menciptakan abstraksi yang tidak perlu untuk aplikasi CRUD sederhana.
// 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
);
}
}Implementasi repository menangani caching secara internal, menjaga class service tetap fokus pada aturan bisnis daripada invalidasi cache.
Siap menguasai wawancara Laravel Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
Debugging Aplikasi Laravel dengan Telescope
Laravel Telescope menyediakan asisten debug yang merekam request, exception, query database, job, dan lainnya. Debugging produksi membutuhkan pemahaman metrik mana yang penting dan cara menyaring noise.
// 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']);
}
}Method isSlowQuery() menandai query database yang melebihi threshold yang dikonfigurasi. Analisis slow query mengungkapkan index yang hilang dan masalah N+1 yang juga dideteksi oleh tool profiling seperti Debugbar.
Pertanyaan Interview Umum dan Jawaban yang Kuat
Interview teknis untuk posisi Laravel mengikuti pola tertentu. Pertanyaan di bawah ini sering muncul, dan jawabannya mendemonstrasikan kedalaman yang diharapkan pewawancara.
Apa Itu Service Container dan Mengapa Itu Penting?
Service Container adalah container dependency injection Laravel. Container ini mengelola dependensi class dan melakukan dependency injection secara otomatis. Ketika constructor controller menggunakan type-hint OrderService, container me-resolve dan meng-inject instance-nya.
// 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)
);
});Container memungkinkan loose coupling: class bergantung pada abstraksi (interface) daripada implementasi konkret, membuat pengujian dan penggantian implementasi menjadi mudah.
Bagaimana Laravel Menangani Transaksi Database?
Laravel membungkus operasi database dalam transaksi menggunakan method DB::transaction(). Transaksi memastikan atomicity: semua operasi berhasil, atau semuanya di-rollback.
// 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
});Pewawancara sering menindaklanjuti dengan bertanya tentang deadlock. Jawabannya: Laravel mencoba ulang transaksi yang gagal karena deadlock (dapat dikonfigurasi melalui argumen kedua ke DB::transaction()).
Jelaskan Middleware dan Berikan Kasus Penggunaan Nyata
Middleware menyaring request HTTP yang masuk ke aplikasi. Setiap middleware dapat memeriksa, memodifikasi, atau menolak request sebelum mencapai controller.
// 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 berjalan secara berurutan. Middleware authentication harus berjalan sebelum middleware authorization, dan middleware logging biasanya membungkus semuanya.
Menyelesaikan Masalah Query N+1
Masalah N+1 menghasilkan satu query untuk koleksi awal ditambah satu query per item saat mengakses relationship. Daftar 100 artikel dengan author menghasilkan 101 query alih-alih 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 dapat mencegah lazy loading dalam development untuk menangkap masalah N+1 lebih awal:
use Illuminate\Database\Eloquent\Model;
public function boot(): void
{
Model::preventLazyLoading(!$this->app->isProduction());
}Dengan pengaturan ini, mengakses relationship yang belum dimuat akan melempar exception dalam development, memaksa eager loading secara eksplisit.
Siap menguasai wawancara Laravel Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
Action Classes untuk Operasi Tujuan Tunggal
Action classes mengenkapsulasi operasi tunggal yang dapat dipanggil dari berbagai entry point. Tidak seperti service classes yang mengelompokkan method terkait, action menangani satu tugas dengan input dan output yang jelas.
// 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 classes bekerja dengan baik dengan sistem job Laravel: action berisi logika, dan job menangani perilaku queueing dan retry.
Arsitektur Event-Driven dengan Events dan Listeners
Event memisahkan momen sesuatu terjadi dari reaksi terhadap event tersebut. Ketika order ditempatkan, event OrderPlaced dipicu. Listener menangani pengiriman email, pembaruan analytics, dan notifikasi warehouse secara independen.
// 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));Listener yang mengimplementasikan ShouldQueue berjalan secara asynchronous, mencegah operasi lambat memblokir response HTTP.
Poin Penting untuk Developer Laravel
- Service classes mengekstrak logika bisnis dari controller, meningkatkan testability dan memungkinkan penggunaan ulang di seluruh konteks HTTP, CLI, dan queue
- Repository pattern menambah nilai ketika aplikasi membutuhkan caching, abstraksi sumber data, atau enkapsulasi query kompleks, tetapi menciptakan overhead untuk CRUD sederhana
- Filter Telescope mengurangi noise di produksi dengan hanya merekam exception, slow query, dan operasi yang gagal
- Service Container mengelola dependency injection secara otomatis melalui type hint, dengan binding eksplisit untuk interface dan setup kompleks
- Masalah N+1 hilang dengan eager loading via
with(), danModel::preventLazyLoading()menangkap eager load yang hilang selama development - Action classes menangani operasi tujuan tunggal yang dapat dipanggil dari controller, command, test, dan job
- Event memisahkan "apa yang terjadi" dari "apa yang harus terjadi selanjutnya", dengan queued listener menangani side effect secara asynchronous
- Jawaban interview harus mendemonstrasikan pemahaman tentang trade-off: kapan pola membantu versus kapan menambah kompleksitas yang tidak perlu
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Bisakah kamu menemukan bug di Laravel?
Satu potongan kode nyata, satu bug tersembunyi, satu percobaan per hari. Tanpa akun untuk mencoba.

Ditulis oleh
Anthony Fillion-MailletPendiri SharpSkill
Developer fullstack selama lebih dari 10 tahun. Ia menjalankan SharpSkill dan bertanggung jawab atas semua yang diterbitkan di sini.
Diperbarui 25 Agustus 2026
Bagikan
Artikel terkait

Pertanyaan Wawancara PHP Laravel Framework 2026: Eloquent, Queues, dan Pola Arsitektur
Pertanyaan wawancara PHP Laravel framework untuk 2026. Kuasai Eloquent ORM, arsitektur queue, pola service container, dan tantangan coding untuk posisi senior.

Laravel Octane di 2026: Swoole, RoadRunner dan Optimisasi Performa
Kuasai Laravel Octane 2.19 dengan FrankenPHP, Swoole dan RoadRunner. Pelajari pemilihan server, pencegahan memory leak, concurrent tasks, dan pola deployment production untuk aplikasi PHP berperforma tinggi.

Pertanyaan Interview PHP Laravel Developer 2026: Panduan Persiapan Lengkap
Panduan komprehensif untuk mempersiapkan interview PHP Laravel developer tahun 2026. Mencakup pertanyaan teknis Eloquent ORM, Service Container, authentication, queue, dan testing.