PHP foreach는 원래 배열 값을 변경합니다.


143

나는 다차원 배열에서 매우 새롭고 이것이 큰 시간을 보내고 있습니다.

내 배열은 다음과 같습니다.

$fields = array(
    "names" => array(
         "type"         => "text",
         "class"        => "name",
         "name"         => "name",
         "text_before"  => "name",
         "value"        => "",
         "required"     => true,
    )
)

그런 다음 필요한 경우 입력이 채워져 있는지 확인하는 기능이 있습니다.

function checkForm($fields){
    foreach($fields as $field){
        if($field['required'] && strlen($_POST[$field['name']]) <= 0){
            $fields[$field]['value'] = "Some error";
        }
    }
    return $fields;
}

이제 내 문제는이 줄입니다

$fields[$field]['value'] = "Some error";

이것을 반환하기 때문에 원래 배열의 내용을 변경하고 싶지만 foreach 루프에서 현재 배열의 이름 (이 예제의 이름)을 어떻게 얻습니까?



1
아무리 새로
Nikolay Ivanov

답변:


261

PHP에서 참조 ( &)로 전달하는 것은 논쟁의 여지가 있습니다. 왜 필요한지 알고 결과를 테스트하지 않는 한 사용하지 않는 것이 좋습니다.

다음을 수행하는 것이 좋습니다.

foreach ($fields as $key => $field) {
    if ($field['required'] && strlen($_POST[$field['name']]) <= 0) {
        $fields[$key]['value'] = "Some error";
    }
}

따라서 기본적으로 $field$fields[$key]이 필요할 때 와 데이터를 변경해야 할 때 사용합니다.


좋아, 이거 효과가있어! 이 같은 것을 먼저 시도했지만, 나는 어떤 장소를 망쳤다 고 생각합니다 :) 이제 나는 당신의 예를 천 번 사용하고 결코 잊지 않을 것입니다! :)
Jeppe

도움이되어 다행입니다. 또한 필자가 링크 한 기사와 foreach 공식 문서 ( php.net/manual/ro/control-structures.foreach.php ) 를 읽는 것이 좋습니다.
Vlad Preda

4
결론 : 배열 / 변수를 변경하려면 참조를 사용해야합니다. 더 빠르고 깨끗하며 읽기 쉽습니다.
Lulu

2
왜 참조로 전달하는 foreach것이 논쟁의 여지가 있는지 궁금 합니다. 숨겨진 부작용이나 다른 것을 가진 함수 호출과 같지 않습니다.
UncaAlby

1
"참조로 전달하지 마십시오"또는 "참조로 전달하는 것이 악의적"이라기보다는 "참조로 전달 (&)은 ... 논쟁의 여지가 있습니다". 불꽃 전쟁을 시작할 가능성이 적습니다. :)
Sean the Bean

163

사용 &:

foreach($arr as &$value)
{
     $value = $newVal;
}

&배열의 값을 참조로 전달하고 변수의 새 인스턴스를 작성하지 않습니다. 따라서 참조를 변경하면 원래 값이 변경됩니다.

http://php.net/manual/en/language.references.pass.php

