Koersi tipe di weak mode memang ramah, tetapi keramahannya berbayar: "5" yang seharusnya string bisa lolos menjadi 5, dan kesalahan data di hulu berjalan tanpa suara sampai menimbulkan kejanggalan di hilir. Pada aplikasi besar, banyak tim memilih mematikan koersi sama sekali agar setiap pemanggilan fungsi tunduk pada tipe yang tertulis apa adanya. PHP menyediakan declare(strict_types=1) untuk itu — dengan satu aturan penempatan dan satu semantik sisi pemanggil yang sering disalahpahami. Keduanya kita uji tuntas pada Chapter ini.
Mengaktifkan strict_types pada Berkas #
Arahan declare(strict_types=1) ditulis di baris paling atas berkas, tepat setelah tag <?php. Setelah aktif, semua pemanggilan fungsi yang dilakukan dari berkas tersebut menuntut tipe argumen yang persis — string "5" tidak lagi dikonversi menjadi integer, dan float 4.0 pun ditolak untuk parameter int meskipun konversinya tidak kehilangan nilai apa pun.
<?php
declare(strict_types=1);
require 'operasi.php';
echo tambah(5, 3) . "\n";
echo strlen("123") . "\n";Output yang Dihasilkan:
8
3Fungsi tambah() berasal dari berkas operasi.php yang tersedia di bagian bawah halaman ini — simpan berkas-berkas contoh pada folder yang sama sebelum menjalankannya. Kedua pemanggilan di atas lolos karena argumennya sudah bertepatan tipe: integer untuk tambah(5, 3), dan string untuk strlen("123") (fungsi bawaan juga tunduk pada strict mode). Hasil 8 dan 3 tercetak normal — strict mode bukan larangan memakai fungsi, melainkan larangan berpindah tipe diam-diam.
Weak vs Strict dengan Fungsi yang Sama #
Untuk melihat bedanya secara adil, kita pakai satu definisi fungsi yang sama — tambah(int $a, int $b): int di operasi.php yang tidak memakai declare apa pun — lalu memanggilnya dari dua berkas pemanggil yang berbeda. Berkas pertama membiarkan mode bawaan (weak); berkas kedua mengaktifkan strict_types.
<?php
require 'operasi.php';
echo tambah("5", "3") . "\n";
echo strlen(123) . "\n";Output yang Dihasilkan:
8
3Di weak mode, string numerik "5" dan "3" dikoersi menjadi integer sebelum masuk fungsi, menghasilkan 8; strlen(123) pun menerima integer yang dikonversi menjadi "123" lalu mengembalikan 3. Semua berjalan lancar — persis perilaku yang kita bahas pada Chapter Parameter Types. Sekarang berkas pemanggil yang kedua:
<?php
declare(strict_types=1);
require 'operasi.php';
echo tambah("5", "3") . "\n";Output yang Dihasilkan:
Fatal error: Uncaught TypeError: tambah(): Argument #1 ($a) must be of type int, string given, called in /home/z/my-project/php-course/content/php/fungsi/strict-types-dalam-fungsi/.verify_tmp.php on line 6 and defined in /home/z/my-project/php-course/content/php/fungsi/strict-types-dalam-fungsi/operasi.php:4
Stack trace:
#0 /home/z/my-project/php-course/content/php/fungsi/strict-types-dalam-fungsi/.verify_tmp.php(6): tambah('5', '3')
#1 {main}
thrown in /home/z/my-project/php-course/content/php/fungsi/strict-types-dalam-fungsi/operasi.php on line 4Pemanggilan yang sama kini berakhir TypeError dan program berhenti dengan exit code 255. Perhatikan isi pesannya: argumen $a dituntut bertipe int tetapi yang datang string. Tidak ada koersi penyelamat, tidak ada yang diubah diam-diam — ketidakcocokan tipe diekspos di baris tempat ia terjadi.
Semantik Sisi Pemanggil #
Inilah bagian yang paling sering disalahpahami: declare(strict_types=1) tidak mengubah fungsi — ia mengubah berkas pemanggil. Aturan koersi ditentukan oleh berkas tempat pemanggilan ditulis, bukan oleh berkas tempat fungsi didefinisikan. Itulah mengapa tambah() yang sama-sama didefinisikan di operasi.php bisa diterima longgar oleh satu berkas dan ditolak ketat oleh berkas lain.
Dua konsekuensi penting mengikuti semantik ini. Pertama, strict_types juga mengatur koersi nilai kembalian dari fungsi yang dipanggil di berkas tersebut — return "5"; dari fungsi : int akan dilempar TypeError bila pemanggilnya berada di berkas strict. Kedua, pengaturan ini mutlak per berkas: mencampur berkas strict dan non-strict dalam satu proyek sah-sah saja, dan kedua kubu berkomunikasi melalui tipe yang eksplisit. Praktik yang disarankan: aktifkan strict_types di seluruh berkas proyek baru agar perilakunya seragam, atau matikan di seluruhnya — jangan setengah-setengah tanpa kesepakatan tim.
Posisi declare Harus Paling Atas #
declare(strict_types=1) hanya sah sebagai statement pertama berkas. Ditempatkan di tengah kode — setelah echo, require, atau statement lain — PHP menolak seluruh berkas sebelum menjalankan apa pun:
<?php
echo "Memulai program\n";
declare(strict_types=1);Output yang Dihasilkan:
Fatal error: strict_types declaration must be the very first statement in the script in /home/z/my-project/php-course/content/php/fungsi/strict-types-dalam-fungsi/.verify_tmp.php on line 4Pesan strict_types declaration must be the very first statement in the script muncul saat kompilasi, sehingga echo di baris sebelumnya pun tidak sempat dieksekusi — tidak ada “Memulai program” pada output. Satu-satunya yang boleh mendahului declare adalah komentar dan baris kosong; PHPDoc block di atasnya tetap aman. Kebiasaan yang rapi: tulis <?php, langsung declare(strict_types=1);, baru sisanya.
Ringkasan #
declare(strict_types=1) mematikan koersi tipe pada seluruh pemanggilan yang berasal dari satu berkas — argumen maupun nilai kembalian, fungsi buatan sendiri maupun fungsi bawaan. Semantiknya melekat pada sisi pemanggil: fungsi yang sama bisa dipanggil longgar dan ketat dari dua berkas berbeda, dan declare wajib menempati statement pertama berkas. Dengan kontrak tipe yang kini kaku dua arah, tinggal satu wilayah yang belum kita petakan: di mana variabel fungsi hidup dan mengapa ia tidak terlihat dari luar — itulah bahasan Variable Scope pada Chapter berikutnya.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
operasi.php
Unduh berkas<?php
// operasi.php — definisi fungsi TANPA strict_types
function tambah(int $a, int $b): int
{
return $a + $b;
}