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

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

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

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



답변

실제 호출이 아니라 함수 정의에서 참조로 호출을 표시해야합니다. 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) { }


답변

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

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

이 정규식 사용 :

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

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

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

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


답변

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);

여기에서 참조를 원하고 이미 참조가 있으므로 참조를 그대로 둡니다. 또한 참조를 묶을 수도 있지만 의심합니다.


답변