Artikel sebelumnya menjelaskan apa itu Context facade di Laravel 12. Artikel ini fokus pada implementasi nyata: bagaimana Context dipakai untuk trace request ID, propagasi ke jobs, dan debugging yang lebih mudah.
Studi Kasus 1: Request ID di Semua Log
Masalah klasik: saat ada error, sulit tahu log mana yang terkait satu request. Solusi dengan Context:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Str;
class AddRequestContext
{
public function handle(Request $request, Closure $next): mixed
{
Context::add([
'request_id' => Str::uuid()->toString(),
'url' => $request->fullUrl(),
'method' => $request->method(),
'ip' => $request->ip(),
'user_id' => $request->user()?->id,
]);
return $next($request);
}
}
Daftarkan di bootstrap/app.php:
->withMiddleware(function (Middleware $middleware) {
$middleware->prepend(AddRequestContext::class);
})
Sekarang semua log di seluruh request otomatis punya context:
Log::info('Memproses pembayaran');
// Output di log:
// [2025-04-18 10:23:45] local.INFO: Memproses pembayaran {"request_id":"abc-123","url":"/checkout","user_id":42}
Studi Kasus 2: Propagasi Context ke Queue Jobs
Masalah: ketika request trigger job di queue, context (request ID, user ID) hilang.
Solusi: Context secara otomatis dipropagasi ke jobs jika menggunakan Illuminate\Queue\SerializesModels atau kalau job implement ShouldQueue — tapi kita harus pastikan data context yang ingin dipropagasi ada di “hydrated context”.
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Log;
class ProcessPayment implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable;
public function __construct(
private int $orderId
) {}
public function handle(): void
{
// Context dari request yang dispatch job ini otomatis tersedia
$requestId = Context::get('request_id');
Log::info("Memproses pembayaran order {$this->orderId}", [
'request_id' => $requestId,
]);
// proses pembayaran...
}
}
Studi Kasus 3: Hidden Context untuk Data Sensitif
Beberapa context tidak ingin muncul di log tapi perlu tersedia di kode:
// Tambah context tersembunyi — tidak masuk ke log
Context::addHidden([
'payment_token' => $request->payment_token,
'api_key' => config('services.payment.key'),
]);
// Ambil di bagian lain
$token = Context::getHidden('payment_token');
Studi Kasus 4: Debugging Feature Flag
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Context;
class TrackFeatureFlags
{
public function handle(Request $request, Closure $next): mixed
{
$user = $request->user();
if ($user) {
Context::add([
'features' => [
'new_checkout' => $user->hasFeature('new-checkout'),
'ai_recommendations' => $user->hasFeature('ai-rec'),
],
]);
}
return $next($request);
}
}
Kalau ada bug laporan dari user tertentu, cek log dan langsung tahu fitur apa yang aktif saat itu.
Dehydrate dan Hydrate untuk Custom Serialization
Untuk objek yang tidak bisa di-serialize otomatis:
Context::dehydrating(function (Context $context) {
// Ubah Carbon ke string saat queue job dikirim
if ($context->has('started_at')) {
$context->add('started_at', $context->get('started_at')->toIso8601String());
}
});
Context::hydrated(function (Context $context) {
// Kembalikan ke Carbon saat job diproses
if ($context->has('started_at')) {
$context->add('started_at', Carbon::parse($context->get('started_at')));
}
});
Baca Juga
Butuh tim yang bantu setup observability dan logging yang proper di aplikasi Laravel? Lihat layanan pengembangan aplikasi kami.