PHP foreach thay đổi giá trị mảng ban đầu


143

Tôi rất mới trong mảng đa chiều, và điều này đang làm tôi khó chịu.

Mảng của tôi như sau:

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

Sau đó, tôi có một chức năng kiểm tra nếu các đầu vào này được điền vào, nếu chúng được yêu cầu.

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

Bây giờ vấn đề của tôi là dòng này

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

Tôi muốn thay đổi nội dung của mảng ban đầu, vì tôi sẽ trả lại cái này, nhưng làm thế nào để tôi có được tên của mảng hiện tại (tên trong ví dụ này) trong vòng lặp foreach của tôi?



1
Bất kể bạn mới (hoặc đã từng như thế nào) - đây là thứ bạn có thể đọc từ tài liệu PHP: php.net/manual/en/control-strucenses.foreach.php
Nikolay Ivanov

Câu trả lời:


261

Trong PHP, chuyển qua tham chiếu ( &) là ... gây tranh cãi. Tôi khuyên bạn không nên sử dụng nó trừ khi bạn biết tại sao bạn cần nó và kiểm tra kết quả.

Tôi khuyên bạn nên làm như sau:

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

Vì vậy, về cơ bản sử dụng $fieldkhi bạn cần các giá trị và $fields[$key]khi bạn cần thay đổi dữ liệu.


Tốt đẹp, công trình này! Đã thử một cái gì đó như thế này đầu tiên, nhưng tôi đoán tôi đã làm hỏng một nơi nào đó :) Bây giờ tôi sẽ sử dụng ví dụ của bạn hàng ngàn lần và không bao giờ quên! :)
Jeppe

Vui vì nó đã giúp. Ngoài ra, tôi khuyên bạn nên đọc bài viết mà tôi đã liên kết, và cũng là tài liệu chính thức cho foreach ( php.net/manual/ro/control-strucenses.foreach.php )
Vlad Preda

4
Dòng dưới cùng: nếu bạn sẽ thay đổi mảng / biến - thì bạn nên sử dụng một tham chiếu. Nó nhanh hơn, sạch hơn và dễ đọc hơn.
Lulu

2
Tôi tò mò tại sao đi qua tham chiếu trong một foreachnên gây tranh cãi? Nó không giống như đó là một cuộc gọi chức năng với các tác dụng phụ ẩn hoặc bất cứ điều gì.
UncaAlby

1
Cảm ơn bạn đã nói rằng "vượt qua tham chiếu (&) là ... gây tranh cãi", thay vì "không vượt qua tham chiếu" hoặc "vượt qua tham chiếu là xấu xa". Ít có khả năng bắt đầu một cuộc chiến ngọn lửa. :)
Sean the Bean

162

Sử dụng &:

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

&chuyển một giá trị của mảng làm tham chiếu và không tạo ra một thể hiện mới của biến. Do đó, nếu bạn thay đổi tham chiếu, giá trị ban đầu sẽ thay đổi.

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

