Retrieve elements from data table and sum the same elements - php

I have the table "orders" from woocommerce.
I filtered and get sorted the elements by status with GET request.
The results are copied to a JSON file.
So now, I want to find the elements with the same "product_id" and their values and summarize them to display in screen so I can print them.
For example:
"product_id": 45329,
"variation_id": 0,
"quantity": 1
"product_id": 48911,
"variation_id": 0,
"quantity": 1,
"product_id": 45329,
"variation_id": 0,
"quantity": 1
The output that I want to achieve is this:
45329 quantity 2
48911 quantity 1
Thanks!

Decode JSON with json_decode() and make calculations. Next example uses simplified JSON data, which I think matches the format from WooCommerce (I guess this format is from list orders GET request):
<?php
# JSON
$json = '
[
{
"id": 727,
"line_items": [
{
"id": 315,
"name": "Woo Single #1",
"product_id": 93,
"variation_id": 0,
"quantity": 2,
"tax_class": "",
"subtotal": "6.00",
"subtotal_tax": "0.45",
"total": "6.00",
"total_tax": "0.45",
"taxes": [
{
"id": 75,
"total": "0.45",
"subtotal": "0.45"
}
],
"meta_data": [],
"sku": "",
"price": 3
},
{
"id": 316,
"name": "Ship Your Idea – Color: Black, Size: M Test",
"product_id": 22,
"variation_id": 23,
"quantity": 1,
"tax_class": "",
"subtotal": "12.00",
"subtotal_tax": "0.90",
"total": "12.00",
"total_tax": "0.90",
"taxes": [
{
"id": 75,
"total": "0.9",
"subtotal": "0.9"
}
],
"meta_data": [
{
"id": 2095,
"key": "pa_color",
"value": "black"
},
{
"id": 2096,
"key": "size",
"value": "M Test"
}
],
"sku": "Bar3",
"price": 12
}
]
}
]';
$input = json_decode($json, true);
# Sum
$output = array();
foreach ($input as $order) {
foreach ($order["line_items"] as $item) {
$product_id = $item['product_id'];
$quantity = $item['quantity'];
if (!array_key_exists($product_id, $output)) {
$output[$product_id] = 0;
}
$output[$product_id] += $quantity;
}
}
#Output
foreach ($output as $key => $value) {
echo $key.' quantity '.$value.'<br>';
}
?>
Output:
93 quantity 2
22 quantity 1

Related

Is it possible extract and merge a single json object from multiple json files?

Sorry for the confusing title. I am having a bit of an issue here merging some JSON files. I need to merge all the products into one array in a separate file.
I have a directory full of same structured json files. I am using glob to select all files and decode->append-->encode json files into one large file.
Here is my code:
<?php
$files = glob("*.json");
$newDataArray = [];
foreach($files as $file){
$thisData = file_get_contents($file);
$thisDataArray = json_decode($thisData);
$newDataArray[] = $thisDataArray;
}
$newDataJSON = json_encode($newDataArray);
file_put_contents("merged.json",$newDataJSON);
?>
Now, the above code seems to work great but I only want to extract all the products.
Quick example of what I need to achieve.
File1.json
{
"status": true,
"user": {
"username": "sally",
"avatar": "/images/default-avatar.png",
"products": [
{
"id": "35vR4hr",
"title": "Picture 1",
"image": null,
"quantity": {
"min": 1,
"max": 1
},
"price": 2,
"currency": "CAD",
"stock_warning": 1,
"type": "service",
"stock": 9223372036854776000
},
{
"id": "na1Id4t",
"title": "Picture 2",
"image": null,
"quantity": {
"min": 1,
"max": 1
},
"price": 0.75,
"currency": "CAD",
"stock_warning": 3,
"type": "service",
"stock": 9223372036854776000
}
]
}
}
File2.json
{
"status": true,
"user": {
"username": "Jessica",
"avatar": "/images/default-avatar.png",
"products": [
{
"id": "wjiefi94",
"title": "Picture 3",
"image": null,
"quantity": {
"min": 1,
"max": 1
},
"price": 2,
"currency": "CAD",
"stock_warning": 1,
"type": "service",
"stock": 9223372036854776000
},
{
"id": "n34idwi",
"title": "Picture 4",
"image": null,
"quantity": {
"min": 1,
"max": 1
},
"price": 0.75,
"currency": "CAD",
"stock_warning": 3,
"type": "service",
"stock": 9223372036854776000
}
]
}
}
I want the data to be merged like:
merged.json
{
"products": [
{
"id": "wjiefi94",
"title": "Picture 1",
"image": null,
"quantity": {
"min": 1,
"max": 1
},
"price": 2,
"currency": "CAD",
"stock_warning": 1,
"type": "service",
"stock": 9223372036854776000
},
{
"id": "n34idwi",
"title": "Picture 2",
"image": null,
"quantity": {
"min": 1,
"max": 1
},
"price": 0.75,
"currency": "CAD",
"stock_warning": 3,
"type": "service",
"stock": 9223372036854776000
},
{
"id": "n34idwi",
"title": "Picture 3",
"image": null,
"quantity": {
"min": 1,
"max": 1
},
"price": 0.75,
"currency": "CAD",
"stock_warning": 3,
"type": "service",
"stock": 9223372036854776000
},
{
"id": "n34idwi",
"title": "Picture 4",
"image": null,
"quantity": {
"min": 1,
"max": 1
},
"price": 0.75,
"currency": "CAD",
"stock_warning": 3,
"type": "service",
"stock": 9223372036854776000
}
]
}
I hope this makes sense. I feel like I have hit a dead end here. Any help is greatly appreciated.
would it be possible for you to call an external tool like "jq"? handling json (just like csv), especially with many files, is not something you should be doing manually.
btw, your example does not have commas between products 2 and 3 and 3 and 4.
Your new code on line 5 should probably read like this with the array brackets? Otherwise you are overwriting the contents of the last files:
$thisDataArray[] = json_decode($thisData);
And why are you merging products from Sally and Jessica into the same user? Maybe you can just extract all the products objects into one file?
More of a code review than an answer, hope it helps ;)

