Ketika kita menjalankan php hal.php, yang sesungguhnya bekerja adalah sebuah program utuh bernama runtime PHP: penerjemah yang membaca teks, memahaminya, lalu mengeksekusinya. Memahami runtime ini bukan ilmu tambahan yang bisa dilewati — diagnosa “halaman lambat”, keputusan mengaktifkan OPcache, hingga kebingungan “kenapa variabel saya hilang antar-request” semuanya dijawab oleh cara kerja runtime. Pada chapter ini kita membedah komponen-komponen runtime PHP, tahapan dari kode sumber sampai eksekusi, dan model per-request yang menjadi identitas PHP.

Komponen Utama PHP Runtime #

Runtime PHP terdiri dari tiga lapisan besar yang bekerja sama. Pertama, Zend Engine — inti bahasa yang bertanggung jawab mengurai sintaks, mengompilasi, dan mengeksekusi kode; namanya berasal dari pendirinya, Zeev Suraski dan Andi Gutmans, sejak era PHP 4. Kedua, extensions — modul-modul seperti pdo_sqlite untuk database atau curl untuk HTTP yang menambah kemampuan baru berupa fungsi dan class. Ketiga, SAPI (Server API) — lapisan antarmuka yang menentukan dari mana PHP dipanggil: lewat terminal (cli), lewat web server melalui PHP-FPM (fpm-fcgi), atau lewat server tertanam.

Ketiga lapisan ini menjelaskan satu fenomena yang sering membingungkan pemula: mengapa hasil php -v di terminal bisa berbeda perilaku dengan PHP yang menjalankan situs di hosting. Keduanya bisa jadi versi berbeda dengan set ekstensi berbeda dan php.ini berbeda — meskipun Zend Engine dan bahasanya sama. Sekumpulan konstanta bawaan memungkinkan kita mengintip identitas runtime dari dalam kode, seperti yang akan kita lakukan pada bagian penutup chapter ini.

Dari Kode Sumber ke Opcode #

Zend Engine memproses kode dalam beberapa tahap berurutan. Diagram berikut memetakan alurnya:

Berikut uraian setiap tahap pada diagram tersebut:

  1. Lexer memindai teks kode dan memotongnya menjadi token — pasangan jenis dan isi, misalnya variabel $harga, angka 15000, operator =.
  2. Parser menyusun token menjadi AST (abstract syntax tree) — pohon yang menggambarkan struktur program, misalnya “penugasan ekspresi perkalian ke variabel”. Kesalahan sintaks terdeteksi di tahap ini, sebelum satu instruksi pun berjalan.
  3. Compiler menerjemahkan AST menjadi daftar opcode — instruksi mesin virtual tingkat rendah seperti “ambil nilai, kalikan, simpan”.
  4. Executor menjalankan opcode satu per satu sambil memelihara tabel variabel dan hasil antara; output dari echo dan teks HTML mengalir keluar pada tahap ini.

Tahap 1 sampai 3 inilah yang dikenal sebagai compile phase, dan proses ini berulang setiap kali berkas diminta — kecuali OPcache turun tangan. Ekstensi OPcache menyimpan opcode hasil kompilasi di memori bersama, sehingga permintaan berikutnya untuk berkas yang sama dapat langsung melompat ke tahap eksekusi tanpa mengulang lexing-parsing-compiling. Pada server produksi, OPcache praktis selalu diaktifkan karena penghematannya besar; pada PHP 8, mesin ini juga dilengkapi JIT (just-in-time compiler) opsional yang menerjemahkan opcode “panas” menjadi instruksi mesin asli untuk beban kerja tertentu.

Model Eksekusi Per-Request #

Karakter paling khas dari PHP adalah model shared-nothing per-request. Setiap permintaan HTTP menjalankan siklus hidup lengkap: runtime menyiapkan superglobal ($_GET, $_POST, $_SERVER, dan kawanannya) dari data permintaan, mengeksekusi skrip dari keadaan bersih, lalu setelah tanggapan terkirim seluruh keadaan — variabel, koneksi database, koneksi jaringan — dibongkar. Tidak ada memori bersama yang tersisa untuk permintaan berikutnya.

Model ini punya dua wajah. Wajah positifnya: penalaran menjadi sederhana dan isolasi kuat — memori bocor pada satu permintaan tidak menumpuk memengaruhi permintaan lain, dan Anda tidak perlu mengelola siklus hidup objek lintas permintaan. Konsekuensinya: keadaan yang perlu bertahan (data login pengguna, isi keranjang belanja) harus disimpan di luar memori proses, misalnya di session yang backend-nya berupa berkas atau database, dan koneksi database dibuka ulang per permintaan. Untuk kebutuhan proses long-running ala Node.js atau aplikasi realtime, komunitas PHP menyediakan jalur khusus seperti ekstensi Swoole dan runtime FrankenPHP — topik lanjutan di luar cakupan course dasar ini.

Mengintip Runtime dari Dalam #

PHP menyediakan konstanta dan fungsi untuk menanyakan identitas runtime yang sedang menjalankan kode kita. Program berikut memeriksa versi bahasa, SAPI yang dipakai, versi Zend Engine, hingga arsitektur integer:

php
<?php
echo "Versi PHP      : " . PHP_VERSION . "\n";
echo "ID versi       : " . PHP_VERSION_ID . "\n";
echo "SAPI aktif     : " . PHP_SAPI . "\n";
echo "Zend Engine    : " . zend_version() . "\n";
echo "Integer        : " . PHP_INT_SIZE . " byte (" . (PHP_INT_SIZE * 8) . "-bit)\n";
echo "Sistem operasi : " . PHP_OS_FAMILY . "\n";

Output yang Dihasilkan:

text
Versi PHP      : 8.4.23
ID versi       : 80423
SAPI aktif     : cli
Zend Engine    : 4.4.23
Integer        : 8 byte (64-bit)
Sistem operasi : Linux

Mari kita bedah tiap baris program di atas:

  1. Baris 2 dan 3: PHP_VERSION menyajikan versi lengkap (misalnya 8.4.23), sedangkan PHP_VERSION_ID menyandikannya menjadi satu angka (misalnya 80423) yang mudah dibandingkan — kita akan memanfaatkannya pada chapter Versi PHP dan Kompatibilitas.
  2. Baris 4: PHP_SAPI melaporkan antarmuka yang dipakai untuk memanggil PHP. Nilai cli berarti dari terminal; nilai fpm-fcgi atau apache2handler berarti dari web server.
  3. Baris 5: fungsi zend_version() mengembalikan versi Zend Engine — angka yang mengikuti versi PHP.
  4. Baris 6: PHP_INT_SIZE adalah ukuran tipe integer dalam byte; angka ini menentukan apakah PHP berjalan 32-bit atau 64-bit.
  5. Baris 7: PHP_OS_FAMILY merangkum keluarga sistem operasi seperti Linux, Windows, atau Darwin (macOS).

Dari Zend Engine hingga SAPI, kita kini mengenal seluruh lapisan yang menghidupkan kode PHP. Satu aspek terakhir yang wajib dipahami sebelum menulis kode serius adalah versi: PHP berkembang setiap tahun, dan runtime yang menjalankan kode Anda hari ini mungkin bukan runtime yang sama milik rekan tim atau server produksi. Chapter berikutnya membahas peta versi PHP beserta cara menulis kode yang tetap kompatibel.

Referensi #