오류 메시지 "엄격한 표준 : 변수 만 참조로 전달해야합니다."


81
$el = array_shift($instance->find(..))

위의 코드는 어떻게 든 엄격한 표준 경고를보고하지만 다음과 같은 것은 아닙니다.

function get_arr(){
    return array(1, 2);
}
$el = array_shift(get_arr());

어쨌든 경고는 언제보고할까요?


1
$ instance-> find (..)는 무엇을 반환합니까?
Silver Light

2
여기에 솔루션입니다 : stackoverflow.com/questions/9848295/...
ajaristi

두 번째 예제 ( get_arr()함수) 엄격한 표준 고지 (테스트 된 PHP 5.2 및 PHP 5.5)를 생성하기 때문에 예제 (또는 논리)가 질문에서 잘못된 방향 일 수 있다고 생각합니다 .
MrWhite

답변:


93

다음 코드를 고려하십시오.

error_reporting(E_STRICT);
class test {
    function test_arr(&$a) {
        var_dump($a);
    }
    function get_arr() {
        return array(1, 2);
    }
}

$t = new test;
$t->test_arr($t->get_arr());

그러면 다음과 같은 출력이 생성됩니다.

Strict Standards: Only variables should be passed by reference in `test.php` on line 14
array(2) {
  [0]=>
  int(1)
  [1]=>
  int(2)
}

이유? 이 test::get_arr()메서드는 변수가 아니며 엄격 모드에서는 경고가 생성됩니다. get_arr()메서드 배열 값을 반환 하므로이 동작은 매우 직관적이지 않습니다 .

엄격 모드에서이 오류를 해결하려면 메서드의 서명을 변경하여 참조를 사용하지 않도록합니다.

function test_arr($a) {
    var_dump($a);
}

서명을 변경할 수 없으므로 array_shift중간 변수를 사용할 수도 있습니다.

$inter = get_arr();
$el = array_shift($inter);

7
@ user198729 : 설명이나 수정 사항을 찾고 있었는데 첫 번째 항목에 current ()를 사용할 수 있다는 것을 알았습니다. 아아 end ()는 "내부 포인터를 마지막 요소로 전진"하기 때문에 마지막으로 작동하지 않습니다. 현재 (array_reverse (SomeFunction을 ())) 작업 (예,이 바보)
MSpreij

1
using을 사용 current하면 배열 포인터가 첫 번째 요소에 있다고 가정합니다. 대부분의 경우 유효한 가정 일 수 있지만주의해야합니다.
cmbuckley 2013-08-03

1
같은 물론 @leepowers는 다음 같은 문제가있을 것 array_shift()그것이 참조 :-) 수정 것으로 예상된다는 점에서
cmbuckley

1
@ user198729 $intermediate추가 괄호 쌍을 사용하여 값을 피할 수 있습니다 . $el = array_shift( ( get_arr() ) );. stackoverflow.com/questions/9848295/…
Chloe

1
@Chloe 이것은 코드를 간단하게 유지하기 위해 내가 본 가장 훌륭한 솔루션입니다! 감사합니다!
hargobind

7

$instance->find() 변수에 대한 참조를 반환합니다.

이 참조를 변수에 먼저 저장하지 않고 함수에 대한 인수로 사용하려고 할 때 보고서를받습니다.

이것은 메모리 누수를 방지하는 데 도움이되며 아마도 다음 PHP 버전에서 오류가 될 것입니다.

두 번째 코드 블록이 다음과 같이 작성하면 오류가 발생합니다 ( &함수 서명에서 참고 ).

function &get_arr(){
    return array(1, 2);
}
$el = array_shift(get_arr());

따라서 빠른 (그렇지 않은) 수정은 다음과 같습니다.

$el = array_shift($tmp = $instance->find(..));

기본적으로 먼저 임시 변수에 할당하고 변수를 인수로 보냅니다.


이제 작동합니다 (확인). 참조를 반환하려면 return 문이 아닌 메서드 서명에서 선언해야합니다 (내 잘못).
Sagi

