PHP terlebih dahulu mengubah nilai array asli


143

Saya sangat baru di array multi dimensi, dan ini mengganggu saya waktu besar.

Array saya adalah sebagai berikut:

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

Lalu saya mendapat fungsi memeriksa apakah input ini diisi, jika mereka diperlukan.

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

Sekarang masalah saya adalah baris ini

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

Saya ingin mengubah konten array asli, karena saya mengembalikan ini, tetapi bagaimana cara mendapatkan nama array saat ini (nama dalam contoh ini) di loop foreach saya?



1
Tidak peduli seberapa baru Anda (atau dulu) - ini adalah sesuatu yang dapat Anda baca dari dokumentasi PHP: php.net/manual/en/control-structures.foreach.php
Nikolay Ivanov

Jawaban:


261

Dalam PHP, melewatkan dengan referensi ( &) adalah ... kontroversial. Saya sarankan tidak menggunakannya kecuali Anda tahu mengapa Anda membutuhkannya dan menguji hasilnya.

Saya akan merekomendasikan melakukan hal berikut:

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

Jadi pada dasarnya gunakan $fieldketika Anda membutuhkan nilai-nilai, dan $fields[$key]ketika Anda perlu mengubah data.


Bagus, ini berhasil! Mencoba sesuatu seperti ini dulu, tapi kurasa aku mengacaukan suatu tempat :) Sekarang aku akan menggunakan contohmu ribuan kali dan tidak pernah lupa! :)
Jeppe

Senang itu membantu. Juga, saya sarankan untuk membaca artikel yang saya tautkan , dan juga dokumentasi resmi untuk foreach ( php.net/manual/ro/control-structures.foreach.php )
Vlad Preda

4
Intinya: jika Anda akan mengubah array / variabel - maka Anda harus menggunakan referensi. Lebih cepat, lebih bersih, dan lebih mudah dibaca.
Lulu

2
Saya ingin tahu mengapa lewat referensi dalam foreachharus kontroversial? Ini tidak seperti panggilan fungsi dengan efek samping tersembunyi atau apa pun.
UncaAlby

1
Terima kasih telah mengatakan bahwa "lewat referensi (&) adalah ... kontroversial", daripada "jangan lewat referensi" atau "lewat referensi adalah jahat". Lebih kecil kemungkinannya memulai perang api. :)
Sean the Bean

163

Gunakan &:

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

&melewati nilai array sebagai referensi dan tidak membuat instance variabel baru. Jadi, jika Anda mengubah referensi, nilai aslinya akan berubah.

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

Sunting 2018
Jawaban ini tampaknya disukai oleh banyak orang di internet, itulah sebabnya saya memutuskan untuk menambahkan lebih banyak informasi dan kata-kata kehati-hatian.
Walaupun pass by reference dalam foreach(atau fungsi) adalah solusi yang bersih dan singkat, bagi banyak pemula ini mungkin merupakan perangkap yang berbahaya.

  1. Loop di PHP tidak memiliki cakupannya sendiri. - @Mark Amery

    Ini bisa menjadi masalah serius ketika variabel sedang digunakan kembali dalam cakupan yang sama. Pertanyaan SO lainnya menggambarkan dengan baik mengapa itu bisa menjadi masalah.

  2. Karena foreach bergantung pada pointer array internal di PHP 5, mengubahnya dalam loop dapat menyebabkan perilaku yang tidak terduga. - Dokumentasi PHP untuk foreach

    Membatalkan pengaturan catatan atau mengubah nilai hash (kunci) selama iterasi pada loop yang sama dapat menyebabkan perilaku yang berpotensi tidak terduga di PHP <7. Masalahnya menjadi semakin rumit ketika array itu sendiri adalah referensi.

  3. Performa pemain depan.
    Secara umum PHP lebih suka nilai berdasarkan karena fitur copy-on-write. Ini berarti bahwa secara internal PHP tidak akan membuat data duplikat kecuali salinannya perlu diubah. Masih bisa diperdebatkan apakah pass by reference in foreachakan menawarkan peningkatan kinerja. Karena selalu demikian, Anda perlu menguji skenario spesifik Anda dan menentukan opsi mana yang menggunakan lebih sedikit memori dan waktu cpu. Untuk informasi lebih lanjut lihat posting SO yang ditautkan di bawah ini oleh NikiC.

  4. Keterbacaan kode.
    Membuat referensi dalam PHP adalah sesuatu yang cepat hilang kendali. Jika Anda seorang pemula dan tidak memiliki kendali penuh atas apa yang Anda lakukan, yang terbaik adalah menjauh dari referensi. Untuk informasi lebih lanjut tentang &operator, lihat panduan ini: Referensi - Apa arti simbol ini dalam PHP?
    Bagi mereka yang ingin mempelajari lebih lanjut tentang bagian bahasa PHP ini : Penjelasan Referensi PHP

Penjelasan teknis yang sangat bagus dari @NikiC tentang logika internal dari PHP foreach loop:
Bagaimana cara kerja PHP 'foreach'?


Selain masalah yang tercantum, saya sarankan menambahkan unset($value);setelah foreachbraket penutupan, untuk memastikan variabel referensi-by tidak lagi tersedia setelah iterasi. 3v4l.org/2V2AQ
fyrye

15

Gunakan foreach($fields as &$field){- jadi Anda akan bekerja dengan array asli.

Berikut ini lebih lanjut tentang melewati referensi.


@RBA mohon merujuk pada jawaban di atas - mereka memiliki lebih banyak detail dan pembaruan - Saya belum menggunakan php untuk sementara waktu sekarang, jadi tidak mengetahui adanya pembaruan tentang ini
k102

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

Inilah yang akan saya sarankan lewat referensi


Teknik ini digunakan untuk mengubah nilai variabel asli. karena PHP mendukung Pass by Value Technique. Kita perlu menambahkan karakter '&' di depan variabel untuk menyatakan nilai yang akan dilewatkan dengan referensi
Sagar Kadam

1
Lalu mengapa masih kembali $fields?
MAZux

Ini adalah jawaban terburuk dari 3 yang disarankan. Untuk siapa pun yang menemukan jawaban ini, jangan mendesain fungsi Anda untuk mengubah data yang ada dan mengembalikannya. Untuk penulis asli: Anda belum memberikan penjelasan mengapa solusi ini akan lebih baik daripada yang lain, atau bagaimana cara kerjanya sama sekali ..
Dharman

-6

Coba ini

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

3
Jangan lakukan ini. Saya dapat melihat setidaknya dua hal yang salah dengan kode Anda: menetapkan $ field tidak berfungsi (array $ fields tidak pernah dimodifikasi ketika Anda melakukan ini), dan return $ field mengembalikan bidang singular, bukan array.
Staplerfahrer
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.