PHP 5.4 Referans zaman çağrı by-Kolay düzeltme mevcut mu?


219

Bu sorunu kolayca düzeltmenin bir yolu var mı yoksa gerçekten tüm eski kodu yeniden yazmam gerekiyor mu?

PHP Ölümcül hata: 30 numaralı satırdaki referans zaman çağrı by-pass kaldırıldı

Değişkenler kod boyunca referans olarak fonksiyonlara aktarıldıkça bu her yerde olur.


Yanıtlar:


344

Çağrıyı, gerçek çağrıyı değil, işlev tanımında referans ile belirtiyor olmalısınız. PHP sürüm 5.3'te kullanımdan kaldırma hatalarını göstermeye başladığından beri, kodu yeniden yazmanın iyi bir fikir olacağını söyleyebilirim.

Belgelerden :

Bir işlev çağrısında referans işareti yoktur - yalnızca işlev tanımlarında. Yalnızca işlev tanımları, argümanı referans olarak doğru bir şekilde iletmek için yeterlidir. PHP 5.3.0 itibaren, kullandığınızda "çağrı zamanlı pass-by-reference" kullanımdan kaldırıldı belirten bir uyarı alacaksınız &içinde foo(&$a);.

Örneğin, kullanmak yerine:

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

kullanın:

// Right way!
myFunc($var);                # pass-by-value argument
function myFunc(&$arg) { }

9
Kullanımdan kaldırılma PHP 5.0.0'dan beri, o zamana kadar E_COMPILE_WARNINGseviye hatası veriyor , referans için: php.net/manual/en/…
hakre

5
Ben bu hatayı vardı ama & değişken ekleme ekleme insted gerekiyordu.
Diana

2
Bu olay (& $ olay) adlı bir nesne için eski kodda kullanılan ve hata iletisi kaybolmak için ve işareti kaldırmak zorunda kaldı.
Natalia

1
bir geliştirici olarak tüm yıllar içinde aslında php kullanmak için gerek yoktu. asla. tam da aradığım şey buydu. harika
Juan Vilar

8
yorumdaki kişiler için, değişkente yapılan herhangi bir değişiklik artık paylaşılmayacağından & yalnızca işlevlerin yerel kapsamı tarafından görülebileceğinden, & öğesinin kaldırılmasının beklenmeyen sonuçlara neden olabileceğini unutmayın. Kodun ne yaptığını bilmiyorsanız, sadece & karakterini kaldırmak yerine yukarıda açıklandığı gibi düzeltmenizi tavsiye ederim
xorinzor

8

Benim gibi, dev bir eski projeyi 5.6'ya güncellemeleri gerektiğinden bunu okuyan herkes için: buradaki yanıtların işaret ettiği gibi hızlı bir çözüm yoktur: sorunun her bir oluşumunu manuel olarak bulmanız ve düzeltmeniz gerekir. .

Bir projedeki tüm sorunlu çizgileri bulmanın en uygun yolu (çok doğru olan tam bir statik kod analizörü kullanmaktan kısa, ancak editörde doğru pozisyona götüren herhangi bir şey bilmiyorum) güzel bir PHP linter yerleşik olan Visual Studio Code ve Regex ile arama sağlayan arama özelliğini kullanıyordu. (Elbette, bunun için PHP linting ve Regex aramaları yapan herhangi bir IDE / Kod düzenleyicisini kullanabilirsiniz.)

Bu normal ifadeyi kullanarak:

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

proje genelinde arama yapmak mümkündür. &$ sadece fonksiyon tanımı olmayan satırlarda .

Bu hala çok sayıda yanlış pozitif ortaya çıkıyor, ancak işi kolaylaştırıyor.

VSCode'un arama sonuçları tarayıcısı, yürümeyi ve rahatsız edici çizgileri bulmayı süper kolaylaştırır: sadece her bir sonucu tıklarsınız ve linterin kırmızının altını çizenleri ararsınız. Düzeltmeniz gerekenler.


1
Aradığım şey buydu!
Sonny

4
Daha doğru regex Bu amaçla kullanıyorum:(?<!function)[:> ][a-zA-Z0-9_]+(?<!foreach|array)\s?\([^()]*&\$
Mojo

sadece phpcs kullanın, sizin için bu olan her dosyayı kazacak.
Thomas Cheng

6

PHP ve referanslar biraz sezgisel değildir. Doğru yerlerde uygun şekilde kullanılırsa, büyük performans iyileştirmeleri sağlayabilir veya çok çirkin geçici çözümlerden ve olağandışı kodlardan kaçınabilir.

Aşağıdakiler bir hata oluşturur:

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

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

Bunların hiçbiri aşağıdaki kurallara uyabilecekleri için başarısız olmak zorunda değildir, ancak birçok eski karışıklığı önlemek için şüphesiz kaldırılmış veya devre dışı bırakılmamıştır.

Çalışırlarsa, her ikisi de referansa yedekli bir dönüşüm içerir ve ikincisi de kapsamlandırılmış bir değişkene geri dönüşümü içerir.

İkincisi, referanslarla çalışmak için tasarlanmamış olan koda bir referansın geçmesine izin vermek mümkün olmuştu. Bu sürdürülebilirlik için son derece çirkin.

Bu hiçbir şey yapmaz:

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

Daha spesifik olarak, referans istemediğiniz için referansı normal bir değişkene dönüştürür.

Bu çalışacak:

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

Bu, bir referansı geçmediğinizi, ancak bir referans istediğinizi görür, bu yüzden referansa dönüştürür.

Bunun anlamı, bir referansın PHP'nin geçiş türlerinde veya bu durumda daha fazla meta türünde katı olduğu birkaç alandan biri olması için açıkça istenmediği bir işleve referans veremeyeceğinizdir.

Daha dinamik davranışa ihtiyacınız varsa, bu işe yarayacaktır:

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

Burada bir referans istediğinizi ve zaten bir referansınız olduğunu görür, bu yüzden onu yalnız bırakır. Ayrıca referans zinciri olabilir ama bundan şüphe ediyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.