Search code examples
phpimplodearray-map

Consolidating multiple array_map functions into one


I'm using Laravel and in my blade template I have several calls to array_map() in order to stringify an array with the & delimiter and for the sake of cleanliness I'm trying to consolidate these calls into one where the logic looks like this:

@foreach ($draws as $draw)
    @php
        $team = $draw->team;
        $participants = array_filter($team ? [$team->partner_one ?: false, $team->partner_two ?: false] : [$draw->user]);
    @endphp
    <tr>
        <td>{{ $draw->event->name }}</td>
        <td>{{ $draw->event_activity->activity_name }}</td>
        <td>{{ $draw->id }}</td>
        <td>{{ $draw->draw_order }}</td>
        <td>
            {{implode(' & ', array_map(function($v, $k){
                return $v->meta('state_back_number');
            }, $participants, array_keys($participants)))}}
        </td>
        <td>
            {{implode(' & ', array_map(function($v, $k){
                return $v->last_name.', '.$v->first_name;
            }, $participants, array_keys($participants)))}}
        </td>
        <td>
            {{implode(' & ', array_map(function($v, $k){
                return $v->address(true)->get()[0]->city.', '.$v->address(true)->get()[0]->state;
            }, $participants, array_keys($participants)))}}
        </td>
        <td>
            {{implode(' & ', array_map(function($v, $k){
                return $v->meta('section');
            }, $participants, array_keys($participants)))}}
        </td>
        <td>
        </td>
        <td>{{$draw->payout_final ? 'Yes' : 'No'}}</td>
    </tr>
@endforeach

Something I had tried was on the line directly below the $participants declaration

$user_data = array_map(function($v, $k){
  return ['state_back_number' => $v->meta('state_back_number'), 'name' => $v->last_name.', '.$v->first_name, 'hometown' => $v->address(true)->get()[0]->city.', '.$v->address(true)->get()[0]->state];
}, $participants, array_keys($participants));

And ideally it would've resulted in me being able to call implode() with the respective array key like so implode(' & ', $user_data['state_back_number']); but instead the array I get is jumbled and and has unnecessary indexes.

My question is: how do I combine these array_map() calls to create a single array which I can call implode on to create the desired string and save 10 or so lines of code?


Solution

  • You can call array_map() once and use it to populate four more arrays: $state_back_numbers, $last_names, $addresses, and $sections. (It would probably be smarter to use another method to loop through two arrays at once but it was easiest to do it the way I did.)

    After you've populated those four arrays, you can implode() them.

    @foreach ($draws as $draw)
        @php
            $team = $draw->team;
            $participants = array_filter($team ? [$team->partner_one ?: false, $team->partner_two ?: false] : [$draw->user]);
            
            $state_back_numbers = [];
            $last_names = [];
            $addresses = [];
            $sections = [];
    
            array_map(function($v, $k) use (&$state_back_numbers, &$last_names, &$addresses, &$sections) {
                  $state_back_numbers[] = $v->meta('state_back_number');
                  $last_names[] = $v->last_name.', '.$v->first_name;
                  $addresses[] = $v->address(true)->get()[0]->city.', '.$v->address(true)->get()[0]->state;
                  $sections[] = $v->meta('section');
                }, $participants, array_keys($participants));
        @endphp
        <tr>
            <td>{{ $draw->event->name }}</td>
            <td>{{ $draw->event_activity->activity_name }}</td>
            <td>{{ $draw->id }}</td>
            <td>{{ $draw->draw_order }}</td>
            <td>
                {{implode(' & ', $state_back_numbers)}}
            </td>
            <td>
                {{implode(' & ', $last_names)}}
            </td>
            <td>
                {{implode(' & ', $addresses}}
            </td>
            <td>
                {{implode(' & ', $sections}}
            </td>
            <td>
            </td>
            <td>{{$draw->payout_final ? 'Yes' : 'No'}}</td>
        </tr>
    @endforeach