D
P
0

WordPress & PHP

Bug PHP 8: 'floatval' sebagai sanitize_callback Bikin Fatal Error di WordPress

12 Juni 2026·2 menit baca
Bug PHP 8: 'floatval' sebagai sanitize_callback Bikin Fatal Error di WordPress

Ini bug yang menjatuhkan seluruh pembuatan post di sebuah platform WordPress yang saya bangun, selama berjam-jam, dan penyebabnya cuma satu baris yang kelihatannya tidak bersalah:

register_post_meta( 'pc_property', '_harga', [
    'type'              => 'number',
    'single'            => true,
    'sanitize_callback' => 'floatval', // ← ini pemicunya
    'show_in_rest'      => true,
] );

Kelihatan wajar, kan? floatval untuk membersihkan input angka. Tapi di PHP 8, baris ini melempar fatal error setiap kali post disimpan:

floatval() expects exactly 1 argument, 4 given
in wp-includes/class-wp-hook.php on line 341

Yang bikin tambah pusing: php -l (lint) lolos tanpa keluhan, karena lint tidak mengeksekusi kode. Bug-nya baru muncul saat runtime, di tengah proses simpan.

Kenapa ini terjadi

WordPress menjalankan sanitize_callback lewat filter sanitize_{$object_type}_meta_{$meta_key}. Dan filter itu tidak hanya mengoper nilainya — ia mengoper empat argumen:

(value, meta_key, object_type, object_subtype)

Untuk fungsi PHP biasa (yang Anda tulis sendiri), ini tidak masalah: PHP diam-diam membuang argumen ekstra yang tidak dideklarasikan. Tapi fungsi internal PHP (yang ditulis di C — seperti floatval, intval, trim, sanitize_text_field bukan termasuk karena itu fungsi WP) menjadi ketat di PHP 8: kalau dideklarasikan menerima 1 argumen, mengoper 4 argumen langsung fatal.

Jadi floatval menerima (value, meta_key, object_type, object_subtype) = 4 argumen, padahal ia hanya mau 1 → ArgumentCountError. Dan karena ini terjadi di rantai filter saat menyimpan meta, semua penyimpanan post ikut tumbang.

Perbaikannya: bungkus dengan closure

Solusinya satu baris — bungkus fungsi internal itu dengan closure (fungsi user), yang dengan tenang membuang argumen ekstra:

register_post_meta( 'pc_property', '_harga', [
    'type'              => 'number',
    'single'            => true,
    'sanitize_callback' => fn( $value ) => (float) $value, // aman
    'show_in_rest'      => true,
] );

Closure fn($value) => (float) $value hanya mendeklarasikan satu parameter. WordPress tetap mengoper empat argumen, tapi karena ini fungsi user, PHP membuang tiga sisanya tanpa protes. Aman di PHP 8.

Aturan umum yang perlu diingat

Jangan pernah mengoper nama fungsi internal PHP secara langsung sebagai callback ke API WordPress yang mengoper banyak argumen. Yang berisiko antara lain:

  • floatval, intval, boolval, strval
  • trim, strtolower, strtoupper, htmlspecialchars (punya parameter opsional tapi bisa fatal tergantung versi)

Selalu bungkus dengan closure kalau Anda hanya mau mengoper nilainya:

'sanitize_callback' => fn( $v ) => (int) $v,        // bukan 'intval'
'sanitize_callback' => fn( $v ) => trim( (string) $v ), // bukan 'trim'

Fungsi WordPress sendiri (sanitize_text_field, absint, sanitize_email, dll.) aman karena ditulis untuk menerima/mengabaikan argumen ekstra — jadi itu boleh dipakai langsung.

Pelajaran

php -l hijau, kode "kelihatan benar", tapi satu nama fungsi internal sebagai callback meledakkan seluruh fitur di runtime PHP 8. Ini jebakan klasik saat migrasi ke PHP 8: C-land strict, user-land lunak. Kalau sebuah API WordPress mengoper lebih dari satu argumen ke callback Anda, bungkus fungsi internal apa pun dengan closure — dan uji dengan benar-benar menjalankan kode, bukan cuma lint.