Cegah Fatal Error! Ini 42 Fungsi PHP Lama yang Wajib Sobat Ganti Sebelum Upgrade ke PHP 8.5

Halo sobat, kembali lagi bersama saya Riyanto. Sebagai orang yang sudah ngulik PHP dan WordPress lebih dari 20 tahun—sejak zaman PHP 4 dan WordPress versi awal—saya sudah menyaksikan berbagai gelombang evolusi bahasa pemograman ini. Kalau sobat sudah lama menggunakan PHP, mungkin sampai saat ini masih ada project, aplikasi backend PHP, atau website klien yang berjalan di PHP 7.4. Memang sampai sekarang aplikasi tersebut masih bisa digunakan dan keliatannya adem-adem saja, tetapi menurut saya sekarang adalah waktu yang sanggat tepat untuk mulai melakukan migrasi ke PHP 8.5.

Pengalaman saya menangani migrasi belasan server Linux skala enterprise dan ratusan site WordPress menunjukkan bahwa menunda upgrade PHP itu ibarat menyimpan bom waktu. PHP 7.4 sudah resmi mencapai end-of-life (EOL) sejak November 2022. Artinya, tidak ada lagi patch keamanan resmi dari core PHP team. Ketika sobat tetap bertahan di PHP 7, aplikasi sobat tidak hanya rentan terhadap celah keamanan, tetapi juga kehilangan lompatan performa yang luar biasa drastis dari JIT (Just-In-Time) compiler, pemakaian memori yang jauh lebih efisien, serta fitur-fitur sintaks modern di PHP 8.0 hingga PHP 8.5 seperti Match Expression, Enums, Readonly Properties, Asymmetric Visibility, hingga Property Hooks.

Namun, kalau saya pribadi disuruh asal upgrade PHP di server produksi tanpa persiapan, jawaban saya: jangan buru-buru! Upgrade dari PHP 7.x langsung meloncat ke PHP 8.5 menyimpan banyak kejutan berupa breaking changes, fungsi yang deprecated (diperingatkan) lalu dihapus (removed), hingga perubahan fatal error handling. Banyak fungsi klasik yang dulu biasa kita tulis di PHP 5 atau PHP 7 kini sudah hilang tanpa bekas.

Di tutorial PHP dan panduan komprehensif ini, saya akan membedah secara mendalam seluruh daftar fungsi deprecated PHP, error yang sering muncul saat proses migrasi PHP, serta cara menggantinya dengan kode modern yang kompatibel hingga PHP 8.5. Panduan ini dirancang khusus untuk sobat yang berprofesi sebagai Programmer PHP, Developer WordPress, Administrator Linux, Backend Developer, maupun Mahasiswa Informatika.


Daftar Isi Panduan Migrasi PHP 7 ke PHP 8.5


Tabel Ringkasan Perubahan & Deprecated Function (PHP 7 ke PHP 8.5)

