PHP 5.4 Call-time pass-by-reference-쉽게 고칠 수 있습니까?


219

이 문제를 쉽게 해결할 수있는 방법이 있습니까? 아니면 모든 레거시 코드를 다시 작성해야합니까?

PHP 치명적 오류 : 30 번 라인에서 콜 타임 통과 기준이 제거되었습니다.

이것은 변수가 코드 전체에서 참조로 함수에 전달 될 때 어디서나 발생합니다.


답변:


344

실제 호출이 아니라 함수 정의에서 참조로 호출을 표시해야합니다. PHP는 버전 5.3에서 더 이상 사용되지 않는 오류를 표시하기 시작했기 때문에 코드를 다시 작성하는 것이 좋습니다.

설명서에서 :

함수 호출에는 함수 정의에만 참조 부호가 없습니다. 함수 정의만으로도 인수를 참조로 올바르게 전달할 수 있습니다. PHP 5.3.0부터에서를 사용할 때 "call-time pass-by-reference"가 더 이상 사용되지 않는다는 경고가 표시 &됩니다 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
이 오류가 있었지만 변수에 추가하는 & insted를 제거해야했습니다.
Diana

2
이전 코드에서 event (& $ event)라는 객체에 대해 이것을 사용했으며 오류 메시지가 사라지기 위해 앰퍼샌드를 제거해야했습니다.
Natalia

1
몇 년 동안 개발자로서 실제로 PHP에서 &를 사용할 필요가 없었습니다. 절대로. 이것은 내가 찾던 것입니다. 위대한
Juan Vilar

8
주석에있는 사람들의 경우 변수를 변경하면 더 이상 공유되지 않고 로컬 범위 함수에만 표시되므로 &를 제거하면 예기치 않은 결과가 발생할 수 있습니다. 코드가 무엇인지 모른다면 & 문자를 제거하는 대신 위에서 설명한대로 수정하는 것이 좋습니다.
xorinzor

8

나와 같은 사람은 거대한 레거시 프로젝트를 5.6으로 업데이트해야하기 때문에이 글을 읽습니다. 여기서 대답에서 알 수 있듯이 빠른 수정은 없습니다. 문제의 각 발생을 수동으로 찾아서 수정해야합니다. .

프로젝트에서 문제가있는 모든 라인을 찾는 가장 편리한 방법 (정확한 정적 코드 분석기를 사용하는 것이 부족하지만 매우 정확하지만 편집기에서 올바른 위치로 바로 이동시키는 것을 모릅니다) 멋진 PHP 린터가 내장 된 Visual Studio Code와 Regex로 검색 할 수있는 검색 기능을 사용하고있었습니다. (물론, PHP linting 및 Regex 검색을 수행하는 IDE / Code 편집기를 사용할 수 있습니다.)

이 정규식 사용 :

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

&$함수 정의가 아닌 행에서만 발생하는 프로젝트 전체를 검색 할 수 있습니다 .

이것은 여전히 ​​많은 오 탐지를 나타내지 만 작업을 더 쉽게 만듭니다.

VSCode의 검색 결과 브라우저를 사용하면 문제가되는 행을 쉽게 탐색하고 찾을 수 있습니다. 각 결과를 클릭하고 린터가 빨간색으로 밑줄을 긋는 것을 찾으십시오. 고쳐야 할 것들.


1
이것이 내가 찾던 것입니다!
Sonny

4
이 목적으로 사용하고있는보다 정확한 정규식 :(?<!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.