Readability of array_* vs foreach in PHP for filtering and extracting With functional programming all the rage, I feel I should be using PHP's array_* functions more.  But when I compare these two identical implementations, I can't help but think foreach is more readable.  Am I just being a dinosaur?

(The foreach implementation takes 1/4 the time, but performance is not of interest for me here, now).

Which do you like better and why?

// Create $attendeeNames from $allPeople who are in the $selectedPeople array
foreach ($allPeople as $person) {
    $id = $person['id'];
    $name = $person['name'];
    if (in_array($id, $selectedPeople)) {
        $attendeeNames[] = $name;
    }
}




// Same, but with array functions
$attendees = array_filter($allPeople, 
    function($item) use ($selectedPeople) {
        $id = $item['id'];
        return in_array($id, $selectedPeople);
    });

$attendeeNames = array_map(
    function($attendee) {
        return $attendee['name'];
    }, $attendees);
If your functional code is a filter and then a map it's likely a good candidate for array_reduce.

One of the main advantages of a function first approach here is that you can name the inner operation (the filtering operation), but using a closure (or a foreach) robs of you of a name (which could have been used to signal intent) and often robs of us of reuse so wrap the Closure in a named, reusable context (another named function).

A named function will also allow us to pre-inject the variable $selectedPeople into the Closure before array_ functions interact with the Closure inside.

See: http://www.phptherightway.com/pages/Functional-Programming.html for more information on this.

Now we can type hint all the inputs.

function selected_attendee_names(array $selectedPeople) : Closure {
  return function (array $attendeeNames, array $attendee) use ($selectedPeople) : array {
    $isSelectedAttendee = in_array($attendee['id'], $selectedPeople);
    $isSelectedAttendee ? $attendeeNames[] = $attendee['name'] : NULL;
    return $attendeeNames;
  };
}

$attendeeNames = array_reduce($allPeope, selected_attendee_names($selectedPeople), []);


Another approach that could have increased reuse is to array_filter and then use array_column.

function is_selected_attendee(array $selectedPeople) : Closure {
  return function (array $attendee) use ($selectedPeople) : bool {
      $isSelectedAttendee = in_array($attendee['id'], $selectedPeople);
      return $isSelectedAttendee;
  };
}

$selected_attendees = array_filter($allPeople, is_selected_attendee($selectedPeople));
$selected_attendees_names = array_column($selected_attendees, 'name');


Generally speaking I'd prefer the bottom approach because you'll usually find you want to do something else with the selected attendees later in your program.