PHP 5.4 การอ้างอิงเวลาโทรผ่าน - แก้ไขได้ง่ายหรือไม่


219

มีวิธีใดที่จะแก้ไขปัญหานี้ได้อย่างง่ายดายหรือฉันต้องเขียนรหัสเดิมทั้งหมดใหม่อีกครั้งหรือไม่

ข้อผิดพลาดร้ายแรงของ PHP: หมายเลขอ้างอิงการโทรตามเวลาการโทรได้ถูกลบใน ... ในบรรทัดที่ 30

สิ่งนี้เกิดขึ้นทุกหนทุกแห่งเนื่องจากตัวแปรถูกส่งผ่านไปยังฟังก์ชั่นเป็นการอ้างอิงตลอดทั้งรหัส


คำตอบ:


344

คุณควรจะปฏิเสธการโทรโดยการอ้างอิงในการกำหนดฟังก์ชั่นไม่ใช่การโทรจริง เนื่องจาก PHP เริ่มแสดงข้อผิดพลาดในการคัดค้านในเวอร์ชั่น 5.3 ฉันจะบอกว่ามันเป็นความคิดที่ดีที่จะเขียนรหัสใหม่

จากเอกสาร :

ไม่มีเครื่องหมายอ้างอิงในการเรียกใช้ฟังก์ชั่น - เฉพาะกับคำจำกัดความของฟังก์ชัน นิยามฟังก์ชั่นเพียงอย่างเดียวเพียงพอที่จะผ่านการโต้แย้งโดยอ้างอิง ในฐานะของ PHP 5.3.0 คุณจะได้รับการเตือนบอกว่า "เรียกร้องเวลาผ่านโดยการอ้างอิง" จะเลิกเมื่อคุณใช้ใน&foo(&$a);

ตัวอย่างเช่นแทนที่จะใช้:

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

ใช้:

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

9
การคัดค้านคือตั้งแต่ PHP 5.0.0 กลับมาเวลาที่ให้E_COMPILE_WARNINGข้อผิดพลาดระดับสำหรับการอ้างอิง: php.net/manual/en/…
hakre

5
ฉันพบข้อผิดพลาดนี้ แต่จำเป็นต้องลบ & ติดตั้งการเพิ่มลงในตัวแปร
ไดอาน่า

2
ฉันใช้สิ่งนี้ในรหัสเก่าสำหรับวัตถุที่เรียกว่าเหตุการณ์ (& $ เหตุการณ์) และต้องลบเครื่องหมายและเพื่อให้ข้อความแสดงข้อผิดพลาดหายไป
Natalia

1
ในทุก ๆ ปีของฉันในฐานะนักพัฒนาฉันไม่จำเป็นต้องใช้ & บน php ไม่เลย. นี่คือสิ่งที่ฉันกำลังมองหา ยอดเยี่ยม
Juan Vilar

8
สำหรับคนที่อยู่ในความคิดเห็นโปรดทราบว่าการลบ & อาจส่งผลให้เกิดผลลัพธ์ที่ไม่คาดคิดเนื่องจากการเปลี่ยนแปลงตัวแปรจะไม่ถูกแบ่งปันอีกต่อไป แต่จะปรากฏเฉพาะกับขอบเขตการทำงานในท้องถิ่นเท่านั้น ดังนั้นถ้าคุณไม่ทราบว่ารหัสทำอะไรฉันขอแนะนำให้แก้ไขตามที่อธิบายไว้ข้างต้นแทนที่จะลบ & ตัวอักษร
xorinzor

8

สำหรับทุกคนที่ชอบฉันอ่านสิ่งนี้เพราะพวกเขาจำเป็นต้องอัปเดตโครงการยักษ์ใหญ่เป็น 5.6: เนื่องจากคำตอบที่นี่ชี้ให้เห็นว่าไม่มีการแก้ไขอย่างรวดเร็ว: คุณต้องค้นหาปัญหาแต่ละครั้งด้วยตนเองและแก้ไขด้วยตนเอง .

