Fungsi-fungsi I/O yang telah kita gunakan sejauh ini — fopen(), file_get_contents(), hingga fwrite() — berjalan dengan perilaku bawaan yang sama pada setiap pemanggilan. Perilaku bawaan tersebut memadai untuk berkas lokal, tetapi menjadi masalah begitu target berpindah ke jaringan: permintaan HTTP tanpa batas waktu bisa menggantung berlama-lama, sebagian server menolak klien tanpa User-Agent, dan verifikasi sertifikat SSL perlu dikontrol secara eksplisit. Stream context adalah mekanisme PHP untuk mengatur semua perilaku tersebut. Pada chapter ini kita akan mempelajari cara membuat context, opsi-opsi yang paling sering dipakai, dan cara menyambungkannya ke fungsi-fungsi stream yang sudah Anda kenal.
Apa Itu Stream Context #
Stream context adalah kumpulan opsi yang menyertai sebuah operasi stream dan dibaca oleh wrapper sebelum stream dibuka. Secara teknis, context dibentuk dari array bertingkat: kunci tingkat pertama adalah nama wrapper (misalnya http atau ssl), kunci tingkat kedua adalah nama opsi, dan nilainya adalah pengaturan yang kita inginkan. Struktur bertingkat ini penting karena opsi dengan nama mirip bisa berbeda makna pada wrapper yang berbeda.
Context diterima sebagai parameter opsional terakhir pada banyak fungsi filesystem: fopen(), file_get_contents(), file(), file_put_contents(), copy(), hingga mkdir(). Jika kita tidak memberikan context, PHP memakai context default bawaan — dan seperti akan kita lihat di bagian akhir chapter, context default tersebut bisa kita ubah.
Membuat Context dengan stream_context_create #
Fungsi stream_context_create() menerima array opsi bertingkat lalu mengembalikan resource context. Contoh berikut menyiapkan context untuk sebuah permintaan HTTP POST dengan batas waktu lima detik, lengkap dengan pengaturan verifikasi SSL:
<?php
$context = stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\nUser-Agent: KursusPHP/1.0",
'timeout' => 5,
'ignore_errors' => true,
],
'ssl' => [
'verify_peer' => true,
'verify_peer_name' => true,
],
]);
echo json_encode(
stream_context_get_options($context),
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
), "\n";Output yang Dihasilkan:
{
"http": {
"method": "POST",
"header": "Content-Type: application/json\r\nUser-Agent: KursusPHP/1.0",
"timeout": 5,
"ignore_errors": true
},
"ssl": {
"verify_peer": true,
"verify_peer_name": true
}
}Mari kita bedah kode di atas baris per baris:
- Array
'http': kumpulan opsi untuk wrapperhttp. Opsimethodmengatur metode HTTP,headermenampung baris header tambahan yang dipisah\r\n,timeoutmembatasi durasi operasi baca dalam detik, danignore_errorsmembuatfile_get_contents()tetap mengembalikan body respons meskipun server menjawab status 4xx atau 5xx. - Array
'ssl': opsi untuk lapisan TLS ketika URL menggunakanhttps://.verify_peerdanverify_peer_namesama-sama bernilaitrue— ini memang nilai bawaannya, tetapi menuliskannya secara eksplisit membuat niat kode lebih jelas. stream_context_get_options(): membaca kembali seluruh opsi yang tersimpan di dalam context — berguna untuk memastikan konfigurasi sudah benar sebelum context dipakai.json_encode()denganJSON_PRETTY_PRINT: kita pakai hanya untuk menampilkan struktur context secara rapi; pada pemakaian nyata context langsung diteruskan ke fungsi stream.
Perhatikan bahwa satu context boleh berisi opsi untuk beberapa wrapper sekaligus. Opsi untuk wrapper yang tidak terlibat dalam operasi akan diabaikan tanpa error.
Opsi yang Sering Dipakai #
Dua kelompok opsi berikut paling sering muncul dalam kode sehari-hari:
| Wrapper | Opsi | Kegunaan |
|---|---|---|
http | method | Metode HTTP: GET, POST, HEAD, dan sebagainya |
http | header | Header tambahan, dipisah \r\n |
http | timeout | Batas waktu operasi baca/tulis socket, dalam detik |
http | ignore_errors | Tetap baca body meski status respons 4xx/5xx |
http | max_redirects | Jumlah maksimum redirect yang diikuti |
ssl | verify_peer | Verifikasi sertifikat server |
ssl | verify_peer_name | Cocokkan nama host dengan sertifikat |
ssl | allow_self_signed | Izinkan sertifikat self-signed, hanya untuk lingkungan pengembangan |
Memakai Context di file_get_contents #
file_get_contents() menerima context pada argumen ketiganya. Pola lengkapnya terlihat pada contoh berikut, yang mengunduh sebuah berkas teks dari server publik:
<?php
$context = stream_context_create([
'http' => [
'method' => 'GET',
'header' => "User-Agent: KursusPHP/1.0\r\nAccept: text/plain",
'timeout' => 5,
],
]);
$isi = file_get_contents('https://www.php.net/robots.txt', false, $context);
if ($isi === false) {
echo "Permintaan gagal\n";
} else {
echo "Total byte yang diterima: " . strlen($isi) . "\n";
}Contoh di atas membutuhkan akses jaringan sehingga tidak dieksekusi otomatis di halaman ini, tetapi mudah Anda coba sendiri. Saat kami mengujinya secara manual, berkas robots.txt berhasil diunduh dan jumlah byte-nya tercetak — angka pastinya berubah sewaktu-waktu karena isi berkas di server ikut diperbarui, itulah sebabnya kami tidak mencantumkannya sebagai output tetap.
Tiga perilaku penting dari contoh tersebut:
- Argumen kedua
falsemenonaktifkan pencarian diinclude_path; context selalu duduk di argumen ketiga. timeout => 5memastikan permintaan yang macet berhenti setelah lima detik. Tanpa context, operasi jaringan mengikutidefault_socket_timeoutyang bernilai 60 detik — terlalu lama untuk sebuah permintaan web.$http_response_header— variabel ini otomatis dibuat oleh PHP setelah pemanggilan sukses dan berisi array baris header respons (status line beserta seluruh headernya). Saat diuji, array tersebut terisi lebih dari dua puluh elemen sehingga kita bisa memeriksa kode status tanpa ekstensi cURL.
Context Default untuk Semua Stream #
Kadang kita ingin satu pengaturan berlaku untuk seluruh operasi HTTP dalam skrip tanpa harus membuat context berulang-ulang. Fungsi stream_context_set_default() mengubah context bawaan yang dipakai PHP ketika tidak ada context eksplisit:
<?php
stream_context_set_default([
'http' => [
'timeout' => 10,
'header' => 'User-Agent: KursusPHP/1.0',
],
]);
// Semua operasi stream http selanjutnya memakai opsi di atas
$default = stream_context_get_default();
echo json_encode(
stream_context_get_options($default),
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
), "\n";Output yang Dihasilkan:
{
"http": {
"timeout": 10,
"header": "User-Agent: KursusPHP/1.0"
}
}stream_context_get_default() mengembalikan context bawaan tersebut, dan stream_context_get_options() membuktikan bahwa opsi kita sudah menempel padanya. Mulai titik ini, setiap file_get_contents('https://...') tanpa context eksplisit akan membawa User-Agent dan batas waktu sepuluh detik.
Context Bersama fopen dan fgets #
fopen() menerima context pada argumen keempatnya. Kombinasi ini berguna ketika kita ingin membaca respons jaringan secara bertahap dengan fgets() atau fread(), alih-alih memuat seluruh isi ke memori sekaligus seperti file_get_contents():
<?php
$context = stream_context_create([
'http' => ['timeout' => 5],
]);
$handle = fopen('https://www.php.net/robots.txt', 'r', false, $context);
if ($handle === false) {
exit("Gagal membuka URL\n");
}
$jumlahBaris = 0;
while (($baris = fgets($handle)) !== false) {
$jumlahBaris++;
}
echo "Jumlah baris: $jumlahBaris\n";
fclose($handle);Sama seperti contoh sebelumnya, blok ini memerlukan jaringan sehingga Anda perlu menjalankannya sendiri — saat kami mencobanya, seluruh baris robots.txt terbaca satu per satu dan terhitung tiga belas baris. Pola pembacaannya identik dengan membaca berkas lokal: stream yang dibuka oleh fopen() bersifat seragam, terlepas dari sumbernya berkas di disk atau respons HTTP. Perbedaannya hanya ada pada argumen keempat fopen() yang kita isi dengan context pembawa timeout, sehingga proses tidak pernah menggantung lebih dari lima detik saat server lambat merespons.
Ringkasan #
Stream context melengkapi API stream dengan lapisan konfigurasi: stream_context_create() membungkus opsi per wrapper, fungsi-fungsi seperti file_get_contents() dan fopen() menerimanya lewat parameter tambahan, dan stream_context_set_default() mengatur konfigurasi global. Dengan bekal ini, kita siap membongkar mesin di balik URL seperti http:// dan data:// — yaitu stream wrapper — pada chapter berikutnya.