Pull nested JSON data using foreach loop in php

I want to pull data from below JSON format using PHP (foreach loop).
User detail is correspondence to house detail and house detail correspondence to individual meter reading.
I want to show Username, Device_No and all meter_detail field. Please help me out.
{
"id": 7,
"Username": "user",
"Housename": "Leela",
"Houses_list": [{
"id": 1,
"Device_No": 1111,
"meter_detail": [{
"id": 1,
"flow": 12,
"date": "2020-02-13T12:05:14.709Z",
"opening": 5,
"volume": 1234
},
{
"id": 2,
"flow": 32,
"date": "2020-02-13T12:05:26.821Z",
"opening": 2,
"volume": 1235
}
]
},
{
"id": 2,
"Device_No": 231,
"meter_detail": [{
"id": 3,
"flow": 78,
"date": "2020-02-13T12:05:41.331Z",
"opening": 5,
"volume": 7854
}]
}
]
}
You need to convert the JSON to an array by using json_decode(). Then a couple of foreach loops would do work for you:
<?php
$json = '{
"id": 7,
"Username": "user",
"Housename": "Leela",
"Houses_list": [{
"id": 1,
"Device_No": 1111,
"meter_detail": [{
"id": 1,
"flow": 12,
"date": "2020-02-13T12:05:14.709Z",
"opening": 5,
"volume": 1234
},
{
"id": 2,
"flow": 32,
"date": "2020-02-13T12:05:26.821Z",
"opening": 2,
"volume": 1235
}
]
},
{
"id": 2,
"Device_No": 231,
"meter_detail": [{
"id": 3,
"flow": 78,
"date": "2020-02-13T12:05:41.331Z",
"opening": 5,
"volume": 7854
}]
}
]
}';
$input = json_decode($json, true);
echo 'Username: '.$input['Username'].'<br>';
foreach ($input['Houses_list'] as $device){
echo '<br>Device No: '.$device['Device_No'].'<br>';
foreach ($device['meter_detail'] as $metrics){
echo '<table style="border: 1px solid black">';
foreach ($metrics as $key => $metric){
echo '<tr><td>'.$key.'</td><td>'.$metric.'</td></tr>';
}
echo '</table>';
}
}
?>
Output:

Laravel : How do I return parent > child relationship from same table

