0

Given the following two arrays, how can they be merged efficiently to result in the third array? productData

$productData =
[
  {
    "product_id": 4,
    "type": "electronic",
    "name": "monitor",
    "specs": {
      "HDMI": true,
      "VGA": false
    }
  },
  {
    "product_id": 5,
    "type": "electronic",
    "name": "HDMI cable",
    "specs": {
      "length": "3ft"
    }
  },
  {
    "product_id": 6,
    "type": "kitchen",
    "name": "spoon"
  }
]

products

$products =
{
  "products": 3,
  "per_page": 10,
  "current_page": 1,
  "data": [
    {
      "id": 4,
      "product_type": "electronic",
      "product_id": 6
    },
    {
      "id": 6,
      "type": "electronic",
      "product_id": 5
    },
    {
      "id": 9,
      "type": "kitchen",
      "product_id": 4
    }
  ]
}

productsFinal ($productData merged into $products - based on matching combo of product_id/product_id and type/product_type)

$productsFinal = 
{
  "products": 3,
  "per_page": 10,
  "current_page": 1,
  "data": [
    {
      "id": 4,
      "product_type": "electronic",
      "product_id": 6,

      // How to merge product data and wrap with "data" key
      "data": {
        "product_id": 6,
        "type": "kitchen",
        "name": "spoon"
      }

    },
    {
      "id": 6,
      "type": "electronic",
      "product_id": 5,

      // How to merge product data and wrap in "data" key
      "data": {
        "product_id": 5,
        "type": "electronic",
        "name": "HDMI cable",
        "specs": {
          "length": "3ft"
        }
      }
    },
    {
      "id": 9,
      "type": "kitchen",
      "product_id": 4,

      // How to merge product data and wrap in "data" key
      "data": {
        "product_id": 6,
        "type": "kitchen",
        "name": "spoon"
      }
    }
  ]
}

I tried different things for the outcome in a foreach loop but still cannot get it to render as intended:

foreach($productData as $productDataItem) {
  // when $productDataItem.product_id == $product.product_id && $productDataItem.type == $product.product_type
  // move the matching $productDataItem object into matching $product object, wrapped in a new "data" key
}
3
  • 1
    This is not PHP code here. What have you tried to solve this yourself? Commented Apr 5, 2017 at 23:57
  • It is in PHP (Laravel) where I have this issue, that is what a laravel collection outputs. I tried a few different ways, but wasn't able to accomplish the format of the third array, and it is taking me way too long to implement. That's why I posted the question under php/laravel, as someone who knows laravel may know how to do this. Commented Apr 6, 2017 at 0:35
  • Are you trying to make a JSON response for an API? If yes, I may have a solution. Commented Apr 7, 2017 at 23:35

2 Answers 2

3
+50

I don't know Laravel too well. However you can join your data objects quite easily:

<?php
$productData = json_decode('[
  {
    "product_id": 4,
    "type": "electronic",
    "name": "monitor",
    "specs": {
      "HDMI": true,
      "VGA": false
    }
  },
  {
    "product_id": 5,
    "type": "electronic",
    "name": "HDMI cable",
    "specs": {
      "length": "3ft"
    }
  },
  {
    "product_id": 6,
    "type": "kitchen",
    "name": "spoon"
  }
]');

$products = json_decode('{
  "products": 3,
  "per_page": 10,
  "current_page": 1,
  "data": [
    {
      "id": 4,
      "type": "electronic",
      "product_id": 6
    },
    {
      "id": 6,
      "type": "electronic",
      "product_id": 5
    },
    {
      "id": 9,
      "type": "kitchen",
      "product_id": 4
    }
  ]
}');

// combine both data objects 

foreach($products->data As &$p) {
    foreach($productData As $d) {
        if(property_exists($p, "product_id") && property_exists($d, "product_id") && property_exists($p, "type") && property_exists($d, "type")) {
            if($p->product_id==$d->product_id && $p->type==$d->type) {
                //$p = (object) array_merge((array) $p, (array) $d);
                $p->data = $d; // updated answer
                continue;
            }
        }
    }
}

echo("<pre>");
echo json_encode($products, JSON_PRETTY_PRINT);


?>

You can test the code here: http://sandbox.onlinephpfunctions.com/code/98a50c35ee32c30f0d2be1661f7afb5895174cbe Update: http://sandbox.onlinephpfunctions.com/code/aeebfdcf4f4db5e960260e931982570cfed19e0e

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for this, it is really close to the final output, but I really am trying to get the exact syntax in $productsFinal (my final output), outputted from your sandbox to match the final output. Currently there are 2 differences, the "data": [ and the fact that it adds the index to each product. Any idea how to change your logic to match $productsFinal?
0

I would suggest to check this package dingo/api. I assume you want to display some kind of JSON response. Take a look at Transformers. You can do something like this :

<?php
namespace App\Http\Transformers;
use App\Http\Controllers\ProductData;
use League\Fractal\TransformerAbstract;

class ProductsDataTransformer extends TransformerAbstract
{
    /**
     * Turn this item object into a generic array
     *
     * @return array
     */
    public function transform(ProductData $productdata)
    {
        return [
            'id' => $productdata->id,
            'product_type' => $productdata->product_type,
            'product /*or data*/' => Product::find($productdata->product_id),
        ];
    }

}

This would find the product by it's ID and look like this :

{
  "id": 4,
  "product_type": "electronic",
  "product" {
    "product_id": 6,
    "type": "kitchen",
    "name": "spoon"
  },
},

You can then also create a transformer for Product to take care of your specs attribute to do the same thing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.