วิธีที่สะดวกที่สุดที่ฉันพบในการค้นหาบรรทัดที่มีปัญหาทั้งหมดในโครงการ (ขาดการใช้ตัววิเคราะห์โค้ดแบบคงที่เต็มรูปแบบซึ่งมีความแม่นยำมาก แต่ฉันไม่รู้ว่าจะนำคุณไปยังตำแหน่งที่ถูกต้องในเครื่องมือแก้ไขทันที) กำลังใช้ Visual Studio Code ซึ่งมี linter PHP ในตัวที่ดีและคุณสมบัติการค้นหาที่อนุญาตให้ทำการค้นหาโดย Regex (แน่นอนว่าคุณสามารถใช้ตัวแก้ไข IDE / Code ใด ๆ สำหรับสิ่งนี้ที่ใช้การค้นหาด้วย PHP และ Regex)

ใช้ regex นี้:

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

เป็นไปได้ที่จะค้นหาทั้งโครงการสำหรับการเกิดขึ้นของ&$เฉพาะในบรรทัดที่ไม่ได้นิยามฟังก์ชั่น

สิ่งนี้ยังปรากฏผลบวกปลอมจำนวนมาก แต่มันทำให้งานง่ายขึ้น

เบราว์เซอร์ผลการค้นหาของ VSCode ทำให้การค้นหาและการค้นหาบรรทัดที่ละเมิดง่ายมาก: คุณเพียงคลิกที่ผลลัพธ์แต่ละรายการและมองหาสิ่งที่ตัวอักษรขีดเส้นใต้ขีดเส้นใต้สีแดง สิ่งที่คุณต้องแก้ไข


1
นี่คือสิ่งที่ฉันกำลังมองหา!
ซันนี่

4
regex ที่แม่นยำยิ่งขึ้นที่ฉันใช้เพื่อจุดประสงค์นี้:(?<!function)[:> ][a-zA-Z0-9_]+(?<!foreach|array)\s?\([^()]*&\$
Mojo

เพียงใช้ phpcs จะขุดทุกไฟล์ที่มีให้คุณ
โทมัสเฉิง

6

PHP และการอ้างอิงค่อนข้างใช้งานง่าย หากใช้การอ้างอิงอย่างเหมาะสมในสถานที่ที่เหมาะสมสามารถให้การปรับปรุงประสิทธิภาพขนาดใหญ่หรือหลีกเลี่ยงการแก้ไขปัญหาที่น่าเกลียดมากและรหัสที่ผิดปกติ

ต่อไปนี้จะทำให้เกิดข้อผิดพลาด:

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

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

สิ่งเหล่านี้ไม่ต้องล้มเหลวเนื่องจากสามารถปฏิบัติตามกฎด้านล่างได้ แต่ไม่ต้องสงสัยเลยว่าถูกลบหรือปิดใช้งานเพื่อป้องกันความสับสนในเรื่องมรดก

หากพวกเขาทำงานทั้งสองเกี่ยวข้องกับการแปลงซ้ำซ้อนเพื่อการอ้างอิงและครั้งที่สองเกี่ยวข้องกับการแปลงซ้ำซ้อนกลับไปเป็นตัวแปรที่มีขอบเขต

คนที่สองเคยเป็นไปได้ที่อนุญาตให้ส่งการอ้างอิงไปยังโค้ดที่ไม่ได้ตั้งใจจะทำงานกับการอ้างอิง มันน่าเกลียดอย่างยิ่งสำหรับการบำรุงรักษา

สิ่งนี้จะไม่ทำสิ่งใด:

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

โดยเฉพาะอย่างยิ่งมันจะเปลี่ยนการอ้างอิงกลับเป็นตัวแปรปกติในขณะที่คุณยังไม่ได้ขอการอ้างอิง

สิ่งนี้จะได้ผล:

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

สิ่งนี้เห็นว่าคุณกำลังผ่านการไม่อ้างอิง แต่ต้องการการอ้างอิงดังนั้นเปลี่ยนเป็นการอ้างอิง

สิ่งนี้หมายความว่าคุณไม่สามารถส่งต่อการอ้างอิงไปยังฟังก์ชันที่ไม่ได้ขอการอ้างอิงอย่างชัดเจนเพื่อให้เป็นหนึ่งในไม่กี่พื้นที่ที่ PHP เข้มงวดในการส่งผ่านประเภทหรือในกรณีนี้มีเมตาดาต้ามากกว่า

หากคุณต้องการพฤติกรรมแบบไดนามิกมากกว่านี้จะทำงาน:

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

ที่นี่จะเห็นว่าคุณต้องการการอ้างอิงและมีการอ้างอิงอยู่แล้วจึงทิ้งไว้คนเดียว มันอาจโยงการอ้างอิง แต่ฉันสงสัยในเรื่องนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.