PHP 5.4 Pass-by-reference waktu panggilan - Perbaikan mudah tersedia?

219

Apakah ada cara untuk dengan mudah memperbaiki masalah ini atau apakah saya benar-benar perlu menulis ulang semua kode lama?

Kesalahan fatal PHP: Pass-by-referensi waktu panggilan telah dihapus di ... pada baris 30

Ini terjadi di mana-mana karena variabel dilewatkan ke fungsi sebagai referensi di seluruh kode.

bardiir
sumber

Jawaban:

344

Anda harus menunjukkan panggilan dengan referensi dalam definisi fungsi, bukan panggilan yang sebenarnya. Karena PHP mulai menunjukkan kesalahan penghentian dalam versi 5.3, saya akan mengatakan itu akan menjadi ide yang baik untuk menulis ulang kode.

Dari dokumentasi :

Tidak ada tanda referensi pada panggilan fungsi - hanya pada definisi fungsi. Definisi fungsi saja sudah cukup untuk melewati argumen dengan referensi. Pada PHP 5.3.0, Anda akan mendapatkan peringatan yang mengatakan bahwa "panggilan-time pass-by-referensi" sudah ditinggalkan ketika Anda menggunakan &di foo(&$a);.

Misalnya, alih-alih menggunakan:

// Wrong way!
myFunc(&$arg);               # Deprecated pass-by-reference argument
function myFunc($arg) { }

Menggunakan:

// Right way!
myFunc($var);                # pass-by-value argument
function myFunc(&$arg) { }
Tim Cooper
sumber
9
Penghentian adalah sejak PHP 5.0.0, saat itu memberikan E_COMPILE_WARNINGtingkat kesalahan, untuk referensi: php.net/manual/en/…
hakre
5
Saya memiliki kesalahan ini tetapi perlu menghapus & insted menambahkan ke variabel.
Diana
2
Saya menggunakan kode lama ini untuk objek yang disebut event (& $ event), dan harus menghapus ampersand agar pesan kesalahannya hilang.
Natalia
1
dalam semua tahun saya sebagai pengembang saya sebenarnya tidak pernah perlu menggunakan & di php tidak akan pernah. ini persis apa yang saya cari. Hebat
Juan Vilar
8
untuk orang-orang di komentar, perhatikan bahwa menghapus & dapat menghasilkan hasil yang tidak terduga karena setiap perubahan pada variabel tidak akan lagi dibagikan tetapi hanya akan terlihat oleh fungsi lingkup lokal. Jadi, kecuali Anda tahu kode apa yang saya lakukan, saya akan merekomendasikan memperbaikinya seperti yang dijelaskan di atas, bukan hanya menghapus & karakter
xorinzor
8

Bagi siapa pun, seperti saya, membaca ini karena mereka perlu memperbarui proyek warisan raksasa ke 5.6: seperti yang ditunjukkan di sini, tidak ada perbaikan cepat: Anda benar-benar perlu menemukan setiap kemunculan masalah secara manual, dan memperbaikinya .

Cara paling mudah yang saya temukan untuk menemukan semua jalur yang bermasalah dalam suatu proyek (singkat menggunakan penganalisa kode statis penuh, yang sangat akurat tapi saya tidak tahu apa pun yang membawa Anda ke posisi yang benar di editor segera) menggunakan Visual Studio Code, yang memiliki linter PHP yang bagus, dan fitur pencariannya yang memungkinkan pencarian oleh Regex. (Tentu saja, Anda dapat menggunakan editor IDE / Kode untuk ini yang melakukan pencarian PHP dan pencarian Regex.)

Menggunakan regex ini:

^(?!.*function).*(\&\$)

dimungkinkan untuk mencari di seluruh proyek untuk kemunculan &$hanya pada baris yang bukan definisi fungsi.

Ini masih menghasilkan banyak kesalahan positif, tetapi itu membuat pekerjaan lebih mudah.

Browser hasil pencarian VSCode membuat berjalan melalui dan menemukan garis yang menyinggung itu super mudah: Anda cukup mengklik setiap hasil, dan mencari orang-orang yang digarisbawahi warna merah. Yang perlu Anda perbaiki.

Pekka
sumber
1
Ini yang saya cari!
Sonny
4
Regex yang lebih akurat yang saya gunakan untuk tujuan ini:(?<!function)[:> ][a-zA-Z0-9_]+(?<!foreach|array)\s?\([^()]*&\$
Mojo
cukup gunakan phpcs, akan menggali setiap file yang memiliki ini untuk Anda.
Thomas Cheng
6

PHP dan referensi agak tidak intuitif. Jika digunakan dengan tepat referensi di tempat yang tepat dapat memberikan peningkatan kinerja besar atau menghindari solusi yang sangat buruk dan kode yang tidak biasa.

Berikut ini akan menghasilkan kesalahan:

 function f(&$v){$v = true;}
 f(&$v);

 function f($v){$v = true;}
 f(&$v);

Tak satu pun dari ini harus gagal karena mereka dapat mengikuti aturan di bawah ini tetapi tidak diragukan lagi telah dihapus atau dinonaktifkan untuk mencegah banyak kebingungan warisan.

Jika mereka berhasil, keduanya melibatkan konversi redundan ke referensi dan yang kedua juga melibatkan konversi redundan kembali ke variabel yang terkandung dalam cakupan.

Yang kedua dulu memungkinkan memungkinkan referensi untuk diteruskan ke kode yang tidak dimaksudkan untuk bekerja dengan referensi. Ini sangat jelek untuk perawatannya.

Ini tidak akan melakukan apa-apa:

 function f($v){$v = true;}
 $r = &$v;
 f($r);

Lebih khusus lagi, ini mengubah referensi kembali menjadi variabel normal karena Anda belum meminta referensi.

Ini akan berhasil:

 function f(&$v){$v = true;}
 f($v);

Ini melihat bahwa Anda melewati non-referensi tetapi menginginkan referensi sehingga mengubahnya menjadi referensi.

Apa artinya ini adalah bahwa Anda tidak dapat meneruskan referensi ke fungsi di mana referensi tidak secara eksplisit diminta untuk menjadikannya salah satu dari sedikit area di mana PHP ketat pada jenis passing atau dalam hal ini lebih dari tipe meta.

Jika Anda membutuhkan perilaku yang lebih dinamis, ini akan berfungsi:

 function f(&$v){$v = true;}
 $v = array(false,false,false);
 $r = &$v[1];
 f($r);

Di sini terlihat bahwa Anda menginginkan referensi dan sudah memiliki referensi, jadi biarkan saja. Mungkin juga rantai referensi tetapi saya ragu ini.

jgmjgm
sumber