Sebelum kita masuk ke pembahasan teknis yang mendalam, berikut adalah tabel rujukan cepat yang saya buat berdasarkan dokumentasi resmi migration guide PHP net. Tabel ini memuat lebih dari 40 perubahan penting dari PHP 7 ke PHP 8.5.

  1. 1. each()
    Status di PHP 8.5: Dihapus (PHP 8.0)
    Solusi Modern: foreach() atau key()/current()
    Wajib Migrasi?: Ya (Fatal Error)
  2. 2. create_function()
    Status di PHP 8.5: Dihapus (PHP 8.0)
    Solusi Modern: Anonymous Functions (Closures) / Arrow Functions
    Wajib Migrasi?: Ya (Fatal Error)
  3. 3. mysql_* (mysql_connect dll)
    Status di PHP 8.5: Dihapus (PHP 7.0)
    Solusi Modern: PDO atau mysqli_*
    Wajib Migrasi?: Ya (Fatal Error)
  4. 4. ereg(), eregi()
    Status di PHP 8.5: Dihapus (PHP 7.0)
    Solusi Modern: preg_match() (PCRE)
    Wajib Migrasi?: Ya (Fatal Error)
  5. 5. split(), spliti()
    Status di PHP 8.5: Dihapus (PHP 7.0)
    Solusi Modern: explode() atau preg_split()
    Wajib Migrasi?: Ya (Fatal Error)
  6. 6. magic_quotes / get_magic_quotes_gpc()
    Status di PHP 8.5: Dihapus (PHP 8.0)
    Solusi Modern: Prepared Statements / Escaping Manual
    Wajib Migrasi?: Ya (Fatal Error)
  7. 7. money_format()
    Status di PHP 8.5: Dihapus (PHP 8.0)
    Solusi Modern: NumberFormatter::formatCurrency()
    Wajib Migrasi?: Ya (Fatal Error)
  8. 8. implode($arr, $glue)
    Status di PHP 8.5: Dihapus (PHP 8.0)
    Solusi Modern: implode($glue, $arr)
    Wajib Migrasi?: Ya (Fatal Error)
  9. 9. strstr($haystack, int)
    Status di PHP 8.5: Perubahan Behavior (PHP 8.0)
    Solusi Modern: Pass string strstr($h, (string)$n)
    Wajib Migrasi?: Ya (Logic Error)
  10. 10. count(null) / Non-Countable
    Status di PHP 8.5: TypeError (PHP 8.0)
    Solusi Modern: Cek is_array() / is_countable()
    Wajib Migrasi?: Ya (Fatal Error)
  11. 11. foreach(null)
    Status di PHP 8.5: TypeError / Warning
    Solusi Modern: foreach($arr ?? [] as $item)
    Wajib Migrasi?: Ya (Fatal Error)
  12. 12. trim(null), strlen(null)
    Status di PHP 8.5: Deprecated (8.1) / Error (8.5)
    Solusi Modern: Explicit string cast / Null coalescing $val ?? ''
    Wajib Migrasi?: Ya (Warning/Error)
  13. 13. strpos(), substr() dengan null
    Status di PHP 8.5: Deprecated / Error
    Solusi Modern: Gunakan string kosong atau ternary validation
    Wajib Migrasi?: Ya (Warning/Error)
  14. 14. array_key_exists(obj)
    Status di PHP 8.5: Dihapus (PHP 8.0)
    Solusi Modern: property_exists() atau cast array
    Wajib Migrasi?: Ya (Fatal Error)
  15. 15. __sleep() & __wakeup()
    Status di PHP 8.5: Deprecated (Dianjurkan diganti)
    Solusi Modern: __serialize() & __unserialize()
    Wajib Migrasi?: Sangat Dianjurkan
  16. 16. Backtick Operator (`)
    Status di PHP 8.5: Membutuhkan shell_exec aktif
    Solusi Modern: exec(), proc_open(), atau Symfony Process
    Wajib Migrasi?: Kondisional
  17. 17. Sintaks switch case ;
    Status di PHP 8.5: Deprecated / Parsing strict
    Solusi Modern: Gunakan titik dua case: atau match
    Wajib Migrasi?: Ya
  18. 18. Cast (unset) & (real)
    Status di PHP 8.5: Dihapus (PHP 8.0)
    Solusi Modern: $var = null; dan (float)
    Wajib Migrasi?: Ya (Fatal Error)
  19. 19. TypeError pada Internal Functions
    Status di PHP 8.5: Behavior Baru (PHP 8.0)
    Solusi Modern: Gunakan try-catch (\TypeError)
    Wajib Migrasi?: Ya
  20. 20. Null Handling (Passing null to scalar)
    Status di PHP 8.5: Strict Error di PHP 8.x
    Solusi Modern: Gunakan nullable type ?string / default value
    Wajib Migrasi?: Ya
  21. 21. Strict Typing (strict_types=1)
    Status di PHP 8.5: Lebih Ketat di PHP 8.x
    Solusi Modern: Type hint eksplisit & strict checking
    Wajib Migrasi?: Sangat Dianjurkan
  22. 22. Resource cURL ke Object
    Status di PHP 8.5: Object CurlHandle (8.0)
    Solusi Modern: Object otomatis terhapus (GC)
    Wajib Migrasi?: Penyesuaian Type Hint
  23. 23. Resource GD ke Object
    Status di PHP 8.5: Object GdImage (8.0)
    Solusi Modern: Object otomatis terhapus (GC)
    Wajib Migrasi?: Penyesuaian Type Hint
  24. 24. Resource Fileinfo ke Object
    Status di PHP 8.5: Object finfo (8.0)
    Solusi Modern: Object otomatis terhapus (GC)
    Wajib Migrasi?: Penyesuaian Type Hint
  25. 25. Dynamic Properties
    Status di PHP 8.5: Deprecated (8.2) / Error (9.0)
    Solusi Modern: Deklarasikan properti / #[AllowDynamicProperties]
    Wajib Migrasi?: Ya (Deprecated Notice)
  26. 26. String Increment ($str++ non-alphanumeric)
    Status di PHP 8.5: Deprecated (8.3) / Removed (8.4)
    Solusi Modern: str_increment()
    Wajib Migrasi?: Ya (Deprecated)
  27. 27. Sintaks list() versi lama
    Status di PHP 8.5: Sintaks Array Modern
    Solusi Modern: Short Array Destructuring [$a, $b]
    Wajib Migrasi?: Dianjurkan
  28. 28. FILTER_SANITIZE_STRING
    Status di PHP 8.5: Dihapus (PHP 8.1+)
    Solusi Modern: htmlspecialchars() / FILTER_SANITIZE_FULL_SPECIAL_CHARS
    Wajib Migrasi?: Ya (Fatal Error)
  29. 29. PDO Error Mode Default
    Status di PHP 8.5: PDO::ERRMODE_EXCEPTION
    Solusi Modern: try-catch (\PDOException)
    Wajib Migrasi?: Ya
  30. 30. MySQLi Error Reporting Default
    Status di PHP 8.5: Strict Exception Mode
    Solusi Modern: try-catch (\mysqli_sql_exception)
    Wajib Migrasi?: Ya
  31. 31. curl_close()
    Status di PHP 8.5: No-Op di PHP 8.0+
    Solusi Modern: Tidak wajib dipanggil lagi (auto GC)
    Wajib Migrasi?: Opsional (Cleanup)
  32. 32. imagedestroy()
    Status di PHP 8.5: No-Op di PHP 8.0+
    Solusi Modern: Tidak wajib dipanggil lagi (auto GC)
    Wajib Migrasi?: Opsional (Cleanup)
  33. 33. finfo_close()
    Status di PHP 8.5: No-Op di PHP 8.0+
    Solusi Modern: Tidak wajib dipanggil lagi (auto GC)
    Wajib Migrasi?: Opsional (Cleanup)
  34. 34. xml_parser_free()
    Status di PHP 8.5: No-Op di PHP 8.0+
    Solusi Modern: Tidak wajib dipanggil lagi (auto GC)
    Wajib Migrasi?: Opsional (Cleanup)
  35. 35. socket_set_timeout()
    Status di PHP 8.5: Dihapus / Alias lama
    Solusi Modern: socket_set_option() / stream_set_timeout()
    Wajib Migrasi?: Ya
  36. 36. Sintaks Offset Kurung Kurawal $str{0}
    Status di PHP 8.5: Dihapus (PHP 8.0)
    Solusi Modern: $str[0]
    Wajib Migrasi?: Ya (Fatal Error)
  37. 37. FILTER_DEFAULT pada Array
    Status di PHP 8.5: Perubahan Strictness
    Solusi Modern: Explicit Filter Flags
    Wajib Migrasi?: Kondisional
  38. 38. class_alias() internal class
    Status di PHP 8.5: Perubahan behavior (8.3+)
    Solusi Modern: Validasi klausa namespace
    Wajib Migrasi?: Dianjurkan
  39. 39. ord() & chr() parameter null
    Status di PHP 8.5: TypeError jika type mismatch
    Solusi Modern: Pastikan tipe data string/int valid
    Wajib Migrasi?: Ya
  40. 40. readdir(), closedir()
    Status di PHP 8.5: Object Directory handling
    Solusi Modern: Sintaks berbasis Object Directory
    Wajib Migrasi?: Dianjurkan
  41. 41. mb_check_encoding() tanpa param
    Status di PHP 8.5: Deprecated (8.1)
    Solusi Modern: Lewatkan argumen eksplisit
    Wajib Migrasi?: Ya
  42. 42. Nested Ternary tanpa Kurung
    Status di PHP 8.5: Fatal Error (PHP 8.0)
    Solusi Modern: Gunakan tanda kurung eksplisit atau match
    Wajib Migrasi?: Ya (Fatal Error)

Grup 1: Fungsi Lengkap yang Dihapus Total / Fatal Error

Pada grup pertama ini, kita akan membahas fungsi-fungsi legendaris yang dulu sangat populer di era PHP 5 dan PHP 7, namun di PHP 8.0 hingga PHP 8.5 sudah benar-benar dihapus dari mesin Zend Engine. Jika aplikasi sobat masih menyimpan fungsi ini, server Linux sobat akan langsung melempar Fatal Error: Uncaught Error: Call to undefined function.

1. Fungsi each()

1. Penjelasan: Fungsi each() digunakan untuk mengembalikan elemen array saat ini (berupa pasangan key dan value) dan memajukan pointer internal array tersebut.

2. Penyebab: Fungsi ini dinilai sangat lambat, memiliki efek samping memperlambat eksekusi array pointer global, serta memiliki keterbatasan pada penanganan perulangan kompleks.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$data = ['nama' => 'Riyanto', 'role' => 'Backend Developer'];
reset($data);
while (list($key, $val) = each($data)) {
    echo "$key: $val\n";
}

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$data = ['nama' => 'Riyanto', 'role' => 'Backend Developer'];
foreach ($data as $key => $val) {
    echo "$key: $val\n";
}

5. Kenapa harus diganti: Karena each() sudah dihapus total sejak PHP 8.0. Kode lama sobat tidak akan bisa berjalan sama sekali.

6. Dampaknya bila tidak diganti: Terjadi Fatal Error yang mengakibatkan seluruh halaman website atau endpoint API mati total (HTTP 500).

7. Tips migrasi: Ganti seluruh blok perulangan while(list() = each()) menggunakan foreach() standar. Sintaksnya jauh lebih bersih, aman, dan dieksekusi lebih cepat oleh JIT compiler.

8. Catatan kompatibilitas: Dideprekasi pada PHP 7.2 dan resmi dihapus pada PHP 8.0.

2. Fungsi create_function()

1. Penjelasan: Fungsi create_function() digunakan untuk membuat fungsi anonim secara dinamis dari string yang dievaluasi runtime.

2. Penyebab: Fungsi ini secara internal memanggil eval(). Hal ini sangat membahayakan keamanan aplikasi dari serangan Remote Code Execution (RCE) dan tidak bisa dioptimasi oleh OPcache.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$hitung = create_function('$a, $b', 'return $a + $b;');
echo $hitung(5, 10);

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
// Menggunakan Anonymous Function (Closure)
$hitung = function(int $a, int $b): int {
    return $a + $b;
};

// Atau menggunakan Arrow Function modern
$hitungArrow = fn(int $a, int $b): int => $a + $b;

echo $hitungArrow(5, 10);

5. Kenapa harus diganti: Menghilangkan potensi celah keamanan RCE fatal dan mengikuti standar penulisan Closure modern.

6. Dampaknya bila tidak diganti: Fatal Error: Call to undefined function create_function().

7. Tips migrasi: Cari kata kunci create_function pada project backend PHP sobat atau plugin WordPress tua, lalu ubah variabel penampung menjadi anonymous function atau arrow function.

8. Catatan kompatibilitas: Deprecated di PHP 7.2, dihapus di PHP 8.0.

3. Ekstensi mysql_* (mysql_connect, mysql_query, dll)

1. Penjelasan: Kumpulan fungsi procedural prosedural untuk menghubungkan PHP ke database MySQL.

2. Penyebab: Ekstensi ini sangat usang, tidak mendukung fitur modern MySQL (seperti Prepared Statements native, Transactions, async query), dan rentan SQL Injection.

3. Contoh Kode Lama (PHP 7 / PHP 5):

// PHP 7 / Kode Legacy
$link = mysql_connect('localhost', 'root', 'secret');
mysql_select_db('db_blog', $link);
$result = mysql_query("SELECT * FROM users WHERE id = " . $_GET['id']);
$row = mysql_fetch_assoc($result);

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5 (Menggunakan PDO)
$pdo = new PDO('mysql:host=localhost;dbname=db_blog;charset=utf8mb4', 'root', 'secret', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);

$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute(['id' => (int)$_GET['id']]);
$row = $stmt->fetch();

5. Kenapa harus diganti: PDO menyediakan lapisan abstraksi database yang aman dari serangan SQL Injection dengan fitur prepared statement.

6. Dampaknya bila tidak diganti: Website tidak bisa terhubung ke database dan memunculkan error fatal.

7. Tips migrasi: Saya sarankan refactoring total layer database sobat ke PDO. Jika terbiasa dengan gaya procedural, sobat bisa menggunakan ekstensi mysqli_*.

8. Catatan kompatibilitas: Dideprekasi di PHP 5.5, dihapus penuh di PHP 7.0. Di PHP 8.5 sudah tidak ada jejaknya sama sekali.

4. Fungsi POSIX Regex (ereg(), eregi(), split(), spliti())

1. Penjelasan: Fungsi pencarian dan pemisahan string berbasis regex versi POSIX lama.

2. Penyebab: Library POSIX regex kalah jauh dari segi kecepatan dan fleksibilitas dibanding pustaka PCRE (Perl Compatible Regular Expressions).

3. Contoh Kode Lama (PHP 7):

// PHP 7 / Legacy
if (ereg("^[0-9]+$", $input)) {
    $parts = split("-", $input);
}

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
if (preg_match('/^[0-9]+$/', $input)) {
    $parts = explode('-', $input); // Gunakan explode jika pemisah berupa string tetap
    // Atau preg_split('/-/', $input); jika pemisah berupa regex
}

5. Kenapa harus diganti: PCRE jauh lebih cepat, hemat memori, dan mendukung Unicode modern.

6. Dampaknya bila tidak diganti: Eksekusi terhenti dengan error Call to undefined function ereg().

7. Tips migrasi: Tambahkan delimiter (seperti /) di awal dan akhir pola regex saat mengganti ereg menjadi preg_match.

8. Catatan kompatibilitas: Deprecated di PHP 5.3, dihapus sejak PHP 7.0.

5. Feature magic_quotes & Fungsi get_magic_quotes_gpc()

1. Penjelasan: Fitur lama PHP yang secara otomatis melakukan escaping karakter backslash pada input GPC (GET/POST/COOKIE).

2. Penyebab: Menimbulkan ilusi keamanan palsu, merusak format data asli, dan memperlambat pemrosesan string.

3. Contoh Kode Lama (PHP 7):

// PHP 7
if (get_magic_quotes_gpc()) {
    $data = stripslashes($_POST['username']);
} else {
    $data = $_POST['username'];
}

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
// Cukup ambil data secara langsung dari superglobal
$data = trim($_POST['username'] ?? '');
// Keamanan query diserahkan ke Prepared Statement PDO/MySQLi

5. Kenapa harus diganti: Karena sanitasi otomatis dari server sudah dianggap sebagai kebiasaan buruk (antipattern) dalam arsitektur software modern.

6. Dampaknya bila tidak diganti: Mengakibatkan error fatal karena fungsi get_magic_quotes_gpc() tidak lagi ditemukan.

7. Tips migrasi: Hapus semua pemeriksaan blok if(get_magic_quotes_gpc()) pada file bootstrapping aplikasi sobat.

8. Catatan kompatibilitas: Dihapus penuh pada PHP 8.0.

6. Fungsi money_format()

1. Penjelasan: Fungsi untuk mengformat angka menjadi string mata uang.

2. Penyebab: Fungsi ini bergantung pada fungsi C-library sistem operasi strfmon() yang tidak tersedia di platform Windows, sehingga membingungkan untuk aplikasi lintas platform.

3. Contoh Kode Lama (PHP 7):

// PHP 7
setlocale(LC_MONETARY, 'id_ID');
echo money_format('%=*^-14#5.2i', 1250000);

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$fmt = new NumberFormatter('id_ID', NumberFormatter::CURRENCY);
echo $fmt->formatCurrency(1250000, 'IDR');

5. Kenapa harus diganti: Menggunakan ekstensi intl berbasis ICU standar internasional yang konsisten di Linux, Windows, maupun macOS.

6. Dampaknya bila tidak diganti: Fatal Error: Call to undefined function money_format().

7. Tips migrasi: Pastikan ekstensi php-intl sudah terinstall dan aktif di server Linux sobat (sudo apt install php8.5-intl).

8. Catatan kompatibilitas: Dideprekasi di PHP 7.4, dihapus penuh di PHP 8.0.

7. Sintaks Access Offset Menggunakan Kurung Kurawal ($var{0})

1. Penjelasan: Mengakses indeks elemen array atau karakter string menggunakan kurung kurawal.

2. Penyebab: Bentuk sintaks ini membingungkan parser parser PHP karena sangat mirip dengan pemanggilan blok fungsi atau initializer object.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$str = "Riyanto";
$firstChar = $str{0};

$arr = [10, 20, 30];
$firstElem = $arr{0};

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$str = "Riyanto";
$firstChar = $str[0];

$arr = [10, 20, 30];
$firstElem = $arr[0];

5. Kenapa harus diganti: Mengembalikan konsistensi pengaksesan elemen menggunakan kurung siku [].

6. Dampaknya bila tidak diganti: Fatal Error: Array and string offset access syntax with curly braces is no longer supported.

7. Tips migrasi: Lakukan pencarian global (Find and Replace) dengan RegEx di IDE sobat untuk mendeteksi variabel yang diakhiri kurung kurawal.

8. Catatan kompatibilitas: Deprecated PHP 7.4, Fatal Error di PHP 8.0+.

8. Cast Type (unset) dan (real)

1. Penjelasan: Pengubahan tipe data secara eksplisit menggunakan sintaks cast (unset) untuk mengembalikan null dan (real) untuk konversi float.

2. Penyebab: Cast (unset) sangat membingungkan karena tidak benar-benar menghapus variabel seperti unset(), melainkan hanya mengembalikan nilai null. Sedangkan (real) hanyalah alias dari (float).

3. Contoh Kode Lama (PHP 7):

// PHP 7
$val = (unset) $data;
$harga = (real) "15000.50";

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$val = null;
$harga = (float) "15000.50";

5. Kenapa harus diganti: Menghilangkan sintaks mubazir yang memperlambat pemahaman alur program.

6. Dampaknya bila tidak diganti: Parse Error / Parse Fatal Syntax Error di PHP 8.0 ke atas.

7. Tips migrasi: Ganti seluruh instruksi (unset) dengan penugasan variabel $var = null; secara eksplisit.

8. Catatan kompatibilitas: Deprecated di 7.2, dihapus di PHP 8.0.


Grup 2: Perubahan Parameter & Behavior Fungsi String / Array

Di grup kedua ini, fokus kita adalah perubahan logika pada fungsi bawaan (built-in functions) yang berhubungan dengan string dan array. Beberapa fungsi tidak dihapus, namun urutan parameternya diubah, atau perilakunya menjadi lebih ketat terhadap tipe data null.

9. Urutan Parameter Fungsi implode()

1. Penjelasan: Fungsi untuk menggabungkan elemen array menjadi sebuah string bertautan.

2. Penyebab: Pada versi PHP kuno, implode() mengizinkan urutan parameter secara terbalik (array dulu baru separator string). Hal ini inkonsisten dengan fungsi string PHP lainnya seperti explode().

3. Contoh Kode Lama (PHP 7):

// PHP 7 (Urutan Terbalik)
$arr = ['PHP', 'Python', 'Go'];
$result = implode($arr, ', '); // Array dulu, baru glue

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$arr = ['PHP', 'Python', 'Go'];
$result = implode(', ', $arr); // Glue string dulu, baru array

5. Kenapa harus diganti: Menjaga konsistensi parameter fungsi internal PHP (Separator selalu di depan).

6. Dampaknya bila tidak diganti: Di PHP 8.0+, melempar TypeError: implode(): Argument #1 ($separator) must be of type string, array given.

7. Tips migrasi: Pastikan argumen pertama selalu berupa string pemisah.

8. Catatan kompatibilitas: Deprecated di PHP 7.4, Fatal Error di PHP 8.0+.

10. Non-String Needle pada strstr() dan stristr()

1. Penjelasan: Mencari kemunculan pertama suatu string (needle) di dalam string utama (haystack).

2. Penyebab: Dulu jika memasukkan nilai integer sebagai needle, PHP akan menganggapnya sebagai nilai ASCII ordinal dari karakter. Perilaku ini membingungkan dan sering memicu bug tersembunyi.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$email = 'riyan.dev@gmail.com';
// Angka 64 adalah ASCII dari '@'
$domain = strstr($email, 64);

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$email = 'riyan.dev@gmail.com';
// Needle wajib berupa string secara eksplisit
$domain = strstr($email, '@'); 
// Jika memiliki angka int, cast ke string dulu: strstr($haystack, (string)$number);

5. Kenapa harus diganti: Menghindari interpretasi ganda tipe data integer dalam pengolahan teks.

6. Dampaknya bila tidak diganti: Di PHP 8.0+, integer akan dikonversi langsung menjadi string angka (misal 64 menjadi "64") alih-alih karakter ASCII, yang menyebabkan pencarian gagal/salah hasil.

7. Tips migrasi: Selalu gunakan karakter string eksplisit atau bungkus argumen dengan chr() jika memang berniat mencari berdasarkan ASCII code.

8. Catatan kompatibilitas: Deprecated di PHP 7.3, berubah behavior penuh di PHP 8.0.

11. Fungsi count() pada Nilai null atau Non-Countable

1. Penjelasan: Menghitung jumlah elemen di dalam array atau objek yang mengimplementasikan interface Countable.

2. Penyebab: Di PHP 7.0 ke bawah, memanggil count(null) atau count("string") mengembalikan angka 0 atau 1 tanpa peringatan. Ini menyembunyikan bug arsitektur aplikasi.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$data = null;
echo count($data); // Mengembalikan 0 dengan Warning di 7.2

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$data = null;

// Cara 1: Menggunakan Null Coalescing dengan Array Kosong
echo count($data ?? []);

// Cara 2: Validasi dengan is_countable()
if (is_countable($data)) {
    echo count($data);
} else {
    echo 0;
}

5. Kenapa harus diganti: Memastikan objek yang dihitung benar-benar berstruktur koleksi/array.

6. Dampaknya bila tidak diganti: Melempar TypeError: count(): Argument #1 ($value) must be of type Countable|array, null given di PHP 8.0+.

7. Tips migrasi: Saya sarankan membungkus variabel opsional dengan $data ?? [] di dalam fungsi count().

8. Catatan kompatibilitas: Deprecated Warning di PHP 7.2, TypeError di PHP 8.0.

12. Perulangan foreach() pada Tipe Data null

1. Penjelasan: Melakukan iterasi terhadap variabel yang bernilai null atau bukan array/object.

2. Penyebab: Mencegah error diam-diam ketika variabel data yang diekspektasi sebagai array dari database ternyata bernilai null.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$users = get_users_from_db(); // Mengembalikan null jika kosong
foreach ($users as $user) {
    echo $user->name;
}

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$users = get_users_from_db() ?? []; // Pastikan fallback berupa array
foreach ($users as $user) {
    echo $user->name;
}

5. Kenapa harus diganti: Menjamin tipe data iterable secara konsisten sebelum memasuki rantai perulangan.

6. Dampaknya bila tidak diganti: Melempar Warning: Warning: Processing null in foreach atau TypeError tergantung pada konfigurasi error level.

7. Tips migrasi: Selalu sediakan fallback array kosong ?? [] pada ekspresi foreach.

8. Catatan kompatibilitas: Diperketat di PHP 8.0 ke atas.

13. Passing Nilai null ke Fungsi String Internal (trim, strlen, strpos, substr)

1. Penjelasan: Mempassing parameter null ke fungsi-fungsi manipulasi string skalar internal PHP.

2. Penyebab: Di PHP 7, null secara otomatis di-coerce (dikonversi paksa) menjadi string kosong "". Hal ini tidak selaras dengan sistem tipe data PHP 8 yang ketat.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$input = null;
$clean = trim($input); // Otomatis mengembalikan ""
$len = strlen($input); // Otomatis mengembalikan 0

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$input = null;

// Lakukan cast string eksplisit atau beri default value string kosong
$clean = trim($input ?? '');
$len = strlen($input ?? '');

5. Kenapa harus diganti: Mencegah kesalahan implisit type coercion dan menjaga kompatibilitas penuh dengan PHP 8.1 hingga 8.5.

6. Dampaknya bila tidak diganti: Melempar Deprecated: Passing null to parameter #1 ($string) of type string is deprecated di PHP 8.1, dan menjadi TypeError di versi PHP selanjutnya.

7. Tips migrasi: Cari semua pemanggilan trim, strlen, substr pada codebase backend PHP sobat dan tambahkan operator ?? ''.

8. Catatan kompatibilitas: Deprecated di PHP 8.1, TypeError di PHP 8.5+ jika mode strict aktif.

14. Penggunaan array_key_exists() pada Tipe Data Object

1. Penjelasan: Memeriksa keberadaan suatu key/properti di dalam variabel bertipe object.

2. Penyebab: array_key_exists() dirancang khusus untuk array. Memeriksa properti objek menggunakan fungsi array memicu kebingungan semantic.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$userObj = new stdClass();
$userObj->nama = 'Riyanto';

if (array_key_exists('nama', $userObj)) {
    echo "Ada properti nama";
}

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$userObj = new stdClass();
$userObj->nama = 'Riyanto';

// Gunakan property_exists untuk Object
if (property_exists($userObj, 'nama')) {
    echo "Ada properti nama";
}

5. Kenapa harus diganti: Pemisahan fungsionalitas yang tegas antara pemeriksaan array dan struktur properti objek.

6. Dampaknya bila tidak diganti: TypeError: array_key_exists(): Argument #2 ($array) must be of type array, stdClass given di PHP 8.0+.

7. Tips migrasi: Ganti seluruh array_key_exists() yang menargetkan object menjadi property_exists().

8. Catatan kompatibilitas: Deprecated di PHP 7.4, TypeError di PHP 8.0.

15. Perubahan Behavior String Increment ($str++) dan str_increment()

1. Penjelasan: Melakukan operasi increment (penambahan) pada variabel bertipe string.

2. Penyebab: Menggunakan operator increment ++ pada string non-alfanumerik atau string kosong menimbulkan perilaku misterius dan tidak dapat diprediksi.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$code = 'Z89';
$code++; // Menjadi 'Z90'

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
// Menggunakan fungsi bawaan baru str_increment() dari PHP 8.3+
$code = 'Z89';
$nextCode = str_increment($code); // Menjadi 'Z90'

5. Kenapa harus diganti: Fungsi str_increment() dan str_decrement() menjamin operasi string increment bekerja aman secara matematis tanpa efek samping.

6. Dampaknya bila tidak diganti: Menggunakan $str++ pada string non-alfanumerik memicu Deprecated Notice di PHP 8.3 dan Fatal Error di PHP 8.4+.

7. Tips migrasi: Manfaatkan fungsi baru str_increment() saat membuat kode generator invoice atau nomor seri otomatis.

8. Catatan kompatibilitas: Deprecated di PHP 8.3, Fungsi resmi diperkenalkan di PHP 8.3 & PHP 8.4.

16. Perilaku Strict pada Fungsi ord() dan chr()

1. Penjelasan: Konversi antara karakter string dan nilai byte ASCII ordinalnya.

2. Penyebab: Dulu mempassing tipe data yang tidak sesuai (seperti array atau null) akan dikonversi diam-diam dengan warning ringan. Di PHP 8.5, validasi tipe data bersifat eksplisit.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$ascii = ord(null); // Mengembalikan 0 dengan peringatan

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$char = 'A';
$ascii = ord($char); // Selalu pastikan parameter bertipe string

$code = 65;
$symbol = chr($code); // Selalu pastikan parameter bertipe int

5. Kenapa harus diganti: Menjaga kepastian tipe data byte stream saat manipulasi biner.

6. Dampaknya bila tidak diganti: Melempar TypeError jika dikirim tipe data selain string/int yang diharapkan.

7. Tips migrasi: Lakukan sanitasi tipe data sebelum memanggil ord() atau chr().

8. Catatan kompatibilitas: Diperketat sejak PHP 8.0.

17. Perubahan Perilaku pada class_alias()

1. Penjelasan: Membuat alias (nama bentukan lain) untuk suatu class PHP.

2. Penyebab: Di PHP 8.3+, class_alias() sekarang mendukung pembuatan alias untuk internal class PHP dan interface, namun penanganan error-nya diperketat jika class sumber belum ter-load.

3. Contoh Kode Lama (PHP 7):

// PHP 7
class_alias('App\Services\OldLogger', 'App\Logger');

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
// Selalu pastikan parameter ketiga $autoload diset true secara aman
if (class_exists('App\Services\OldLogger', true)) {
    class_alias('App\Services\OldLogger', 'App\Logger', true);
}

5. Kenapa harus diganti: Mencegah kegagalan pengikatan alias saat autoloader Composer berpacu secara async.

6. Dampaknya bila tidak diganti: Melempar ValueError jika nama class asal bernivalid atau berisi karakter terlarang.

7. Tips migrasi: Bungkus pemanggilan class_alias() dengan pengecekan class_exists() terlebih dahulu.

8. Catatan kompatibilitas: Diperbarui pada PHP 8.3.

18. Manajemen Directory Handle (readdir(), rewinddir(), closedir())

1. Penjelasan: Mengiterasi dan membaca isi folder direktori di server Linux.

2. Penyebab: Resource direktori lawas kini telah dimigrasi menjadi instance object Directory bawaan PHP 8.0.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$handle = opendir('/var/www/html');
while (false !== ($entry = readdir($handle))) {
    echo "$entry\n";
}
closedir($handle);

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5 (Menggunakan Directory Object atau DirectoryIterator Modern)
$dir = dir('/var/www/html');
while (false !== ($entry = $dir->read())) {
    echo "$entry\n";
}
$dir->close();

5. Kenapa harus diganti: Gaya pemrograman Berbasis Objek (OOP) jauh lebih mudah dibaca dan aman dalam manajemen resource memori.

6. Dampaknya bila tidak diganti: Meskipun fungsi lama masih berfungsi sebagai alias, pemanggilan closedir() sudah menjadi no-op karena garbage collector menangani pembersihan objek secara otomatis.

7. Tips migrasi: Gunakan class modern DirectoryIterator atau FilesystemIterator dari standar SPL PHP.

8. Catatan kompatibilitas: Resource diubah ke Object pada PHP 8.0.


Grup 3: Perubahan Orientasi Objek, Dynamic Properties, dan Resource ke Object

Salah satu transformasi terbesar dari PHP 7 ke PHP 8.5 terjadi di ranah Object-Oriented Programming (OOP) dan perombakan arsitektur resource internal mesin Zend. Sobat developer WordPress dan backend PHP wajib menyimak bagian ini dengan cermat!

19. Magic Methods: Depresi __sleep() & __wakeup() Diganti __serialize() & __unserialize()

1. Penjelasan: Magic method yang dipanggil saat objek di-serialize menjadi string atau di-unserialize kembali menjadi objek.

2. Penyebab: __sleep() hanya bisa mengembalikan daftar nama variabel (string) dan tidak bisa memanipulasi struktur data secara fleksibel. Selain itu, __wakeup() sering dieksploitasi dalam serangan Deserialization Vulnerability.

3. Contoh Kode Lama (PHP 7):

// PHP 7
class UserSession {
    public $db;
    public $username;

    public function __sleep() {
        return ['username']; // Hanya mengembalikan nama atribut
    }

    public function __wakeup() {
        $this->connectDb();
    }
}

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
class UserSession {
    public string $username;

    public function __serialize(): array {
        // Mengembalikan Key-Value pair array secara langsung
        return [
            'username' => $this->username,
            'timestamp' => time()
        ];
    }

    public function __unserialize(array $data): void {
        $this->username = $data['username'];
    }
}

5. Kenapa harus diganti: Memberikan kontrol mutlak terhadap struktur array hasil serialisasi data tanpa trik magic property.

6. Dampaknya bila tidak diganti: Jika kedua pasangan method ditulis bersamaan, PHP 8.x akan memprioritaskan __serialize() dan mengabaikan __sleep() sepenuhnya.

7. Tips migrasi: Ganti seluruh fungsi __sleep dan __wakeup di model/entity aplikasi sobat menjadi __serialize dan __unserialize.

8. Catatan kompatibilitas: Diperkenalkan di PHP 7.4, diprioritaskan penuh di PHP 8.0+.

20. Depresi Dynamic Properties (Properti Dinamis Tanpa Deklarasi Class)

1. Penjelasan: Menetapkan nilai pada properti objek yang belum pernah dideklarasikan di dalam definisi class.

2. Penyebab: Dynamic properties sering menjadi sumber bug fatal akibat salah mengetik nama properti (typo), serta mencegah optimasi struktur kelas oleh JIT compiler.

3. Contoh Kode Lama (PHP 7):

// PHP 7
class User {
    public string $nama;
}

$u = new User();
$u->namatypo = 'Riyanto'; // Properti dibuat secara melayang/dinamis

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
// Opsi 1: Deklarasikan properti secara eksplisit (SANGAT DIANJURKAN)
class User {
    public string $nama;
    public ?string $namatypo = null;
}

// Opsi 2: Gunakan Attribute #[AllowDynamicProperties] jika sangat terpaksa
#[AllowDynamicProperties]
class LegacyUser {
    public string $nama;
}

5. Kenapa harus diganti: Menjaga integritas kode, type safety, dan performa eksekusi memori.

6. Dampaknya bila tidak diganti: Melempar Deprecated Notice: Creation of dynamic property User::$namatypo is deprecated di PHP 8.2, dan menjadi Fatal Error di PHP 9.0.

7. Tips migrasi: Untuk class DTO atau data container lama di WordPress, gunakan class bawaan stdClass yang masih mengecualikan aturan ini secara native.

8. Catatan kompatibilitas: Deprecated di PHP 8.2, Fatal Error di PHP 9.0.

21. Migrasi Resource Menjadi Object Instance (cURL, GD, Fileinfo, XMLParser, Sockets)

1. Penjelasan: Tipe data internal PHP yang dulunya berwujud resource khusus (seperti curl_init() atau imagecreatetruecolor()) kini dikonversi menjadi instance class Objek resmi (seperti CurlHandle, GdImage, finfo, Socket).

2. Penyebab: Tipe data resource adalah peninggalan arsitektur PHP lama yang susah diintegrasikan dengan sistem Type Hinting OOP PHP 8.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$ch = curl_init('https://api.github.com');
if (is_resource($ch)) { // Mengecek apakah tipe data berupa resource
    curl_exec($ch);
}

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$ch = curl_init('https://api.github.com');
if ($ch instanceof \CurlHandle) { // Mengecek instance Object
    curl_exec($ch);
}

5. Kenapa harus diganti: Memungkinkan penulisan Type Hinting yang presisi pada parameter method: function processCurl(\CurlHandle $ch).

6. Dampaknya bila tidak diganti: Fungsi lama seperti is_resource($ch) akan selalu mengembalikan nilai false karena $ch sekarang adalah sebuah Objek!

7. Tips migrasi: Ganti seluruh fungsi pengecekan is_resource() pada cURL dan GD Image menjadi instanceof atau cek is_object().

8. Catatan kompatibilitas: Diubah bertahap dari PHP 8.0 hingga PHP 8.4.

22. Fungsi Closing Resource yang Menjadi No-Op (curl_close, imagedestroy, finfo_close, xml_parser_free)

1. Penjelasan: Fungsi-fungsi yang dulunya digunakan untuk menutup koneksi atau membebaskan alokasi memori resource.

2. Penyebab: Karena resource kini telah berubah menjadi Objek resmi, mesin Garbage Collector (GC) PHP secara otomatis akan menghapus objek dari RAM saat objek tersebut keluar dari scope (didestruksi).

3. Contoh Kode Lama (PHP 7):

// PHP 7
$img = imagecreatetruecolor(100, 100);
// Process image...
imagedestroy($img); // Wajib dipanggil manual untuk cegah leak memori

$ch = curl_init('https://example.com');
curl_exec($ch);
curl_close($ch);

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$img = imagecreatetruecolor(100, 100);
// Process image...
// imagedestroy($img) tidak wajib dipanggil lagi (No-Op)

$ch = curl_init('https://example.com');
curl_exec($ch);
// curl_close($ch) tidak wajib dipanggil lagi. Objek $ch otomatis dihancurkan oleh GC
unset($ch); // Jika ingin membebaskan memori secara instan

5. Kenapa harus diganti: Menyederhanakan penulisan kode tanpa rasa takut terjadi memory leak.

6. Dampaknya bila tidak diganti: Pemanggilan curl_close() atau imagedestroy() di PHP 8.x tidak akan menyebabkan error, namun fungsi tersebut bersifat tidak melakukan apa-apa (No-Operation).

7. Tips migrasi: Sobat bisa membiarkannya atau membersihkannya secara bertahap saat refactoring kode.

8. Catatan kompatibilitas: Menjadi No-Op sejak PHP 8.0.


Grup 4: Perubahan Sintaks, Operator, Cast, dan Type System

PHP 8 menghadirkan perombakan total pada sistem fondasi pemrosesan sintaks dan tipe data. Pembatasan tipe data yang lebih strict akan memaksa kita menulis kode backend PHP yang jauh lebih bersih dan bebas bug tersembunyi.

23. Backtick Operator (`command`) & Ketergantungan shell_exec()

1. Penjelasan: Menjalankan perintah terminal server Linux dengan mengapit string di antara dua tanda backtick.

2. Penyebab: Backtick operator secara internal memanggil fungsi shell_exec(). Jika fungsi shell_exec() dimatikan pada file php.ini server Linux (melalui directive disable_functions), penggunaan backtick akan langsung memicu error fatal.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$output = `ls -la /var/www/html`;
echo "
$output

“;

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
// Sangat disarankan menggunakan proc_open atau Library Process
use Symfony\Component\Process\Process;

$process = new Process(['ls', '-la', '/var/www/html']);
$process->run();

if ($process->isSuccessful()) {
    echo "
" . $process->getOutput() . "

“;
}

5. Kenapa harus diganti: Menghindari eksekusi shell liar yang rentan terhadap serangan Command Injection.

6. Dampaknya bila tidak diganti: Melempar Error: Call to disabled function shell_exec() jika server Linux di-hardening.

7. Tips migrasi: Hindari pemanggilan terminal langsung di skrip PHP. Jika terpaksa, gunakan library eksternal yang melakukan sanitasi argumen shell secara ketat.

8. Catatan kompatibilitas: Diperketat pada PHP 8.0 ke atas.

24. Sintaks switch case Menggunakan Titik Koma (case 1;) & Migrasi ke match

1. Penjelasan: Penulisan pembatas kondisi pada struktur switch menggunakan titik koma ; alih-alih titik dua :.

2. Penyebab: Sintaks case 1; adalah anomalitas parser PHP kuno yang ambigu dan rawan kesalahan pengetikan.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$status = 1;
switch ($status) {
    case 1; // Menggunakan titik koma
        $msg = 'Aktif';
        break;
    case 2;
        $msg = 'Nonaktif';
        break;
}

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5 (Menggunakan Expression Match Modern PHP 8)
$status = 1;

$msg = match($status) {
    1 => 'Aktif',
    2 => 'Nonaktif',
    default => 'Status Tidak Dikenal',
};

5. Kenapa harus diganti: Expression match mengembalikan nilai secara langsung, melakukan pengecekan tipe data secara ketat (===), serta tidak membutuhkan instruksi break.

6. Dampaknya bila tidak diganti: Sintaks titik koma pada switch case memicu peringatan deprecation/parse error pada parser PHP 8.5.

7. Tips migrasi: Ganti seluruh struktur switch-case sederhana di project sobat menggunakan ekspresi match.

8. Catatan kompatibilitas: Match Expression resmi hadir di PHP 8.0.

25. Pengetatan Cast Tipe Data (boolean), (integer), (double), (binary)

1. Penjelasan: Pengubahan tipe data skalar secara langsung menggunakan tanda kurung.

2. Penyebab: Penggunaan nama alias seperti (double) atau (binary) membingungkan karena nama tipe data resmi di PHP adalah float dan string.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$a = (boolean) $isAvailable;
$b = (integer) $count;
$c = (double) $price;
$d = (binary) $data;

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$a = (bool) $isAvailable;
$b = (int) $count;
$c = (float) $price;
$d = (string) $data; // Cast biner disarankan menggunakan string atau b2hex

5. Kenapa harus diganti: Menyesuaikan dengan nama kanonis tipe data skalar pada PHP modern.

6. Dampaknya bila tidak diganti: Alias lama akan dideprekasi bertahap pada rilis PHP mendatang.

7. Tips migrasi: Gunakan format cast pendek: (bool), (int), (float), (string).

8. Catatan kompatibilitas: Diresmikan penyeragamannya sejak PHP 8.0.

26. Transformasi Warning Menjadi Exception TypeError dan ValueError

1. Penjelasan: Fungsi internal PHP 8 sekarang melemparkan Exception \TypeError atau \ValueError saat diberikan argumen dengan tipe atau nilai yang tidak valid, alih-alih hanya mengeluarkan Warning ringan dan mengembalikan nilai false.

2. Penyebab: Warning ringan sering kali terabaikan di log server, sehingga aplikasi terus berjalan dalam kondisi State yang rusak.

3. Contoh Kode Lama (PHP 7):

// PHP 7
// Mengirimkan nilai minus ke array_chunk hanya mengeluarkan Warning
$chunks = array_chunk(['A', 'B'], -1); 
// $chunks bernilai null/false, skrip tetap berjalan!

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
try {
    $chunks = array_chunk(['A', 'B'], -1);
} catch (\ValueError $e) {
    echo "Error nilai argumen: " . $e->getMessage();
} catch (\TypeError $e) {
    echo "Error tipe data: " . $e->getMessage();
}

5. Kenapa harus diganti: Menjamin bahwa setiap kegagalan argumen tertangkap oleh arsitektur penanganan exception (Error Handling).

6. Dampaknya bila tidak diganti: Jika tidak ditangkap dengan blok try-catch, aplikasi akan langsung Fatal Error Uncaught ValueError.

7. Tips migrasi: Bungkus pemanggilan fungsi internal yang berisiko dengan block try-catch (\Throwable $e).

8. Catatan kompatibilitas: Perubahan besar ini diberlakukan penuh sejak PHP 8.0.

27. Operator Nullsafe (?->) dan Handling Null Coalescing (??)

1. Penjelasan: Mengakses properti atau method dari objek yang berpotensi bernilai null tanpa harus melakukan pengujian if ($obj !== null) bertingkat.

2. Penyebab: Memangkas boilerplate code penanganan null yang sangat panjang di PHP 7.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$country = null;
if ($user !== null) {
    $profile = $user->getProfile();
    if ($profile !== null) {
        $address = $profile->getAddress();
        if ($address !== null) {
            $country = $address->country;
        }
    }
}

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
// Rantai diputus secara otomatis jika salah satu bernilai null
$country = $user?->getProfile()?->getAddress()?->country;

5. Kenapa harus diganti: Menjadikan kode backend PHP sobat jauh lebih elegan, mudah dibaca, dan bebas dari error Attempt to read property on null.

6. Dampaknya bila tidak diganti: Kode lama tetap berjalan, tetapi sobat melewatkan kesempatan emas untuk menyederhanakan ratusan baris kode rimbun.

7. Tips migrasi: Refactor seluruh pengujian kondisi objek bertingkat menggunakan operator ?->.

8. Catatan kompatibilitas: Nullsafe Operator resmi diperkenalkan pada PHP 8.0.

28. Strict Typing (declare(strict_types=1);) dan Modern Type System

1. Penjelasan: Mengaktifkan moda pemeriksaan tipe data super ketat pada file PHP.

2. Penyebab: PHP 8 mendukung Union Types (int|string), Intersection Types (Countable&ArrayAccess), DNF Types ((HasTitle&HasAuthor)|Null), dan Typed Class Constants di PHP 8.3.

3. Contoh Kode Lama (PHP 7):

// PHP 7
class Product {
    /** @var int|float */
    private $price;

    public function setPrice($price) {
        $this->price = $price;
    }
}

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
declare(strict_types=1);

class Product {
    // Union Type pada Property
    private int|float $price;

    public function setPrice(int|float $price): void {
        $this->price = $price;
    }

    public function getPrice(): int|float {
        return $this->price;
    }
}

5. Kenapa harus diganti: Dokumentasi PHPDoc @var di atas variabel kini bisa dipindahkan langsung ke engine PHP secara native.

6. Dampaknya bila tidak diganti: Tidak ada error jika tidak diaktifkan, namun aplikasi sobat kehilangan fitur Type Safety komprehensif.

7. Tips migrasi: Tambahkan dekalarasi declare(strict_types=1); di baris pertama seluruh file kelas utama aplikasi sobat.

8. Catatan kompatibilitas: Terus disempurnakan dari PHP 8.0 hingga PHP 8.5.

29. Destructuring Array Sintaks Pendek ([] vs list())

1. Penjelasan: Memecah elemen array ke dalam beberapa variabel terpisah.

2. Penyebab: Sintaks list() terkesan seperti pemanggilan fungsi bawaan, padahal merupakan konstruksi bahasa. Sintaks siku [] jauh lebih ringkas.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$data = ['Riyanto', 'Purwokerto', 'Backend Developer'];
list($nama, $kota, $role) = $data;

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$data = ['Riyanto', 'Purwokerto', 'Backend Developer'];
// Short Array Destructuring dengan Key Matching
[$nama, $kota, $role] = $data;

$user = ['id' => 101, 'username' => 'riyan85'];
['username' => $userName, 'id' => $userId] = $user;

5. Kenapa harus diganti: Sintaks siku [] mendukung destructuring berdasarkan key array assosiatif secara langsung.

6. Dampaknya bila tidak diganti: Sintaks list() masih didukung untuk kebelakang, tetapi dinilai usang oleh komunitas PHP modern.

7. Tips migrasi: Gunakan destructuring [$a, $b] = $arr saat mengambil data dari hasil query database.

8. Catatan kompatibilitas: Diperkenalkan sejak PHP 7.1 dan menjadi standar di PHP 8.x.


Grup 5: Perubahan Filter, Database (PDO & MySQLi), dan Ekstensi

Perubahan pada ekstensi pemrosesan data seperti Filter, PDO, dan MySQLi sangat krusial bagi aplikasi web yang sering berinteraksi dengan form input user dan database server Linux.

30. Perubahan filter_var() dan Depresi FILTER_SANITIZE_STRING

1. Penjelasan: Menyaring dan membersihkan input karakter khusus atau tag HTML dari string.

2. Penyebab: Constant FILTER_SANITIZE_STRING (dan FILTER_SANITIZE_STRIPPED) sangat menyesatkan karena dianggap bisa mengamankan string dari celah XSS, padahal hanya melakukan strip tag sederhana tanpa pembersihan kontekstual.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$rawComment = "<script>alert('xss');</script> Halo Sobat!";
$cleanComment = filter_var($rawComment, FILTER_SANITIZE_STRING);

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
$rawComment = "<script>alert('xss');</script> Halo Sobat!";

// Opsi 1: Menggunakan htmlspecialchars secara eksplisit (Sangat Dipertimbangkan)
$cleanComment = htmlspecialchars($rawComment, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');

// Opsi 2: Menggunakan FILTER_SANITIZE_FULL_SPECIAL_CHARS
$cleanComment2 = filter_var($rawComment, FILTER_SANITIZE_FULL_SPECIAL_CHARS);

5. Kenapa harus diganti: htmlspecialchars() melakukan encoding karakter HTML secara sempurna sehingga aman ditampilkan kembali ke layar browser.

6. Dampaknya bila tidak diganti: Melempar Deprecated Notice: Constant FILTER_SANITIZE_STRING is deprecated di PHP 8.1+ dan dihapus di PHP 8.4/8.5.

7. Tips migrasi: Ganti seluruh FILTER_SANITIZE_STRING di project WordPress/backend sobat dengan htmlspecialchars().

8. Catatan kompatibilitas: Deprecated di PHP 8.1, Dihapus penuh di PHP 8.4+.

31. Perubahan Handling Mode Error Default pada PDO (PDO::ERRMODE_EXCEPTION)

1. Penjelasan: Mode pelaporan kesalahan query pada ekstensi PDO database.

2. Penyebab: Dulu mode default PDO adalah PDO::ERRMODE_SILENT, di mana query SQL yang gagal tidak memicu exception apapun kecuali developer rajin mengecek $pdo->errorInfo() secara manual.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
// Query salah sintaks ini tidak melempar exception di PHP 7 (Silent Error)
$pdo->query("SELECT * FROM tabel_yang_tidak_ada"); 

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
try {
    $pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
    $pdo->query("SELECT * FROM tabel_yang_tidak_ada");
} catch (\PDOException $e) {
    // PHP 8 secara otomatis melempar PDOException!
    echo "Gagal Eksekusi SQL: " . $e->getMessage();
}

5. Kenapa harus diganti: Menjamin tidak ada kegagalan query database yang lolos tanpa terdeteksi.

6. Dampaknya bila tidak diganti: Jika kode lama sobat bergantung pada pengujian manual if ($stmt === false) tanpa try-catch, aplikasi akan crash mendadak akibat fatal uncaught exception.

7. Tips migrasi: Bungkus koneksi dan transaksi database PDO dalam blok try-catch (\PDOException $e).

8. Catatan kompatibilitas: Mode default resmi diubah pada PHP 8.0.

32. Perubahan Mode Error Reporting pada MySQLi (Strict Exception)

1. Penjelasan: Mode pelaporan kesalahan pada ekstensi koneksi MySQLi.

2. Penyebab: Sama seperti PDO, mode default MySQLi sebelumnya adalah MYSQLI_REPORT_OFF yang menyembunyikan error SQL. Di PHP 8, mode diubah menjadi MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT.

3. Contoh Kode Lama (PHP 7):

// PHP 7
$conn = mysqli_connect("localhost", "my_user", "my_password", "my_db");
$res = mysqli_query($conn, "SELECT * FROM invalid_table");
if (!$res) {
    echo "Query Gagal secara manual";
}

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
try {
    $conn = mysqli_connect("localhost", "my_user", "my_password", "my_db");
    $res = mysqli_query($conn, "SELECT * FROM invalid_table");
} catch (\mysqli_sql_exception $e) {
    echo "Terjadi Error MySQLi: " . $e->getMessage();
}

5. Kenapa harus diganti: Menyamakan penanganan error ekosistem database PHP berbasis Exception.

6. Dampaknya bila tidak diganti: Query salah akan melemparkan mysqli_sql_exception secara otomatis.

7. Tips migrasi: Tangkap \mysqli_sql_exception pada blok penanganan query database procedural MySQLi sobat.

8. Catatan kompatibilitas: Diubah sejak PHP 8.0.


Grup 6: Fitur Modern PHP 8.0 – 8.5 untuk Refactoring Kode WordPress & Backend

Setelah kita membahas seluruh fungsi yang dihapus dan diperketat, sekarang saatnya kita menikmati hadiah manis dari upgrade PHP 8.5! Fitur-fitur baru berikut ini akan membuat proses penulisan kode backend PHP sobat terasa jauh lebih menyenangkan, ringkas, dan powerful.

33. Constructor Property Promotion

1. Penjelasan: Deklarasi dan penugasan atribut class (properties) langsung di dalam daftar parameter constructor.

2. Penyebab: Memangkas penulisan variabel bertingkat yang sangat berulang di PHP 7 (boiler-plate code).

3. Contoh Kode Lama (PHP 7):

// PHP 7
class ProductService {
    private $db;
    private $logger;

    public function __construct(Database $db, Logger $logger) {
        $this->db = $db;
        $this->logger = $logger;
    }
}

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
class ProductService {
    // Cukup satu baris ini saja!
    public function __construct(
        private Database $db,
        private Logger $logger
    ) {}
}

34. Named Arguments (Argumen Bernama)

1. Penjelasan: Mengirimkan parameter ke fungsi berdasarkan nama parameternya, tanpa harus terikat pada urutan posisinya.

2. Penyebab: Memudahkan pemanggilan fungsi yang memiliki banyak parameter opsional dengan default value.

3. Contoh Kode Lama (PHP 7):

// PHP 7
// Harus mengisi null untuk melewatinya ke parameter ke-4
setcookie('session_token', 'xyz123', 0, '', '', true, true);

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
// Langsung sebut nama parameternya!
setcookie(
    name: 'session_token',
    value: 'xyz123',
    secure: true,
    httponly: true
);

35. Native Enums (Enumerations)

1. Penjelasan: Tipe data bawaan untuk mendefinisikan himpunan nilai konstan yang terbatas dan terisolasi.

2. Penyebab: Di PHP 7, kita terpaksa menggunakan kelas `class Status { const DRAFT = ‘draft’; }` yang tidak memiliki type safety.

3. Contoh Kode Lama (PHP 7):

// PHP 7
class PostStatus {
    const DRAFT = 'draft';
    const PUBLISHED = 'published';
}

function setStatus($status) { /* Tidak ada type safety */ }

4. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
enum PostStatus: string {
    case DRAFT = 'draft';
    case PUBLISHED = 'published';
    case ARCHIVED = 'archived';
}

function setStatus(PostStatus $status): void {
    echo "Status diubah ke: " . $status->value;
}

setStatus(PostStatus::PUBLISHED); // Super aman!

36. Readonly Properties dan Readonly Classes

1. Penjelasan: Mencegah perubahan nilai properti setelah properti tersebut di-inisialisasi pertama kali.

2. Penyebab: Memudahkan pembuatan objek Immutable Data Transfer Object (DTO).

3. Contoh Kode Baru (PHP 8.5):

// PHP 8.5
// Menandai seluruh class sebagai Readonly
readonly class UserDTO {
    public function __construct(
        public int $id,
        public string $email
    ) {}
}

$user = new UserDTO(10, 'riyan@dev.id');
// $user->email = 'hack@dev.id'; // Error Fatal: Cannot modify readonly property!

37. Asymmetric Visibility (PHP 8.4 / 8.5)

1. Penjelasan: Mengizinkan visibilitas pembacaan properti (get) berbeda dengan visibilitas penulisan properti (set).

2. Contoh Kode Modern (PHP 8.5):

// PHP 8.5
class BankAccount {
    // Boleh dibaca secara public, tetapi HANYA boleh diubah dari internal private class!
    public private(set) float $balance = 0.0;

    public function deposit(float $amount): void {
        $this->balance += $amount;
    }
}

$acc = new BankAccount();
$acc->deposit(500000);
echo $acc->balance; // Boleh dibaca (Output: 500000)
// $acc->balance = 10000000; // Error Fatal: Cannot modify private(set) property!

38. Property Hooks (PHP 8.4 / 8.5)

1. Penjelasan: Menuliskan logika getter dan setter secara langsung di dalam deklarasi atribut properti tanpa perlu membuat method terpisah.

2. Contoh Kode Modern (PHP 8.5):

// PHP 8.5
class UserProfile {
    public string $firstName;
    public string $lastName;

    // Property Hook untuk fullName
    public string $fullName {
        get => "{$this->firstName} {$this->lastName}";
        set (string $value) {
            [$this->firstName, $this->lastName] = explode(' ', $value, 2);
        }
    }
}

$p = new UserProfile();
$p->fullName = "Riyanto Dev"; // Otomatis memicu Hook Set!
echo $p->firstName; // Output: Riyanto

Checklist Panduan Migrasi Server Linux & WordPress PHP 8.5

Kalau saya pribadi mau melakukan upgrade PHP di server produksi Linux (Ubuntu/Debian) yang menjalankan WordPress atau aplikasi backend PHP skala besar, saya selalu mengikuti 5 langkah checklist ketat berikut ini. Jangan sampai sobat melewatinya!

Catatan Pengalaman Saya: Jangan pernah langsung eksekusi command apt upgrade php di server produksi utama tanpa melakukan pengujian staging terlebih dahulu!

Tahap 1: Auditing Kode & Static Analysis (Di Komputer Lokal)

  • Jalankan PHP_CodeSniffer dengan PHPCompatibility Standard: Kerakas ini akan memindai seluruh direktori project sobat dan memberikan laporan rinci baris mana saja yang mengandung fungsi deprecated.
    // Terminal Command
    vendor/bin/phpcs -p ./src --standard=PHPCompatibility --runtime-set testVersion 8.5-
    
  • Gunakan PHPStan / Psalm: Lakukan statis analisis untuk mengecek potensi TypeError dan Nullability mismatch.
  • Gunakan Rector PHP: Tool serbaguna ini bisa melakukan refactoring kode otomatis dari sintaks PHP 7 ke PHP 8.5 secara instan!

Tahap 2: Persiapan Server Staging Linux (Ubuntu/Debian)

  • Install repositori PPA Ondřej Surý di server Linux sobat:
    // Bash Script
    sudo add-apt-repository ppa:ondrej/php
    sudo apt update
    sudo apt install php8.5 php8.5-fpm php8.5-mysql php8.5-xml php8.5-curl php8.5-mbstring php8.5-zip php8.5-intl
    
  • Jalankan dua versi PHP bersamaan (PHP 7.4-FPM dan PHP 8.5-FPM) menggunakan Nginx upstream block untuk testing subdomain staging.

Tahap 3: Update Core WordPress, Theme, dan Plugin

  • Core WordPress: Pastikan versi WordPress sobat sudah di-update minimal ke versi 6.4+ (WordPress versi terbaru sudah mendukung kompatibilitas PHP 8.x dengan sangat baik).
  • Cek Plugin Tambahan: Nonaktifkan plugin WordPress tua yang sudah tidak di-update oleh developer-nya lebih dari 2 tahun. Pengalaman saya, plugin SEO atau slider tua sering memicu error create_function() atau each().
  • Aktifkan WP_DEBUG pada file wp-config.php di environment staging:
    // wp-config.php
    define( 'WP_DEBUG', true );
    define( 'WP_DEBUG_LOG', true );
    define( 'WP_DEBUG_DISPLAY', false );
    

Tahap 4: Konfigurasi php.ini untuk Error Logging di Server Linux

Pastikan di file /etc/php/8.5/fpm/php.ini sobat mengonfigurasi directive berikut agar error tidak bocor ke pengunjung website, melainkan tercatat rapi di log file:

// php.ini directive
error_reporting = E_ALL
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/php8.5-fpm-errors.log

Tahap 5: Testing & Cutover Production

  • Simulasikan skenario pendaftaran user, transaksi checkout, upload file, dan pengiriman email API.
  • Periksa file log error: tail -f /var/log/php/php8.5-fpm-errors.log. Jika tidak ada Fatal Error atau Deprecated Notice yang kritis, sobat siap melakukan switch socket FPM pada Nginx/Apache ke PHP 8.5!

Frequently Asked Questions (FAQ) Migrasi PHP

1. Apakah PHP 7.4 benar-benar sudah tidak aman digunakan di server Linux?

Sangat benar sobat. PHP 7.4 sudah resmi EOL sejak 28 November 2022. Server yang masih menjalankan PHP 7.4 tidak lagi menerima patch celah keamanan resmi dari tim PHP core, sehingga sangat rawan diretas hacker melalui eksploitasi memory buffer atau RCE.

2. Berapa peningkatan performa yang didapat setelah upgrade ke PHP 8.5?

Berdasarkan benchmark resmi dan pengalaman saya mengelola server Linux ber-traffic tinggi, upgrade dari PHP 7.4 ke PHP 8.x memberikan peningkatan kecepatan eksekusi hingga 30% – 50% lebih cepat berkat optimasi OPcache dan JIT (Just-In-Time) compiler, serta menghemat pemakaian RAM server hingga 20%.

3. Bisakah saya menjalankan PHP 7.4 dan PHP 8.5 secara bersamaan dalam satu server Linux?

Bisa banget sobat! Jika sobat menggunakan web server Nginx atau Apache dengan PHP-FPM, sobat bisa menginstal beberapa versi PHP sekaligus (misal PHP 7.4 dan PHP 8.5) dan mengarahkan domain/subdomain tertentu ke socket FPM yang berbeda (misal unix:/run/php/php8.5-fpm.sock).

4. Bagaimana jika WordPress saya mengalami Whitescreen (WSoD) setelah upgrade ke PHP 8.5?

Jangan panik! White Screen of Death biasanya terjadi karena ada plugin atau theme tua yang memanggil fungsi yang sudah dihapus di PHP 8 (seperti create_function atau each). Cek log error di wp-content/debug.log atau log FPM server Linux untuk menemukan plugin mana yang bermasalah, lalu matikan folder plugin tersebut secara sementara.

5. Apakah fungsi mysql_connect() masih bisa diakal-akali di PHP 8.5?

Tidak bisa sobat. Ekstensi mysql_* sudah benar-benar dicabut dari source code PHP. Tidak ada extension pendukung resmi lagi. Sobat WAJIB mengganti kode tersebut menggunakan PDO atau MySQLi.

6. Mengapa saya mendapat error “Fatal error: Uncaught TypeError: count()”?

Error ini muncul karena kode sobat memanggil fungsi count() pada variabel yang bernilai null atau bukan bertipe array/Countable. Di PHP 8.0+, aturan ini menjadi sangat strict. Solusinya, bungkus variabel tersebut dengan count($var ?? []).

7. Apa itu Rector PHP dan bagaimana kerakas ini membantu migrasi PHP?

Rector adalah tool CLI berbasis PHP yang mampu memindai ast (Abstract Syntax Tree) kode sobat dan secara otomatis mengubah sintaks PHP lama menjadi sintaks PHP 8.5 modern sesuai aturan yang sobat tentukan. Tool ini sangat menghemat waktu refactoring jutaan baris kode!

8. Apakah pengubah tipe data seperti (unset) masih bisa digunakan?

Sudah tidak bisa. Penggunaan cast (unset) akan menghasilkan Parse Syntax Error di PHP 8.0 ke atas. Sobat harus menggantinya dengan mengisikan nilai null secara langsung ($var = null;).

9. Mengapa pesan warning di PHP 7 berubah menjadi Exception crash di PHP 8.5?

PHP 8 merubah filosofi error handling. Peringatan ringan (warning) pada fungsi internal PHP yang dulu sering memicu silent bug, kini diubah menjadi TypeError atau ValueError agar developer dipaksa menangani error tersebut secara benar menggunakan arsitektur Exception.

10. Apakah aman jika saya langsung melompat dari PHP 7.2 ke PHP 8.5?

Kalau saya pribadi menyarankan: lakukan secara bertahap jika kodenya sangat raksasa. Sobat bisa menaikkan versi dari PHP 7.2 -> 7.4 -> 8.0 -> 8.2 -> 8.5 sambil membereskan Deprecated Notice di tiap tahapan agar proses debugging tidak terlalu membingungkan.


Penutup & Kesimpulan

Melakukan upgrade dan migrasi PHP dari PHP 7 ke PHP 8.5 memang membutuhkan kerja keras, ketelitian, dan pengujian yang mendalam. Namun, hasil yang akan sobat petik sangat sepadan: website yang jauh lebih kencang, penggunaan resource server Linux yang hemat, tingkat keamanan yang terjamin, serta kebahagiaan menulis kode modern dengan fitur-fitur canggih seperti Match Expression, Enums, Readonly Properties, hingga Property Hooks.

Kunci sukses migrasi PHP berada pada tahap auditing dan testing. Jangan pernah meremehkan log error, manfaatkan kerakas otomatis seperti PHP_CodeSniffer dan Rector, serta pastikan server staging sobat sudah terkonfigurasi dengan teliti sebelum melakukan deploy ke server produksi.

Bagaimana dengan project sobat saat ini? Apakah masih ada aplikasi backend atau site WordPress yang tersangkut di PHP 7.4? Atau sobat punya pengalaman unik dan kendala error yang membingungkan saat mencoba upgrade ke PHP 8.5?

Yuk, kita bedah dan diskusikan bersama di kolom komentar di bawah ini! Saya akan sangat senang membantu menjawab pertanyaan dan kendala teknis yang sobat temui di lapangan. Selamat ber-refactoring kode, sobat!

Tinggalkan Balasan

Informasi kontak Anda tidak akan dipublikasikan. Kolom yang wajib diisi ditandai *. Notifikasi akan dikirim ke telegram untuk mempercepat tanggapan komentar