Migrasi php 5 ke 8

Artikel ini bukan tentang fitur baru atau uji komparatif;

Hari ini, kami akan menyusun rencana pembaruan dan membahas potensi kesulitan utama berdasarkan contoh memperbarui proyek besar dari PHP 7. 4 sampai 8. 0. Sebagian besar langkah juga akan membantu saat merencanakan pemutakhiran dari versi sebelumnya

PHP 8 official logo

Kenapa sekarang?

PHP 8 dirilis empat bulan lalu. Pada saat penulisan, ada tiga versi tambalan PHP 8 yang memperbaiki bug kritis. Selain itu, paket pustaka dan komposer paling populer akhirnya menambahkan dukungan PHP 8. Meskipun untuk banyak perpustakaan, dukungan PHP 8 melibatkan perubahan versi di komposer, kompatibilitas yang dikonfirmasi secara resmi dari semua dependensi folder vendor adalah pemblokir untuk pemutakhiran

Prasyarat

Artikel ini adalah retrospektif dari proses pembaruan PHP dari 7. 4 sampai 8. 0 di Oro Inc. repositori monolitik dengan 11 aplikasi web dan 45 modul proyek yang cukup besar berdasarkan Symfony 4. 4 LTS, 3M + LoC, dan lebih dari 600.000 kelas PHP, termasuk pengujian tetapi tidak termasuk vendor

Angka-angka tersebut tidak mencerminkan kerumitan proyek tetapi menunjukkan jumlah kode PHP yang telah diperbarui. Saya juga harus mencatat bahwa sebagian besar kode tidak menggunakan strict_types=1, yang secara teknis mempersulit pembaruan

Perubahan Besar

Selain fitur-fitur baru, yang dalam banyak kasus memiliki alternatif, rilis utama memungkinkan pengembang bahasa PHP untuk merusak kompatibilitas ke belakang. Ini tidak terlalu buruk karena tidak perlu menulis ulang sebagian besar proyek untuk meningkatkan

Kompatibilitas rusak hanya dengan menghapus fitur yang ditandai sebagai usang dalam versi minor PHP 7 sebelumnya. 0–7. 4. Untuk memperkenalkan peningkatan, pengembang inti PHP juga dapat mengubah perilaku fungsi yang belum didokumentasikan sebelumnya atau telah diposisikan sebagai sesuatu yang tidak pasti sejak awal.

Sebagian besar perubahan terjadi di bidang perbandingan yang ketat dan jenis argumen yang ketat. Meskipun strict_types=1 tidak menjadi perilaku default, di versi 8, sebagian besar fungsi bawaan PHP telah menerima pengetikan argumen yang ketat, terkadang tanpa pengetikan

Memutakhirkan Ekstensi PHP

Jika Anda menggunakan ekstensi PHP pihak ketiga, perbarui terlebih dahulu. Meskipun untuk sebagian besar proyek ini seharusnya bukan masalah besar, ini dapat memblokir peningkatan lebih lanjut

Menentukan Paket Komposer Yang Perlu Ditingkatkan

Peringatan spoiler. pembaruan dependensi telah menjadi tahap pemutakhiran yang paling rumit

PHP memiliki banyak solusi siap pakai, sehingga sulit menemukan aplikasi tanpa ketergantungan pihak ketiga. Dalam kebanyakan kasus, komposer digunakan untuk mengelolanya. Alat ini memungkinkan Anda untuk menentukan ketergantungan pada paket dan menentukan apa yang disebut ketergantungan platform dari setiap paket, yang menyertakan versi PHP dan daftar ekstensi PHP yang diperlukan

Hal pertama yang terlintas dalam pikiran adalah menentukan versi PHP baru di root composer. json tetapi jangan terburu-buru dulu karena ini akan memicu rantai koreksi kesalahan yang tidak menyenangkan saat Anda menjalankan pembaruan komposer. Sebaiknya tanyakan langsung kepada komposer jika ada perpustakaan yang dapat mengganggu pemutakhiran. Untuk melakukannya, buka root proyek dan jalankan perintah berikut

composer why-not php 8

Jika Anda menggunakan paket populer dan memperbarui dependensi ke versi terbaru tepat waktu, Anda akan melihat pesan ini dalam satu menit atau lebih

composer why-not php 8

Sebagian besar akan melihat daftar dependensi "lengkap" yang perlu diperbarui untuk mendukung PHP 8. Lengkap dalam koma terbalik di sini karena selalu ada beberapa perpustakaan yang menetapkan batasan platform yang sangat lemah sejak awal atau tidak menentukannya sama sekali, yang berarti mereka sebenarnya tidak kompatibel dengan PHP 8. Jika proyek memiliki cakupan pengujian yang baik, proyek tersebut akan memainkan peran penting di masa depan dan membantu mengidentifikasi paket tersebut. Jika belum, mari kita coba dan optimis