Chỉnh sửa 2018
Câu trả lời này dường như được rất nhiều người ưa thích trên internet, đó là lý do tại sao tôi quyết định thêm thông tin và lời cảnh báo.
Mặc dù vượt qua tham chiếu trong foreach(hoặc các chức năng) là một giải pháp sạch và ngắn, nhưng đối với nhiều người mới bắt đầu, đây có thể là một cạm bẫy nguy hiểm.

  1. Các vòng lặp trong PHP không có phạm vi riêng. - @Mark Amery

    Đây có thể là một vấn đề nghiêm trọng khi các biến đang được sử dụng lại trong cùng một phạm vi. Một câu hỏi SO khác minh họa độc đáo tại sao đó có thể là một vấn đề.

  2. Vì foreach dựa vào con trỏ mảng bên trong trong PHP 5, việc thay đổi nó trong vòng lặp có thể dẫn đến hành vi không mong muốn. - Tài liệu PHP cho foreach

    Việc không đặt bản ghi hoặc thay đổi giá trị băm (khóa) trong quá trình lặp trên cùng một vòng lặp có thể dẫn đến các hành vi bất ngờ tiềm ẩn trong PHP <7. Vấn đề thậm chí còn phức tạp hơn khi chính mảng là tham chiếu.

  3. Hiệu suất giảng dạy.
    Nói chung, PHP thích chuyển qua giá trị do tính năng sao chép trên ghi. Điều đó có nghĩa là PHP bên trong sẽ không tạo ra một dữ liệu trùng lặp trừ khi bản sao của nó cần được thay đổi. Người ta tranh cãi liệu việc thông qua tham chiếu trong foreachcó mang lại sự cải thiện hiệu suất hay không. Vì nó luôn luôn như vậy, bạn cần kiểm tra kịch bản cụ thể của mình và xác định tùy chọn nào sử dụng ít bộ nhớ và thời gian cpu hơn. Để biết thêm thông tin, xem bài viết SO được liên kết dưới đây bởi NikiC.

  4. Mã dễ đọc.
    Tạo các tài liệu tham khảo trong PHP là một cái gì đó nhanh chóng vượt ra khỏi tầm tay. Nếu bạn là người mới và không có toàn quyền kiểm soát những gì bạn đang làm, tốt nhất là tránh xa các tài liệu tham khảo. Để biết thêm thông tin về &toán tử, hãy xem hướng dẫn này: Tham khảo - Biểu tượng này có ý nghĩa gì trong PHP?
    Đối với những người muốn tìm hiểu thêm về phần này của ngôn ngữ PHP : Giải thích về Tài liệu tham khảo PHP

Một giải thích kỹ thuật rất hay của @NikiC về logic bên trong của các vòng lặp foreach PHP:
PHP 'foreach' thực sự hoạt động như thế nào?


Ngoài các vấn đề được liệt kê, tôi khuyên bạn nên thêm unset($value);sau dấu foreachngoặc đóng, để đảm bảo biến phụ tham chiếu không còn khả dụng sau khi lặp. 3v4l.org/2V2AQ
fyrye

15

Sử dụng foreach($fields as &$field){- vì vậy bạn sẽ làm việc với mảng ban đầu.

Đây là nhiều hơn về việc vượt qua bằng cách tham khảo.


@RBA vui lòng tham khảo các câu trả lời ở trên - họ có nhiều thông tin chi tiết và cập nhật hơn - Tôi đã không sử dụng php trong một thời gian, vì vậy không biết về bất kỳ cập nhật nào về điều này
k102

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

Đây là những gì tôi sẽ đề nghị vượt qua bằng cách tham khảo


Kỹ thuật này được sử dụng để thay đổi giá trị của biến ban đầu. kể từ khi PHP hỗ trợ Pass by Value Technique. Chúng ta cần thêm ký tự '&' vào trước biến để nêu giá trị đó được chuyển qua tham chiếu
Sagar Kadam

1
Vậy thì tại sao vẫn quay về $fields?
MAZux

Đây là câu trả lời tồi tệ nhất trong 3 gợi ý. Đối với bất kỳ ai vấp phải câu trả lời này, xin vui lòng không thiết kế các chức năng của bạn để thay đổi dữ liệu tại chỗ và trả lại nó. Đối với tác giả ban đầu: Bạn chưa cung cấp bất kỳ lời giải thích nào tại sao giải pháp này sẽ tốt hơn các giải pháp khác, hoặc cách thức hoạt động của nó ..
Dharman

-6

Thử cái này

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

3
Đừng làm điều này. Tôi có thể thấy ít nhất hai điều sai với mã của bạn: gán cho trường $ không hoạt động (mảng $ field không bao giờ được sửa đổi khi bạn làm điều này) và trả về trường $ trả về trường số ít, không phải mảng.
Staplerfahrer
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.