Skrip command line yang berguna hampir selalu membutuhkan input: berkas mana yang diproses, siapa penggunanya, atau berapa jumlah data yang diinginkan. Input tersebut diberikan pengguna sebagai command-line arguments — teks yang ditulis setelah nama skrip saat memanggilnya. PHP menyediakan dua mekanisme utama untuk membacanya: variabel otomatis $argv untuk akses mentah, dan fungsi getopt() untuk mengenali opsi berbentuk flag. Pada chapter ini kita akan mempelajari keduanya, memisahkan opsi dari argumen posisi, memvalidasi masukan, lalu menutup dengan pola main() yang menjaga skrip tetap rapi.

Membaca Semua Argumen dengan $argv dan $argc #

Saat skrip CLI dijalankan, PHP otomatis menyiapkan dua variabel: $argv berupa array yang memuat nama skrip beserta seluruh argumen, dan $argc berupa jumlah elemen $argv. Indeks 0 selalu diisi nama berkas skrip, sehingga argumen pertama dari pengguna berada di $argv[1]. Tabel berikut memetakan isinya untuk perintah php sapa.php Budi Santoso:

EkspresiIsi
$argc3
$argv[0]sapa.php (nama berkas skrip)
$argv[1]Budi (argumen pertama)
$argv[2]Santoso (argumen kedua)

Mari kita lihat wujudnya dalam kode:

php
<?php
printf("Jumlah argumen: %d\n", $argc);
printf("Halo, %s %s!\n", $argv[1], $argv[2]);

Output yang Dihasilkan:

text
Jumlah argumen: 3
Halo, Budi Santoso!

Baris pertama mencetak 3 karena $argc menghitung nama skrip bersama dua argumen. Baris kedua menggabungkan $argv[1] dan $argv[2] menjadi sapaan lengkap. Nilai $argv dan $argc tersedia otomatis di skrip CLI tanpa perlu deklarasi apa pun.

Semua Argumen Bertipe String #

Shell mengirimkan seluruh argumen sebagai teks, dan PHP tidak menebak maksud kita. Argumen 42 sampai di skrip sebagai string "42", bukan integer:

php
<?php
$angka = $argv[1] ?? "1";

var_dump($angka);
var_dump($angka + 10);

Output yang Dihasilkan:

text
string(2) "42"
int(52)

Keluaran var_dump() menegaskan bahwa $angka bertipe string(2) "42". Operasi $angka + 10 tetap berhasil karena PHP mengonversi string numerik menjadi integer secara otomatis — perilaku yang dikenal sebagai type juggling. Meskipun berjalan, jangan mengandalkan konversi diam-diam ini: ubah secara eksplisit dengan (int) $argv[1] atau (float) $argv[1] agar niat kode terbaca jelas dan skrip tidak terkejut ketika argumen ternyata bukan angka.

Memakai Opsi dengan getopt #

Tool command line dewasa seperti git atau composer memakai opsi: flag pendek -v, opsi panjang --verbose, dan opsi bernilai --user=Budi. Menulis parser sendiri untuk bentuk-bentuk ini rawan kekeliruan; PHP menyediakan fungsi getopt() yang mengenalinya untuk kita. Fungsi ini menerima string opsi pendek dan array opsi panjang, lalu mengembalikan opsi yang dikenali sebagai array asosiatif:

php
<?php
$options = getopt("u:v", ["verbose", "user:"]);

var_export($options);
echo "\n";

Output yang Dihasilkan:

text
array (
  'verbose' => false,
  'user' => 'Budi',
)

Aturan penulisannya ringkas namun harus tepat. Dalam string "u:v", huruf tanpa titik dua (v) adalah flag tanpa nilai, sedangkan huruf dengan titik dua (u:) menuntut nilai. Daftar opsi panjang memakai aturan yang sama secara terpisah: "verbose" tanpa nilai dan "user:" dengan nilai. Tabel berikut merangkum formatnya:

FormatArtiContoh pemakaian
uflag pendek tanpa nilai-u
u:opsi pendek yang menuntut nilai-u Budi
"verbose"opsi panjang tanpa nilai--verbose
"user:"opsi panjang yang menuntut nilai--user=Budi

Kunci pada hasil getopt() mengikuti bentuk opsi yang dipakai pengguna: -u Budi menghasilkan kunci u, sedangkan --user=Budi menghasilkan kunci user. Flag tanpa nilai bernilai false. Perhatikan demonstrasi berikut saat hanya opsi pendek yang dipakai:

bash
php opsi-sederhana.php -u Budi

Output yang Dihasilkan:

text
array (
  'u' => 'Budi',
)

Memisahkan Opsi dari Argumen Posisi #

Argumen yang bukan opsi — misalnya nama berkas target — disebut argumen posisi. Parameter ketiga getopt() dioper secara by reference dan akan berisi indeks $argv tempat pemindaian opsi berhenti; dari titik itulah argumen posisi dimulai:

php
<?php
$restIndex = null;
$options = getopt("u:v", ["user:"], $restIndex);
$files = array_slice($argv, $restIndex);

$user = $options["u"] ?? $options["user"] ?? "tanpa nama";
printf("Pengguna: %s\n", $user);
printf("Berkas: %s\n", implode(", ", $files));

Output yang Dihasilkan:

text
Pengguna: Siti
Berkas: data-a.csv, data-b.csv

