Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

talel's avatar
Level 16

Map label to data from API response

Hello, I have API results that look something like that:

Illuminate\Support\Collection {#1282
  #items: array:35 [
    "id" => "05c327f4-5sdb-498c-b641-337ecf66ed57"
    "type" => 320
    "number" => 60013
    "documentDate" => "2021-03-11"
    "creationDate" => 1615482203
    "amountDueVat" => 170
    "amountExemptVat" => 0
    "vat" => 28.9
    "amount" => 198.9
    "amountOpened" => 0
    "client" => array:12 [
      "id" => "55d63e90-cf7e-4bb8-9b1f-7400as6094f"
      "name" => "Jow D"
      "department" => ""
      "address" => "Address"
      "city" => "City"
      "zip" => "1234567"
      "country" => "IL"
      "phone" => "7237918237"
      "fax" => ""
      "mobile" => ""
      "emails" => array:1 [
        0 => "[email protected]"
      ]
      "self" => false
    ],
   "payment" => array:1 [
      0 => array:18 [
        "id" => "af5f80d8-e882-4668-bc11-df75958a9323e"
        "date" => "2021-03-11"
        "type" => 3
        "status" => 1
        "price" => 198.9
        "currency" => "ILS"
        "currencyRate" => 1
        "paymentStatus" => 0
        "ref" => []
        "cancellable" => false
        "cardType" => 2
        "cardNum" => "0000"
        "dealType" => 1
        "numPayments" => 1
        "payment" => 1
        "name" => "כרטיס אשראי"
        "description" => "ויזה 0000 / רגיל"
        "amount" => 198.9
      ]
}

And I would like to map over this collection and convert let's say

  "type" => 320

to

  "type" => 'Some String'

Based on an array of conversation:

	return [
		'320' => 'Some String'
	];

And with one level from the results, I can accomplish that, but then if an item from the map function is an array, it can get a bit tricky. Any suggestion on how to go about it?

$results->map(function($item, $key) use ($array){
  
  foreach($array as $typeKey => $typeValue){
  	return $typeKey === $item ? $typeValue : $item;
  }
  
})->toArray();

I was thinking of deligating to a separate function to check for each item from the map function , and then check is that item is an array, in that case, call the same function again and collapse the array to one dimension.

0 likes
7 replies
talel's avatar
Level 16

Thanks, it is a way to go over it but it is required prior knowledge of how deep is the nested array. I would prefer to call again a method that would extract each array over and over.

talel's avatar
Level 16

Thanks for the comment.

To wrap the response back to the client I will use an API Resource.

I am still at the stage prior to it where I receive data from a request and need to convert some data in it to be readable from constants for instance:

	{
	"type" => 320
	}

Really mean for the client

	{	
	"type" => "Credit Card"
	}
jlrdw's avatar

but it is required prior knowledge of how deep is the nested array.

The format of an API should not be changing it should always be the same.

I wouldn't deal with one unless it did have the same structure each time.

For example I deal with bank data Imports for a non-profit, the structure is always the exact same.

What is the use case of:

  "type" => 'Some String'
talel's avatar
talel
OP
Best Answer
Level 16

Not the most elegant solution, but that's where I ended up:

    public function mapDocument($document, $attributes, $map)
    {
        return collect($document)->only($attributes)->map(function ($item, $key) use ($map) {
            return $this->mapper($item, $key, $map);
        });
    }

    protected function mapper($item, $key, $map = [])
    {
        if (! is_array($item) && Arr::has($map, $item)) {
            return $map[$item];
        }

        if (! is_array($item) && Arr::has($map, $key)) {
            if (is_array($map[$key])) {
                return $map[$key][$item];
            }
        }

        if (! is_array($item) && Arr::has($map, $key)) {
            return $map[$key];
        }

        if (is_array($item) && Arr::has($map, $key)) {
            $item = Arr::collapse($item);
            foreach ($item as $itemKey => $itemValue) {
                if (Arr::has($map[$key], $itemKey) && is_array($map[$key][$itemKey])) {
                    $item[$itemKey] = $map[$key][$itemKey][$itemValue];
                }
                if (Arr::has($map[$key], $itemKey) && ! is_array($map[$key][$itemKey])) {
                    $item[$itemKey] = $map[$key][$itemKey];
                }
            }

            return $item;
        } else {
            return $item;
        }

        if (is_array($item)) {
            foreach ($item as $itemKey => $itemValue) {
                return $this->mapper($itemValue, $itemKey, $map);
            }
        }

        return $item;
    }
MichalOravec's avatar

@talelmishali Your code could be just

public function mapDocument($document, $attributes, $map)
{
    return collect($document)->only($attributes)->map(function ($item) use ($map) {
        return $this->mapper($item, $map);
    });
}

protected function mapper($item, $map)
{
    if (! is_array($item) && Arr::has($map, $item)) {
        return $map[$item];
    }

    if (is_array($item)) foreach ($item as $key => $value) {
        if (Arr::has($map, $key)) {
            $item[$key] = is_array($map[$key]) ? $map[$key][$value] : $map[$key];

            return $item;
        }

        return $this->mapper($value, $map);
    }

    return $item;
}
1 like

Please or to participate in this conversation.