I have a 3 tables product, category, attributes. In attributes table there is parent_id used for sub-attributes in a same table.Using loop I get a data.
My code :
$productDetails = Product::with('categories')->get();
foreach ($productDetails as $key => $value) {
foreach ($value->categories as $key => $value) {
$attributes = Attribute::where('product_id',$value->product_id)->where('category_id',$value->id)->where('parent_id',Null)->get();
$value->Attributes = $attributes;
foreach ($attributes as $key => $value) {
$subAttributes = Attribute::where('parent_id', $value->id)->get();
$value->subAttributes = $subAttributes;
}
}
}
Output :
{
"productDetails": [
{
"id": 1,
"title": "Small Size Diamond",
"icon": null,
"status": "Active",
"categories": [
{
"id": 1,
"product_id": 1,
"title": "Sieve Size",
"status": "Active",
"sort_order": 1,
"Attributes": [
{
"id": 1,
"product_id": 1,
"category_id": 1,
"parent_id": null,
"title": "- 2.0",
"status": "Active",
"sort_order": 1,
"subAttributes": [
[
{
"id": 9,
"product_id": 1,
"category_id": 1,
"parent_id": 1, // Attributes table ID
"title": "+ 0000 - 000",
"status": "Active",
"sort_order": 1
},
{
"id": 10,
"product_id": 1,
"category_id": 1,
"parent_id": 1, // Attributes table ID
"title": "+ 000 - 00",
"status": "Active",
"sort_order": 2
}
]
]
}
]
}
]
}
]}
The problem is in first product I gt completed response but in other prodcts in loop I do not get subAttributes data. How can i do this?
Simple, please do not use same variable name in all foreach loop,
Your code should like following
$productDetails = Product::with('categories')->get();
foreach ($productDetails as $pro_key => $pro_value) {
foreach ($pro_value->categories as $cat_key => $cat_value) {
$attributes = Attribute::where('product_id',$cat_value->product_id)->where('category_id',$cat_value->id)->where('parent_id',Null)->get();
$cat_value->Attributes = $attributes;
foreach ($attributes as $att_key => $att_value) {
$subAttributes = Attribute::where('parent_id', $att_value->id)->get();
$att_value->subAttributes = $subAttributes;
}
}
}

Sum all item prices and multiplication them to them pivot table in laravel

I have a problem to solve here, I need to calculate total price of cart.
I add multiple products to my cart. They have prices and quantities in pivot.
Something like this:
{
"id": 1,
"user_id": "1",
"status": "closed",
"total_price": "100",
"created_at": "2017-07-22 06:06:17",
"updated_at": "2017-07-22 08:02:04",
"skues": [
{
"id": 1,
"title": "مربعی ۵x2",
"description": "مربعی ۵x2، مربعی ۵x2 است.",
"sku_card_theme": "#2222",
"visible": "hidden",
"price": "50",
"category_id": "2",
"created_at": "2017-07-22 06:50:02",
"updated_at": "2017-07-22 07:16:33",
"pivot": {
"cart_id": "1",
"sku_id": "1",
"feature": "{\"size\": \"big\",\"quantity\": 2}",
"image_path": "images/users5e51d08006fed056b19db7d041d5688f.jpeg",
"id": 1
}
},
{
"id": 1,
"title": "مربعی ۵x2",
"description": "مربعی ۵x2، مربعی ۵x2 است.",
"sku_card_theme": "#2222",
"visible": "hidden",
"price": "50",
"category_id": "2",
"created_at": "2017-07-22 06:50:02",
"updated_at": "2017-07-22 07:16:33",
"pivot": {
"cart_id": "1",
"sku_id": "1",
"feature": "{\"size\": \"big\",\"quantity\": 2}",
"image_path": "images/users/416e9f70dee50547866e9e89696d16e3.jpeg",
"id": 2
}
},
{
"id": 3,
"title": "تقویم دیواری",
"description": "سشیشیش",
"sku_card_theme": "#2222",
"visible": "hidden",
"price": "25",
"category_id": "3",
"created_at": "2017-07-22 07:56:45",
"updated_at": "2017-07-22 07:56:45",
"pivot": {
"cart_id": "1",
"sku_id": "3",
"feature": "{\"size\": \"big\",\"quantity\": 2}",
"image_path": "images/users/273c1f5e3324815a82060931f30ead97.jpeg",
"id": 3
}
},
]
I want to sum all skues prices here and multiply them by their pivot quantity, I tried some methods like foreach, laravel collection each and other approaches...
But I have got no answer.
my code sample:
$skues->each(function ($item) {
$quantity = json_decode($item->pivot->feature)->quantity;
$price = $item->price;
});
$total_price = $quantity * $price;
It has an error, telling me that $quantity and $price are undefined variables.
and this is my foreach method:
foreach ($cart->skues as $skue) {
$quantity = json_decode($skue->pivot->feature)->quantity;
$total_price = $skue->price * $quantity;
}
$cart->update([
'total_price' => $total_price,
]);
Thank you.
I fixed it finally:
public function total($cart) {
$cart->update([
'total_price' => NULL,
]);
$cart->skues->each(function ($item) {
$user = auth()->user();
$quantity = json_decode($item->pivot->feature)->quantity;
$price = $item->price;
$total_price = $price * $quantity;
$user->cart->update([
'total_price' => $total_price + $user->cart->total_price,
]);
});
}

Laravel 5.3 - Merge array based on 2 matching keys?

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
}
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
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.

Categories