PHP 5.4 Truyền qua thời gian cuộc gọi - Dễ dàng sửa lỗi?


219

Có cách nào để dễ dàng khắc phục vấn đề này hay tôi thực sự cần phải viết lại tất cả các mã kế thừa?

Lỗi nghiêm trọng của PHP: Tham chiếu qua thời gian cuộc gọi đã bị xóa trong ... trên dòng 30

Điều này xảy ra ở mọi nơi khi các biến được truyền vào các hàm như các tham chiếu trong toàn bộ mã.


Câu trả lời:


344

Bạn nên biểu thị cuộc gọi bằng cách tham chiếu trong định nghĩa hàm, không phải cuộc gọi thực tế. Vì PHP bắt đầu hiển thị các lỗi không dùng nữa trong phiên bản 5.3, tôi sẽ nói rằng đó là một ý tưởng tốt để viết lại mã.

Từ tài liệu :

Không có dấu hiệu tham chiếu trên một lệnh gọi hàm - chỉ trên các định nghĩa hàm. Chỉ các định nghĩa hàm là đủ để truyền chính xác đối số bằng tham chiếu. Tính đến PHP 5.3.0, bạn sẽ nhận được một cảnh báo nói rằng "cuộc gọi thời gian pass-by-reference" bị phản đối khi bạn sử dụng &trong foo(&$a);.

Ví dụ: thay vì sử dụng:

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

Sử dụng:

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

9
Deprecation là kể từ PHP 5.0.0, trở lại thời gian đó cho E_COMPILE_WARNINGlỗi cấp, để tham khảo: php.net/manual/en/...
hakre

5
Tôi đã có lỗi này nhưng cần phải loại bỏ & insted thêm vào biến.
Diana

2
Tôi đã sử dụng mã này trong mã cũ cho một đối tượng được gọi là sự kiện (& $ event) và phải xóa ký hiệu và thông báo lỗi biến mất.
Natalia

1
trong tất cả những năm làm nhà phát triển, tôi thực sự không bao giờ cần sử dụng & trên php. chưa bao giờ. đây chính xác là những gì tôi đang tìm kiếm. tuyệt vời
Juan Vilar

8
đối với những người trong các nhận xét, lưu ý rằng việc xóa & có thể dẫn đến kết quả không mong muốn vì mọi thay đổi đối với biến sẽ không còn được chia sẻ mà sẽ chỉ hiển thị cho phạm vi cục bộ của hàm. Vì vậy, trừ khi bạn biết mã làm gì, tôi khuyên bạn nên sửa nó như được mô tả ở trên thay vì chỉ xóa & ký tự
xorinzor

8

Đối với bất kỳ ai, giống như tôi, đọc điều này bởi vì họ cần cập nhật một dự án kế thừa khổng lồ lên 5.6: như câu trả lời ở đây chỉ ra, không có cách khắc phục nhanh: bạn thực sự cần phải tìm ra từng sự cố một cách thủ công và khắc phục nó .

Cách thuận tiện nhất tôi tìm thấy để tìm tất cả các dòng có vấn đề trong một dự án (không sử dụng bộ phân tích mã tĩnh đầy đủ, rất chính xác nhưng tôi không biết bất kỳ điều gì đưa bạn đến đúng vị trí trong trình soạn thảo ngay lập tức) đã sử dụng Visual Studio Code, có một trình giả lập PHP đẹp được tích hợp và tính năng tìm kiếm của nó cho phép tìm kiếm bằng Regex. (Tất nhiên, bạn có thể sử dụng bất kỳ trình soạn thảo IDE / Code nào cho việc tìm kiếm linting và Regex của PHP.)

Sử dụng regex này:

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

có thể tìm kiếm trên toàn dự án để chỉ xuất hiện &$trong các dòng không phải là định nghĩa hàm.

Điều này vẫn xuất hiện rất nhiều tích cực sai, nhưng nó làm cho công việc dễ dàng hơn.

Trình duyệt kết quả tìm kiếm của VSCode giúp cho việc đi qua và tìm ra các dòng vi phạm cực kỳ dễ dàng: bạn chỉ cần nhấp qua từng kết quả và tìm ra những người mà kẻ nói dối gạch dưới màu đỏ. Những người bạn cần sửa chữa.


1
Đây là những gì tôi đang tìm kiếm!
Sonny

4
Regex chính xác hơn Tôi đang sử dụng cho mục đích này:(?<!function)[:> ][a-zA-Z0-9_]+(?<!foreach|array)\s?\([^()]*&\$
Mojo

Chỉ cần sử dụng phpcs, sẽ đào mọi tập tin có cái này cho bạn.
Thomas Cheng

6

PHP và tài liệu tham khảo có phần không trực quan. Nếu được sử dụng các tài liệu tham khảo phù hợp ở đúng nơi có thể cung cấp các cải tiến hiệu suất lớn hoặc tránh các cách giải quyết rất xấu và mã bất thường.

Sau đây sẽ tạo ra một lỗi:

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

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

Không ai trong số này phải thất bại vì họ có thể tuân theo các quy tắc dưới đây nhưng không nghi ngờ gì đã bị xóa hoặc vô hiệu hóa để ngăn chặn nhiều sự nhầm lẫn di sản.

Nếu chúng đã hoạt động, cả hai đều liên quan đến chuyển đổi dự phòng sang tham chiếu và lần thứ hai cũng liên quan đến chuyển đổi dự phòng trở lại biến chứa trong phạm vi.

Cái thứ hai được sử dụng có thể cho phép một tham chiếu được chuyển đến mã không có ý định làm việc với các tham chiếu. Điều này là cực kỳ xấu cho khả năng bảo trì.

Điều này sẽ không làm gì:

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

Cụ thể hơn, nó biến tham chiếu trở lại thành một biến bình thường khi bạn không yêu cầu tham chiếu.

Điều này sẽ làm việc:

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

Điều này thấy rằng bạn đang chuyển một tham chiếu nhưng muốn tham chiếu nên biến nó thành một tham chiếu.

Điều này có nghĩa là bạn không thể chuyển tham chiếu đến một hàm trong đó tham chiếu không được yêu cầu rõ ràng để làm cho nó trở thành một trong số ít các lĩnh vực mà PHP nghiêm ngặt trong việc chuyển các loại hoặc trong trường hợp này là loại meta hơn.

Nếu bạn cần hành vi năng động hơn, nó sẽ hoạt động:

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

Ở đây nó thấy rằng bạn muốn có một tài liệu tham khảo và đã có một tài liệu tham khảo vì vậy hãy để nó một mình. Nó cũng có thể chuỗi tham chiếu nhưng tôi nghi ngờ điều này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.