아니요, 서명을 변경할 수 없습니다. @ pygorex1의 중간 변수는이 문제를 해결할 수 있지만 중복 된 것 같지 않습니까?
user198729 2010 년

나는 당신이 서명을 변경할 수 없다는 것을 알고 있습니다. 당신은 일시적으로 (= 중간) 변수를 사용하지만 같은 줄에 그것을 할 수 있습니다. 두 번째 코드 스 니펫을보십시오.
Sagi

4
작동하지 않는 두 번째 스 니펫을 시도했습니다. 별도의 줄에서만 작동합니다
user198729

3
과연. 할당 은 할당 된 값을 반환합니다 . array_shift($tmp = $instance->find(..))양수인의 값 $instance->find(..)$tmp다음 통과 과제의 값array_shift()- 전달과 같은 것이 아니다 $tmp자체는, 그래서 더 좋은 할당하지 않고 원래의 상황보다 더 없습니다.
phils

6

오류의 원인은 내부 PHP 프로그래밍 데이터 구조 함수 인 array_shift () [php.net/end]를 사용하기 때문입니다.

이 함수는 배열을 매개 변수로 사용합니다. array_shift()매뉴얼 의 프로토 타입에는 앰퍼샌드가 표시되어 있지만, 해당 기능의 확장 된 정의 뒤에는주의 문서가 없으며 매개 변수가 실제로 참조로 전달된다는 명백한 설명도 없습니다.

아마도 이것은 / understood /입니다. 하지만 이해가 안 돼 오류의 원인을 찾기가 어려웠습니다.

코드 재현 :

function get_arr()
{
    return array(1, 2);
}
$array = get_arr();
$el = array_shift($array);

3

이 코드 :

$monthly_index = array_shift(unpack('H*', date('m/Y')));

다음으로 변경해야합니다.

$date_time = date('m/Y');
$unpack = unpack('H*', $date_time);
array_shift($unpack);


0

이와 같은 명백한 경우에는 함수 앞에 "@"를 사용하여 메시지를 억제하도록 항상 PHP에 지시 할 수 있습니다.

$monthly_index = @array_shift(unpack('H*', date('m/Y')));

이런 식으로 모든 오류 를 억제하는 것이 최고의 프로그래밍 관행 중 하나가 아닐 수도 있지만, 특정 경우 (이와 같은 경우)는 편리하고 수용 가능합니다.

결과적으로 당신의 친구 '시스템 관리자'가 덜 오염 된 것에 만족할 것이라고 확신합니다 error.log.


이 대답을 누가 반대했는지는 모르지만 제시된 솔루션은 작동하며 PHP 표준 기술입니다. 정말 실망 스럽네요 ... 다음에 더 이상 질문에 대답하지 않을 수도 있습니다 ... :(
Julio Marchi

5
오류 메시지를 억제해도 코드 문제가 해결되지 않기 때문이라고 생각합니다. 이 유형의 오류가 향후 PHP 릴리스에서 E_STRICT에서 E_ERROR로 변경되고 이제 코드가 실행되지 않고 오류 / 출력도 생성되지 않으면 어떻게 하시겠습니까?
Luke

@TinoDidriksen, 특히 새로운 세대를 위해 일부 "나쁜 습관"에 대해 조언해야하는 이유를 이해하고 이에 동의합니다. 그러나 자원은 사용하기에 안전하고 제안 된 컨텍스트에 적용 할 수있는 경우에 사용됩니다. 오류 억 제기 "@"를 폐지하려면 언어 자체에서 제거되었을 것입니다. "eval"과 동일합니다 (악할 수 있지만 목적이 있음). 내가 반대하는 것은 일부 자원의 사용이 아니라 조언의 일반화에 관한 것입니다. 제안 된 사례의 경우 디버깅 목적이 아니라도 사용하는 것이 해가되지 않습니다.
Julio Marchi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.