Selanjutnya, dengan daftar lengkap dependensi yang tidak mendukung PHP 8 di versi saat ini, navigasikan ke ahli paket. org dan periksa apakah ada versi paket yang mendukung versi baru dari bahasa pemrograman. Aplikasi dengan OroCommerce dan OroCRM memiliki sekitar 300 paket komposer dalam dependensi, dan sejauh ini semuanya telah menerima pembaruan yang kompatibel. Dalam beberapa kasus, seperti dengan friendsofsymfony/rest-bundle, Anda bahkan tidak perlu memperbarui paket ke versi terbaru yang mengandung banyak ketidakcocokan mundur

Kontribusi untuk Open-Source

Jika Anda menemukan beberapa paket yang tertinggal, tidak perlu khawatir. Komunitas PHP cukup aktif. Dalam kebanyakan kasus, meningkatkan ke PHP 8 tidak memerlukan investasi yang signifikan. Pertama, periksa cabang master untuk melihat apakah dukungan telah ditambahkan dan akan disertakan dalam rilis berikutnya. Kemudian, periksa daftar masalah dan tarik permintaan untuk menyebutkan PHP 8. Dalam kebanyakan kasus, alasan keterlambatan pembaruan dan penyelesaian masalah sudah teridentifikasi pada tahap ini

Namun, jika perpustakaan tidak digunakan secara luas dan metode sebelumnya tidak membuahkan hasil, Anda selalu dapat berkontribusi pada sumber terbuka. Dalam kasus kami, itu cukup untuk memperbaiki tes di symfony/acl-bundle dan menulis komentar untuk masalah di nelmio/security-bundle. Ini memungkinkan kami untuk mengurangi daftar dengan dua poin. Menjadi sangat aktif, para pengembang perpustakaan ini berhasil merilis versi baru hanya dalam beberapa jam setelah kontribusi minimal. Ini tidak selalu terjadi begitu cepat. Dalam beberapa kasus, kami harus menunggu beberapa minggu untuk rilis baru. Untuk sebagian besar proyek, ini bukan masalah besar. Jika perpustakaan tidak lagi didukung, masuk akal untuk memikirkan garpu atau alternatif;

Upgrade Paket Komposer

Memperbarui paket komposer mungkin merupakan tahap terpanjang untuk sebagian besar proyek karena, bersama dengan dukungan versi PHP yang baru, pengembang ekstensi aktif sering kali merilis versi utama dan merusak kompatibilitas ke belakang. Namun kabar baiknya adalah sebagian besar perubahan dijelaskan secara mendetail di catatan rilis atau changelog di root repositori. Kompilasi daftar perubahan, dan itu adalah sebagian besar cakupan peningkatan Anda

Tingkatkan Estimasi Waktu

Bergantung pada bagaimana dependensi digunakan (misalnya, apakah hanya antarmuka yang digunakan atau ada banyak penggantian), upaya pemutakhiran dari satu paket mungkin berbeda. Itu sering dapat diidentifikasi dengan membaca daftar perubahan dan melakukan pencarian cepat pada kode berdasarkan ruang nama, kelas, dan nama fungsi yang telah berubah. Ini memungkinkan untuk mendapatkan perkiraan perkiraan waktu pembaruan dengan segera

Memperbarui Dependensi

Penting untuk dicatat bahwa sebagian besar, versi dependensi baru dengan dukungan untuk PHP 8 masih mendukung PHP 7. 4, sehingga pembaruan dapat dilakukan secara bertahap, paket demi paket

Jika Anda telah berhasil menyelesaikan pembaruan komposer dan mencapai tahap ini, selamat. Folder vendor, yang biasanya berisi sebagian besar kode PHP dalam proyek, secara teoritis kompatibel. Kita dapat melangkah lebih jauh dan memperbarui kode secara langsung

Peretasan untuk Ketergantungan yang Tidak Kompatibel

Jika Anda perlu memperbarui sekarang untuk menguji kompatibilitas pustaka yang tidak kompatibel sebelum memperbaruinya ke PHP 8, berikut adalah beberapa trik untuk melakukannya

  • Beri tahu komposer bahwa Anda menggunakan PHP 7. 4 tetapi jalankan kode di PHP 8
"platform": {"php": "7.4"}
_

