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
ไม่ว่าคุณจะใหม่แค่ไหน (หรือเคยเป็น) - นี่คือสิ่งที่คุณสามารถอ่านได้จากเอกสาร PHP: php.net/manual/en/control-structures.foreach.php
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
Bottom line: หากคุณกำลังจะเปลี่ยน array / variable - คุณควรใช้การอ้างอิง มันเร็วขึ้นสะอาดขึ้นและอ่านง่ายขึ้น
Lulu

2
ฉันอยากรู้ว่าทำไมการอ้างอิงใน a 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 ไม่มีขอบเขตของตัวเอง - @Mark Amery

    นี่อาจเป็นปัญหาร้ายแรงเมื่อตัวแปรถูกนำมาใช้ซ้ำในขอบเขตเดียวกัน คำถาม SO อีกข้อหนึ่งแสดงถึงสาเหตุที่อาจเป็นปัญหา

  2. เนื่องจาก foreach อาศัยตัวชี้อาร์เรย์ภายในใน PHP 5 การเปลี่ยนภายในลูปอาจทำให้เกิดพฤติกรรมที่ไม่คาดคิด - เอกสาร PHP สำหรับ foreach

    การยกเลิกการบันทึกหรือเปลี่ยนค่าแฮช (คีย์) ระหว่างการวนซ้ำในลูปเดียวกันอาจนำไปสู่พฤติกรรมที่ไม่คาดคิดใน PHP <7 ปัญหานี้มีความซับซ้อนยิ่งขึ้นเมื่ออาเรย์อ้างอิง

  3. ประสิทธิภาพของ Foreach
    โดยทั่วไป PHP ชอบการส่งผ่านค่าเนื่องจากคุณสมบัติการคัดลอกเมื่อเขียน หมายความว่าภายใน PHP จะไม่สร้างข้อมูลที่ซ้ำกันยกเว้นว่าจำเป็นต้องเปลี่ยนสำเนา เป็นที่ถกเถียงกันว่าการส่งผ่านโดยอ้างอิงforeachจะช่วยปรับปรุงประสิทธิภาพหรือไม่ เป็นกรณีเสมอคุณต้องทดสอบสถานการณ์เฉพาะของคุณและกำหนดตัวเลือกที่ใช้หน่วยความจำน้อยและเวลา cpu สำหรับข้อมูลเพิ่มเติมโปรดดูที่โพสต์ลิงก์ด้านล่างโดย NikiC

  4. อ่านรหัสได้
    การสร้างการอ้างอิงใน PHP นั้นเป็นสิ่งที่หลุดมือไปอย่างรวดเร็ว หากคุณเป็นสามเณรและไม่สามารถควบคุมสิ่งที่คุณกำลังทำอยู่ได้ดีที่สุดที่จะหลีกเลี่ยงการอ้างอิง สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ&โอเปอเรเตอร์ดูที่คู่มือนี้: การอ้างอิง - สัญลักษณ์นี้มีความหมายอะไรใน PHP?
    สำหรับผู้ที่ต้องการเรียนรู้เพิ่มเติมเกี่ยวกับส่วนของภาษาPHP นี้ : การอ้างอิง PHP อธิบาย

คำอธิบายทางเทคนิคที่ดีมากโดย @NikiC ของตรรกะภายในของ PHP foreach loops:
PHP 'foreach' ทำงานอย่างไร


นอกเหนือจากปัญหาที่ระบุไว้ฉันขอแนะนำให้เพิ่มunset($value);หลังforeachวงเล็บปิดเพื่อให้แน่ใจว่าตัวแปรอ้างอิงโดยไม่สามารถใช้ได้อีกหลังจากการวนซ้ำ 3v4l.org/2V2AQ
fyrye

15

ใช้foreach($fields as &$field){- ดังนั้นคุณจะทำงานกับอาร์เรย์เดิม

นี่คือเพิ่มเติมเกี่ยวกับการส่งผ่านโดยการอ้างอิง


@RBA โปรดอ้างถึงคำตอบข้างต้น - พวกเขามีรายละเอียดและการอัปเดตมากขึ้น - ฉันยังไม่ได้ใช้ 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 เราจำเป็นต้องเพิ่มอักขระ '&' ด้านหน้าตัวแปรเพื่อระบุว่าค่าจะถูกส่งผ่านโดยการอ้างอิง
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
อย่าทำอย่างนี้. ฉันเห็นอย่างน้อยสองสิ่งที่ผิดกับรหัสของคุณ: การกำหนดให้กับเขตข้อมูล $ ไม่ทำงาน (อาร์เรย์ของเขตข้อมูล $ จะไม่ถูกแก้ไขเมื่อคุณทำเช่นนี้) และคืนค่าเขตข้อมูล $ ส่งคืนเขตข้อมูลเอกพจน์ไม่ใช่อาร์เรย์
Staplerfahrer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.