2018 년 편집
이 답변은 인터넷상의 많은 사람들이 선호하는 것 같습니다. 그래서 더 많은 정보와주의를 기울이기로 결정했습니다.
참조로 foreach(또는 기능에서) 참조 는 깨끗하고 짧은 해결책이지만 많은 초보자에게는 이것이 위험한 함정일 수 있습니다.

  1. PHP의 루프에는 자체 범위가 없습니다. -@ 마크 애 머리

    변수가 동일한 범위에서 재사용되는 경우 심각한 문제가 될 수 있습니다. 또 다른 SO 질문은 이것이 왜 문제가 될 수 있는지 잘 보여줍니다.

  2. foreach는 PHP 5의 내부 배열 포인터를 사용하므로 루프 내에서 포인터를 변경하면 예기치 않은 동작이 발생할 수 있습니다. -foreach 용 PHP 문서

    동일한 루프에서 반복하는 동안 레코드를 설정 해제하거나 해시 값 (키)을 변경하면 PHP <7에서 예기치 않은 동작이 발생할 수 있습니다.이 문제는 배열 자체가 참조 일 때 더욱 복잡해집니다.

  3. 각 성능.
    일반적으로 PHP는 copy-on-write 기능으로 인해 값으로 전달하는 것을 선호합니다. 즉, 내부적으로 PHP는 복사본을 변경하지 않으면 중복 데이터를 만들지 않습니다. 참조에 의한 전달 foreach이 성능 향상을 제공 하는지 여부는 논쟁의 여지 가 있습니다. 항상 그렇듯이 특정 시나리오를 테스트하고 더 적은 메모리와 CPU 시간을 사용하는 옵션을 결정해야합니다. 자세한 내용은 아래 NikiC에서 링크 한 SO 게시물을 참조하십시오.

  4. 코드 가독성.
    PHP에서 참조를 작성하는 것은 빠르게 처리되지 않는 것입니다. 당신이 초보자이고 당신이하고있는 일을 완전히 통제 할 수 없다면, 참고 문헌에서 멀리 떨어져있는 것이 가장 좋습니다. &연산자에 대한 자세한 내용은 이 안내서를 참조하십시오 . 참조 — PHP에서이 기호의 의미는 무엇입니까?
    PHP 언어의이 부분에 대해 더 배우고 싶은 사람들을 위해 : PHP References Explained

PHP foreach 루프의 내부 로직에 대한 @NikiC의 매우 좋은 기술 설명 :
PHP 'foreach'는 실제로 어떻게 작동합니까?


나열된 문제 외에도 반복 후 참조 기준 변수를 더 이상 사용할 수 없도록 닫는 대괄호 unset($value);뒤에 추가하는 것이 좋습니다 foreach. 3v4l.org/2V2AQ
3

15

사용 foreach($fields as &$field){-원본 배열로 작업합니다.

참조로 전달하는 방법에 대한 자세한 내용은 다음과 같습니다 .


@RBA의 PLS 위의 답변을 참조 - 그들은 더 자세한 내용과 업데이트가 - 지금 동안이에, A에 대한 업데이트 너무 모르고 PHP를 사용하지 않은
k102

1
function checkForm(& $fields){
    foreach($fields as $field){
        if($field['required'] && strlen($_POST[$field['name']]) <= 0){
            $fields[$field]['value'] = "Some error";
        }
    }
    return $fields;
}

이것이 내가 참조로 전달하는 것입니다.


이 기법은 원래 변수의 값을 변경하는 데 사용됩니다. PHP는 Pass by Value Technique을 지원하기 때문에. 변수 앞에 '&'문자를 추가하여 참조로 전달할 값을 명시해야합니다.
Sagar Kadam

1
그럼 왜 아직도 돌아 오는 $fields거야?
MAZux

이것은 제안 된 3 가지 중 최악의 대답입니다. 이 답변을 우연히 발견 한 사람은 데이터를 변경하고 반환하도록 함수를 설계하지 마십시오. 원저자 : 당신은 왜이 솔루션이 다른 솔루션보다 더 좋은지 또는 어떻게 작동하는지에 대한 설명을 제공하지 않았습니다.
Dharman

-6

이 시도

function checkForm($fields){
        foreach($fields as $field){
            if($field['required'] && strlen($_POST[$field['name']]) <= 0){
                $field['value'] = "Some error";
            }
        }
        return $field;
    }

3
이러지 마십시오. 코드에서 적어도 두 가지 잘못된 점을 볼 수 있습니다. $ field에 할당이 작동하지 않고 (이 작업을 수행 할 때 $ fields 배열이 수정되지 않음) return $ field는 배열이 아닌 단일 필드를 반환합니다.
Staplerfahrer 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.