Karena hampir semua perpustakaan pihak ketiga bekerja secara bersamaan dengan PHP 8 dan 7. 4, Anda dapat memperoleh pembaruan dan, pada saat yang sama, berhasil menyelesaikan pembaruan komposer dengan persyaratan ketergantungan tingkat platform yang tidak kompatibel. Composer mengabaikan versi sebenarnya dari PHP jika konfigurasi platform tingkat proyek ditentukan

  • Mendefinisikan ulang kelas yang tidak kompatibel. Jika DiC digunakan, biasanya cukup sederhana. Hiasi, atau bahkan ganti sepenuhnya, kelas asli melalui konfigurasi wadah. Bahkan jika kelas di vendor dinyatakan sebagai final, itu selalu dapat ditimpa pada tingkat di komposer. json, misalnya, suka. Tentu saja, ini berantakan, tetapi seperti yang dikatakan Marco Pivetta, peretasan akan terlihat seperti peretasan

Memperbarui Kode Anda

Belum waktunya untuk fitur baru karena Anda harus terlebih dahulu memperbaiki apa yang rusak. Di sini, tes otomatis akan berguna. Dengan bantuan mereka, Anda dapat menginstal proyek pada versi baru, menjalankan semua pengujian, dan memperkirakan jumlah pekerjaan lebih lanjut dalam hitungan beberapa jam. Misalnya, di Oro, sebagian besar fungsi dicakup oleh pengujian Behat, fungsional, dan unit. Sekadar memberi gambaran tentang jumlah tes, total waktu tes lebih dari 30 jam. Ini memungkinkan kami untuk melihat gambar yang lengkap dan akurat segera setelah memperbarui vendor dan memperbaiki masalah pemasangan aplikasi

Konfigurasi Sebelum Pengujian

Jika rekan-rekan developer sudah rajin dan sudah menggunakan pengetikan yang ketat, seharusnya update berjalan lancar; . Itulah mengapa penting untuk menguji proyek, secara otomatis atau manual, dan menyusun daftar apa yang rusak, menuliskan pengecualian dari log jika ada. Pengujian masuk akal dengan pesan kesalahan yang ketat diaktifkan di php. ini

error_reporting = E_ALL

Tentu saja, asalkan proyek sebelumnya bekerja dalam mode ini tanpa kesalahan. Jika tidak, dikombinasikan dengan display_errors=off, ini akan membantu Anda melihat log kesalahan dan peringatan tanpa merusak struktur halaman. Jika lognya tidak panjang, daftar ini akan terbukti sangat berguna

Deteksi Kesalahan Otomatis

Berkat AST oleh Nikita Popov, ada cukup banyak penganalisa statis di PHP yang dapat menunjukkan area masalah dan terkadang bahkan memperbarui kode secara otomatis

  • Phpstan dan Psalm adalah alat paling populer untuk membantu mempertahankan pengetikan yang ketat. Tetapi jika mereka belum pernah digunakan dalam proyek sebelumnya, tidak perlu terburu-buru, karena mereka akan menemukan banyak masalah. Namun, tidak semuanya memerlukan perbaikan segera untuk meningkatkan ke PHP 8
  • Rektor akan membantu untuk "menulis ulang" kode menggunakan perbaikan gula sintaksis, tetapi tidak akan menunjukkan masalah yang mendesak
  • Dari podcast “Lima Menit PHP”, saya belajar tentang plugin PHPCompatibility yang cukup menarik untuk PHP_CodeSniffer, yang seharusnya menunjukkan masalahnya. Sayangnya, apa yang sebenarnya dilakukannya hanya menunjukkan beberapa kesalahan positif dalam proyek kami, jadi saya tidak dapat merekomendasikannya. Plugin tidak memeriksa kompatibilitas nyata; . Misalnya, ini menunjukkan bahwa kami tidak dapat menggunakan "string" di ruang nama yang dimulai dengan versi 7. 0, meskipun masih berfungsi tanpa kesalahan

PHP_CodeSniffer false-positive checks

PhpStorm ternyata yang paling berguna. Secara default, IntelliJ IDEA hanya memvalidasi file yang terbuka, tetapi memiliki fitur untuk menganalisis keseluruhan proyek. Untuk melakukannya, kode yang Anda tulis harus sempurna dari perspektif PhpStorm; . Di sini, kami dapat meluncurkan satu inspeksi khusus