Ekspresi $options["u"] ?? $options["user"] mengambil nilai opsi dari bentuk pendek ataupun panjang, sehingga pengguna bebas memilih gaya penulisan. Fungsi array_slice() memotong $argv mulai indeks $restIndex sehingga yang tersisa hanyalah daftar berkas murni. Pola “opsi terlebih dahulu, lalu argumen posisi” inilah yang dipakai hampir semua tool Unix.

bash
php opsi.php laporan.txt --user=Budi

Output yang Dihasilkan:

text
Pengguna: tanpa nama
Berkas: laporan.txt, --user=Budi

Pada pemanggilan di atas, laporan.txt membuat getopt() langsung berhenti sehingga --user=Budi tidak pernah diproses sebagai opsi. Karena itu, dokumentasikan urutan pemanggilan yang benar pada pesan pemakaian skrip Anda.

Validasi Argumen dan Pesan Pemakaian #

Argumen berasal dari manusia — bisa salah ketik, bisa pula dikosongkan. Skrip yang baik memvalidasi argumen sebelum bekerja, menampilkan pesan pemakaian (usage message) saat input tidak benar, dan keluar dengan kode galat. Skrip konversi.php berikut menerapkan ketiganya:

php
<?php
$command = $argv[1] ?? null;

if ($command === null || $command === "--help" || $command === "-h") {
    echo "Pemakaian: php konversi.php <meter>\n";
    echo "Mengonversi meter ke sentimeter.\n";
    exit(0);
}

if (!is_numeric($command)) {
    fwrite(STDERR, "Galat: \"$command\" bukan angka.\n");
    exit(1);
}

$meter = (float) $command;
printf("%.2f m = %.2f cm\n", $meter, $meter * 100);

Output yang Dihasilkan:

text
1.50 m = 150.00 cm

Mari kita telaah alurnya langkah demi langkah:

  1. Baris 2 ($command = $argv[1] ?? null;): argumen pertama diambil dengan nilai cadangan null agar skrip tidak memicu warning saat dijalankan tanpa argumen.
  2. Baris 4-8 (if ($command === null || ...)): skrip tanpa argumen, atau dengan -h/--help, diarahkan ke pesan pemakaian. Pesan ini dicetak ke STDOUT dan ditutup exit(0) — meminta bantuan adalah tindakan yang sah, bukan kegagalan.
  3. Baris 10-13 (if (!is_numeric(...))): nilai yang bukan angka ditolak. Pesan galat dikirim ke STDERR dan exit(1) menandai kegagalan.
  4. Baris 15-16: baris yang bertahan dari validasi akhirnya dikonversi secara eksplisit dengan (float) sebelum dihitung.

Dua skenario pentingnya tampak seperti ini di terminal:

bash
php konversi.php --help
echo "exit code: $?"

Output yang Dihasilkan:

text
Pemakaian: php konversi.php <meter>
Mengonversi meter ke sentimeter.
exit code: 0
bash
php konversi.php abc
echo "exit code: $?"

Output yang Dihasilkan:

text
Galat: "abc" bukan angka.
exit code: 1

Konvensi pesan pemakaian ke STDOUT dan pesan galat ke STDERR akan semakin jelas setelah kita membahas ketiga stream tersebut pada chapter stdin, stdout, dan stderr.

Pola Fungsi main #

Saat skrip memanjang, menulis seluruh logika di ruang lingkup global membuat variabel mudah bertabrakan dan kode sulit diuji. Solusinya: bungkus logika dalam fungsi main() yang menerima $argv dan mengembalikan kode keluar bertipe integer:

php
<?php
declare(strict_types=1);

function main(array $argv): int
{
    $nama = $argv[1] ?? "Dunia";
    printf("Halo, %s!\n", $nama);
    return 0;
}

exit(main($argv));

Output yang Dihasilkan:

text
Halo, Dunia!

Baris terakhir exit(main($argv)) adalah inti pola ini: nilai kembali fungsi main() — sebuah integer — langsung menjadi exit code skrip. Logika kini terisolasi di dalam fungsi sehingga bisa diuji terpisah, misalnya dengan memanggil main(["salam.php", "Siti"]) dari berkas uji. Skrip yang sama tetap responsif terhadap argumen sungguhan:

bash
php salam-main.php Siti

Output yang Dihasilkan:

text
Halo, Siti!

Ringkasan #

$argv dan $argc memberi akses mentah ke seluruh argumen yang selalu bertipe string, sementara getopt() mengenali opsi pendek dan panjang beserta nilainya. Argumen posisi diambil lewat array_slice($argv, $restIndex) setelah pemindaian opsi berhenti, validasi menjaga skrip dari masukan yang salah, dan pola main() menjaga struktur kode tetap sehat. Setelah argumen, pintu masukan lain yang tak kalah penting adalah data yang mengalir lewat pipe — kita akan membahasnya pada chapter stdin, stdout, dan stderr.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

contoh.php

Unduh berkas
php
<?php

declare(strict_types=1);

// contoh.php — rangkuman Chapter Command-Line Arguments.
// Jalankan dengan: php contoh.php [nama] [jumlah]
// Tanpa argumen skrip memakai nilai bawaan sehingga selalu aman dijalankan.

function main(array $argv): int
{
    $nama = $argv[1] ?? "Budi";
    $jumlah = max(1, min(5, (int) ($argv[2] ?? "2")));

    for ($i = 1; $i <= $jumlah; $i++) {
        printf("%d. Halo, %s!\n", $i, $nama);
    }

    return 0;
}

exit(main($argv));