Вопрос по работе foreach в php

Есть цикл for:

for($i = 0; $i < count($passengers); $i++) {
        $passenger[] = [
            'id' => $passengers[$i]['id'],
            'first_name' => $passengers[$i]['first_name'],
            'last_name' => $passengers[$i]['last_name'],
            'birth_date' => $passengers[$i]['birth_date'],
            'document_number' => $passengers[$i]['document_number'],
            'place_from' => $passengers[$i]['place_from'],
            'flace_back' => $passengers[$i]['flace_back']
        ];
}

Он перебирает массив $passengers, состоящий из двух массивов и записывает нужные данные в $passenger. Если выведем, получается такой результат: (данные ниже в json).

[
{
    "id": "11",
    "first_name": "Ivan",
    "last_name": "Ivanov",
    "birth_date": "1990-02-20",
    "document_number": "1234567890",
    "place_from": null,
    "flace_back": null
},
{
    "id": "12",
    "first_name": "Ivan",
    "last_name": "Gorbunov",
    "birth_date": "1990-03-20",
    "document_number": "1224567890",
    "place_from": null,
    "flace_back": null
}
]

Массив перезаписывается для того, чтобы отсеять ненужные поля, пришедшие из базы.

Вопрос: Как добиться такого же эффекта через foreach? И вообще можно ли?

Я пробовал так:

foreach($passengers as $passenger) {
    $passenger = [
        'id' => $passenger['id'],
        'first_name' => $passenger['first_name'],
        'last_name' => $passenger['last_name'],
        'birth_date' => $passenger['birth_date'],
        'document_number' => $passenger['document_number'],
        'place_from' => $passenger['place_from'],
        'flace_back' => $passenger['flace_back']
    ];
}

Но тут в итоге записывается только последний пассажир и выводит:

{
"id": "12",
"first_name": "Ivan",
"last_name": "Gorbunov",
"birth_date": "1990-03-20",
"document_number": "1224567890",
"place_from": null,
"flace_back": null
}

Что в принципе логично. Но вот только как добиться первого результата через foreach?

Пробовал также добавлять скобы в фориче [] как в for, вот:

foreach($passengers as $passenger) {
    $passenger**[]** = [
        'id' => $passenger['id'],
        'first_name' => $passenger['first_name'],
        'last_name' => $passenger['last_name'],
        'birth_date' => $passenger['birth_date'],
        'document_number' => $passenger['document_number'],
        'place_from' => $passenger['place_from'],
        'flace_back' => $passenger['flace_back']
    ];
}

Но выводится вообще абра-кадабра:

{
"id": "12",
"booking_id": "10",
"first_name": "Ivan",
"last_name": "Gorbunov",
"birth_date": "1990-03-20",
"document_number": "1224567890",
"place_from": null,
"place_back": null,
"created_at": null,
"updated_at": null,
"0": {
    "id": "12",
    "first_name": "Ivan",
    "last_name": "Gorbunov",
    "birth_date": "1990-03-20",
    "document_number": "1224567890",
    "place_from": null,
    "flace_back": null
}

}

Заранее благодарю.


Ответы (1 шт):

Автор решения: Michael

Можно использовать ссылку (&) на элемент массива, чтобы записать его:

foreach($passengers as &$passenger) {
    $passenger = [
        'id' => $passenger['id'],
        ...
    ];
}

Если вам нужно оставить в элементах только определённые ключи, можно явно их указать и использовать array_filter:

$public_keys = [
    'id',
    'first_name',
    'last_name',
    'birth_date',
    'document_number',
    'place_from',
    'flace_back',
];

foreach ($passengers as &$passenger) {
    $passenger = array_filter($passenger, function ($key) use ($public_keys) {
        return in_array($key, $public_keys);
    }, ARRAY_FILTER_USE_KEY);
}

Как подсказали в комментариях, «правильнее» вместо ссылок перед циклом определить новый массив и записывать значения уже в него:

$public_keys = [
    'id',
    ...
];

$filtered_passengers = [];

foreach ($passengers as $passenger) {
    $filtered_passengers[] = array_filter($passenger, function ($key) use ($public_keys) {
        return in_array($key, $public_keys);
    }, ARRAY_FILTER_USE_KEY);
}

И дальше использовать уже $filtered_passengers

→ Ссылка