Ketika Anda melihat kesalahan, salin namanya, pilih folder kode di file tree, pilih Code> Run inspection by name di menu PhpStorm, masukkan nama inspeksi. Sangat cepat, Anda akan mendapatkan hasil untuk keseluruhan proyek. Misalnya, saat memperbarui pustaka pihak ketiga, "Pemeriksaan Hierarki Kelas" akan menampilkan tanda tangan metode yang perlu diperbaiki dalam kode setelah memperbarui vendor

Check class hierarchy in PhpStorm

Class must be declared abstract or implement method …

Perubahan yang perlu diingat

Jika tidak ada tes otomatis pada proyek atau cakupannya tidak lengkap, Anda perlu memperhatikan fungsi penyortiran dan pembanding

Penyortiran

Perilaku fungsi pengurutan (usort,…) telah berubah. Pertama, fungsi perbandingan yang digunakan dalam pengurutan sekarang harus mengembalikan -1, 0, atau 1

True and false still work but trigger a deprecation notice. The spaceship operator `<=>` will be helpful here. But most importantly, sorting of the elements with the same weight now leaves the order of the elements unchanged, which is different from the behavior in PHP 7.4. Suppose the project is large enough and has a modular structure like at Oro. In that case, problems may arise in extensions that are implemented using a chain of responsibilities, decorators, or a simple registry with a sorted list of add-ons. In our case, some extensions that depended on the order of execution were broken, because the sorting priority was not clearly specified. For example, the order of columns and rows in some tables changed, and in other places, we received an exception.

usort($exportFiles, function (File $a, File $b) {
- return $b->getMtime() > $a->getMtime();
+ return $b->getMtime() <=> $a->getMtime();
});

Peretasan untuk menyimpan penyortiran, seperti di PHP 7

$comparisonClosure = function (ExtensionVisitorInterface $a, ExtensionVisitorInterface $b) {
if ($a->getPriority() === $b->getPriority()) {
- return 0;
+ return -1;
}
return $a->getPriority() > $b->getPriority() ? -1 : 1;
}
_

Pada gambar di bawah, hanya dua Ekstensi terakhir yang memiliki prioritas eksplisit. Di sini, perhatikan item 4

Stable sorting PHP 7.4 vs PHP 8.0

Perbandingan Non-Ketat

Perbandingan non-ketat antara angka dan string non-numerik sekarang berfungsi dengan mentransmisikan angka ke string dan membandingkan string. Kami memiliki masalah dengan dua contoh pertama

╔═══════════════╦════════╦═══════╗
║ Comparison ║ Before ║ Now ║
╠═══════════════╬════════╬═══════╣
║ 0 == "foo" ║ true ║ false ║
║ 0 == "" ║ true ║ false ║
║ 42 == "42foo" ║ true ║ false ║
╚═══════════════╩════════╩═══════╝

Perbandingan Ketat

Masalah-masalah ini sulit ditemukan dalam kode, tetapi lebih baik mengetahuinya terlebih dahulu

Seperti disebutkan di atas, beberapa fungsi PHP bawaan beralih ke argumen yang diketik dengan ketat, dan perpustakaan pihak ketiga mendukung tren yang sama. Jika pengetikan yang ketat tidak digunakan dalam kode, semuanya akan tetap berfungsi dengan pengetikan dalam banyak kasus. Tapi ada pengecualian;

Misalnya, fungsi bulat tidak menerima argumen string yang tidak cocok dengan int. tanda tangan mengapung. Baris “40. 5” akan berfungsi tetapi “40. 5” tidak akan, atau sebaliknya, tergantung pada lokalnya

- $amount = round($row[$attributeName], 2);
+ $amount = round((float)$row[$attributeName], 2);
_

str_replace dengan menyatakan(strict_types=1) tidak lagi menerima integer sebagai argumen kedua karena mengharapkan sebuah array. rangkaian

- $alias = str_replace(WebsiteIdPlaceholder::NAME, $websiteId, $alias);
+ $alias = str_replace(WebsiteIdPlaceholder::NAME, (string)$websiteId, $alias);

Tetapi ada juga kasus yang kurang jelas di mana perilaku berubah secara diam-diam. Dalam kasus kami, php-amqplib berhenti terhubung ke RabbitMQ karena kami meneruskan array kosong ke fungsi saat null diharapkan. Di versi sebelumnya, dengan perbandingan yang longgar, ini bekerja sangat berbeda

- $this->channel->wait([], false, $timeout);
+ $this->channel->wait(null, false, $timeout);
_

Argumen bernama

Kami mengalami masalah dari fitur yang agak kontradiktif ini bahkan sebelum kami mulai menggunakannya

Misalnya, sekarang Anda tidak dapat dengan aman meneruskan larik asosiatif dengan argumen ke call_user_func_array

- $data = call_user_func_array('array_merge', $indexData);
+ $data = array_merge(...array_values($indexData));
_

Kesalahan Alih-alih Mengembalikan Salah

Berikut adalah beberapa contoh perubahan pada kode kami

get_parent_class

"platform": {"php": "7.4"}
_0

metode_ada

"platform": {"php": "7.4"}
_1

Atau benar-benar menangkap kesalahan

"platform": {"php": "7.4"}
_2

Ini hanyalah perubahan wajib yang diperlukan saat memutakhirkan satu repositori dengan 3.000.000.000 baris kode PHP ke versi 8. 0, yang sedikit dijelaskan dalam dokumentasi. Anda dapat menemukan daftar lengkapnya di panduan pembaruan resmi

Hasil

Jadi berapa banyak baris kode yang harus kita perbarui di repositori Oro untuk mendukung PHP 8?. )

Seperti yang Anda lihat, pembaruannya cukup sederhana dan umumnya membantu menemukan kode yang bukan kualitas terbaik. Karena tujuannya adalah untuk mendukung PHP 8. 0 tanpa menggunakan fitur-fitur baru, dan pengembang berusaha mempertahankan kompatibilitas mundur, permintaan tarikan ternyata relatif kecil. 86 file dengan +316 dan 257 baris yang dimodifikasi. Ini tanpa memperhitungkan perubahan pada composer. json dan komposer. kunci

Permintaan penarikan kecil, terutama karena kami menyelesaikan sebagian besar pembaruan vendor tiga bulan lalu sebagai bagian dari persiapan rilis LTS. Proses pemutakhiran, tidak termasuk ulasan, memakan waktu sekitar 40 jam di seluruh repositori monolitik, yang relatif sedikit dibandingkan dengan pengalaman pembaruan teknologi sebelumnya di Oro. Tentu saja, perkiraannya akan bervariasi tergantung pada jumlah dan konten kode, tetapi karena sebagian besar proyek PHP sebagian besar tingkat tinggi, Anda seharusnya tidak menghadapi lebih banyak masalah daripada yang kami alami.

Apa berikutnya?

Sekarang Anda dapat menggunakan semua fitur baru untuk meningkatkan keterbacaan kode — setidaknya dalam kode baru. Paling-paling, jika Anda tidak khawatir kehilangan kesalahan git, Anda dapat menggunakannya di seluruh proyek, berkat otomatisasi yang disediakan oleh Rektor dan alat serupa

Nyalakan JIT, silangkan jari, dan luncurkan ApacheBench

Dan tunggu PHP 8. 1 (yang akhirnya akan menyertakan enum), revolusi dari serat, dan ketika semua pemeriksaan jenis yang bekerja saat runtime di PHP akan memperlambat aplikasi lebih sedikit

Bagaimana cara memigrasikan PHP 5 ke PHP 7?

Kode untuk Memutakhirkan dari PHP5 ke PHP7 . Misalnya. error_reporting(E_ALL ^ ​​E_STRICT); . Buat lapisan abstraksi untuk operasi basis data dengan menggunakan ekstensi PDO karena PDO mendukung banyak basis data. Set error reporting to E_ALL as below. Eg: error_reporting(E_ALL ^ E_STRICT); Solve all the errors including notice errors and deprecated errors. Create an abstraction layer for database operations by using PDO extension as PDO supports multiple databases.

Bagaimana cara memutakhirkan PHP saya ke 8?

PHP 8 adalah pembaruan utama bahasa PHP yang dirilis pada 26 November 2020. .
Paket PHP. .
Copot pemasangan/Hapus PHP 7. .
Autoclean dan Autoremove. .
Tambahkan repositori PPA Ondřej Surý. .
Instal PHP8. .
Instal Ekstensi PHP 8

Haruskah saya bermigrasi ke PHP 8?

Selain itu, versi PHP yang lebih baru berkinerja lebih baik daripada versi yang lebih lama. Peningkatan kinerja dan keamanan yang signifikan mungkin merupakan satu-satunya hal yang diperlukan untuk meningkatkan dan mengamankan pengalaman pengguna yang positif di situs web Anda. PHP 8 jauh lebih cepat daripada PHP 7 menurut berbagai tolok ukur web .

Apakah PHP 5 masih didukung?

PHP 5. 6, 7. 0, 7. 1, 7. 2, 7. 3, dan 7. 4 Akhir Hidup. Akhir masa pakai berarti versi ini tidak lagi memiliki dukungan keamanan dan dapat terpapar pada kerentanan keamanan yang belum ditambal.