Laravel 5.5 Collection Partial Grouping - php

I need help on how to group the collection below by location and then by sizes:
[
{
"location_id": 1,
"location_address": "Some address",
"location_image": "https://some/image.url",
"size_id": 1,
"size_code": "S",
"available_boxes": 3
},
{
"location_id": 1,
"location_address": "Some address",
"location_image": "https://some/image.url",
"size_id": 2,
"size_code": "M",
"available_boxes": 4
},
{
"location_id": 1,
"location_address": "Some address",
"location_image": "https://some/image.url",
"size_id": 3,
"size_code": "L",
"available_boxes": 5
},
{
"location_id": 2,
"location_address": "Some other address",
"location_image": "https://some/other/image.url",
"size_id": 4,
"size_code": "XL",
"available_boxes": 10
}
]
Here is the expected result:
Really appreciate it, thanks in advance!

Might not be elegant, but this does the job:
$locations = $this->records->unique('location_id');
$transformed = [];
foreach ($locations as $location) {
$sizes = $this->records->whereStrict('location_id', $location->location_id);
$transformedSizes = [];
foreach ($sizes as $size) {
$transformedSizes[] = [
'id' => $size->size_id,
'code' => $size->size_code,
'available_boxes' => $size->available_boxes
];
};
$transformed[] = array_merge(
[
'id' => $location->location_id,
'address' => $location->location_address,
'image' => $location->location_image
],
[
'sizes' => $transformedSizes
]
);
}
return $transformed;

Related

Get parent and leaf ids from tree builder

I'm building a tree feature for my app. My tree has infinite level. I'm using this functions to build my tree (you can try my code here https://onlinephp.io/c/a50bc):
function build(array $array): array
{
if (count($array) <= 0) {
return [
'leaf_ids' => [],
'parent_ids' => [],
'tree' => [],
];
}
$groupByParent = [];
foreach ($array as $arr) {
$parent_id = empty($arr['parent_id']) ? 0 : $arr['parent_id'];
$groupByParent[$parent_id][] = $arr;
}
return makeTree($groupByParent, $groupByParent[0]);
}
function makeTree(array &$parentList, array $items): array
{
$tree = [];
$leafIds = [];
$parentIds = [];
foreach ($items as $item) {
if (isset($parentList[$item['id']])) {
$item['children'] = makeTree($parentList, $parentList[$item['id']])['tree'];
}
if (!isset($item['children'])) {
$leafIds[] = $item['id'];
} else {
$parentIds[] = $item['id'];
}
$tree[] = $item;
}
return ['tree' => $tree, 'leaf_ids' => $leafIds, 'parent_ids' => $parentIds];
}
$array = [
[
'id' => 1,
'parent_id' => NULL,
'value' => 'Hi',
],
[
'id' => 2,
'parent_id' => NULL,
'value' => 'Bye',
],
[
'id' => 3,
'parent_id' => 1,
'value' => 'Hey',
],
[
'id' => 4,
'parent_id' => 1,
'value' => 'Hello',
],
[
'id' => 5,
'parent_id' => 2,
'value' => 'Cya',
],
[
'id' => 6,
'parent_id' => 5,
'value' => 'Byebye',
],
];
print_r(json_encode(build($array), JSON_PRETTY_PRINT));
I'd like to get the list of leafs and parents but my code doesn't work at all. At the end I don't have all parents ids and my leaf_ids array is empty.
I got this output:
{
"tree": [
{
"id": 1,
"parent_id": null,
"value": "Hi",
"children": [
{
"id": 3,
"parent_id": 1,
"value": "Hey"
},
{
"id": 4,
"parent_id": 1,
"value": "Hello"
}
]
},
{
"id": 2,
"parent_id": null,
"value": "Bye",
"children": [
{
"id": 5,
"parent_id": 2,
"value": "Cya",
"children": [
{
"id": 6,
"parent_id": 5,
"value": "Byebye"
}
]
}
]
}
],
"leaf_ids": [],
"parent_ids": [
1,
2
]
}
The output that I want for leaf_ids is: "leaf_ids": [3,4,6] and for parent_ids: "parent_ids": [1,2,5].
How can I do to return leafs and parents list ?
When you make the recursive call, you will need to merge the results for leaf_ids and parent_ids obtained from sub tree results as well, like below:
<?php
if (isset($parentList[$item['id']])) {
$sub_tree = makeTree($parentList, $parentList[$item['id']]);
$item['children'] = $sub_tree['tree'];
$leafIds = array_merge($leafIds, $sub_tree['leaf_ids']);
$parentIds = array_merge($parentIds, $sub_tree['parent_ids']);
}
Online Demo

Order Array in groups

i have an array like this with position disordered i want to order the position like 123 123 123 12
[{
"id": 1,
"name": "ASDAS",
"position": 1,
},
{
"id": 2,
"name": "ASDAS",
"position": 1,
},
{
"id": 3,
"name": "ASDAS",
"position": 3,
},
{
"id": 4,
"name": "ASDAS",
"position": 2,
},
{
"id": 5,
"name": "ASDAS",
"position": 2,
},
{
"id": 6,
"name": "ASDAS",
"position": 3,
},
{
"id": 7,
"name": "ASDAS",
"position": 2,
},
{
"id": 8,
"name": "ASDAS",
"position": 1,
}
]
i want the order like that
[{
"id": 1,
"name": "ASDAS",
"position": 1,
},
{
"id": 4,
"name": "ASDAS",
"position": 2,
},
{
"id": 3,
"name": "ASDAS",
"position": 3,
},
{
"id": 2,
"name": "ASDAS",
"position": 1,
},
{
"id": 5,
"name": "ASDAS",
"position": 2,
},
{
"id": 6,
"name": "ASDAS",
"position": 3,
},
{
"id": 8,
"name": "ASDAS",
"position": 1,
},
{
"id": 7,
"name": "ASDAS",
"position": 2,
}
]
The below should do the trick. I assume your data is an array of objects.
First I order the array by ID and then seperate the items by group. Finally, I merge all the groups 1 item at a time. There is probably a better way to acheive what you are after but thought this might be a good starting point.
This will adapt to the max position value. For example, if one of the data items has a position of 4 you would end up with a position order: 1234 123 123 123 12... etc
<?php
$input = [
(object)[
"id" => 1,
"name" => "ASDAS",
"position" => 1,
],
(object)[
"id" => 2,
"name" => "ASDAS",
"position" => 1,
],
(object)[
"id" => 3,
"name" => "ASDAS",
"position" => 3,
],
(object)[
"id" => 4,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 5,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 6,
"name" => "ASDAS",
"position" => 3,
],
(object)[
"id" => 7,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 8,
"name" => "ASDAS",
"position" => 1,
]
];
// Sort array by ID
usort($input, function($a, $b) {
return $a->id <=> $b->id;
});
$groups = [];
foreach ($input as $item) {
// Create new group array
if (!array_key_exists($item->position, $groups)) {
$groups[$item->position] = [];
}
// Add item to group
$groups[$item->position][] = $item;
}
// Sort groups by position
ksort($groups);
// Merge groups 1 item at a time
function merge_groups(&$groups, &$target) {
foreach ($groups as $position => $group) {
if (!empty($group)) {
$target[] = array_shift($groups[$position]);
} else {
unset($groups[$position]);
}
}
if (!empty($groups)) {
merge_groups($groups, $target);
}
}
// Our final result array
$ouput = [];
merge_groups($groups, $ouput);
var_dump($ouput);
Tested in PHP 7.
Solution with simple loops. Foreach searches for a specific position and then increases the position. The number of positions can be more than 3. Positions like 123 123 23 are also possible.
$input = [
(object)[
"id" => 1,
"name" => "ASDAS",
"position" => 1,
],
(object)[
"id" => 2,
"name" => "ASDAS",
"position" => 1,
],
(object)[
"id" => 3,
"name" => "ASDAS",
"position" => 3,
],
(object)[
"id" => 4,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 5,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 6,
"name" => "ASDAS",
"position" => 3,
],
(object)[
"id" => 7,
"name" => "ASDAS",
"position" => 2,
],
(object)[
"id" => 8,
"name" => "ASDAS",
"position" => 1,
]
];
$minPos = min(array_column($input, "position"));
$arr = [];
$pos = $minPos;
while(true){
$found = false;
foreach($input as $key => $obj){
if($obj->position == $pos){
$arr[] = $obj;
unset($input[$key]);
++$pos;
$found = true;
}
}
if(empty($input)) break;
$minPos = min(array_column($input, "position"));
if(!$found AND $pos != $minPos){
$pos = $minPos;
}
}
var_dump($arr);

how to add folder path in foreach value in laravel

I have a table, name is templates. In which id and image_name field is present. in image_name value is image1.png, image2.png. Now I have to send image_name with its folder path in JSON to postman.
I tried with this. But don't think it will not work.
My controller is:
public function TemplateList()
{
$items = array();
$templates = TemplateList::all();
foreach($templates as $key=>$value)
{
$items['key'][] = $key;
$items['value'][] = 'www.xyz.com/images/'.$value;
}
if ($templates->count()) {
$data = collect(["status" => ["code" => "100", "message" => "Success", "data" => $items]]);
} else {
$data = collect(["status" => [ "code" => "101", "message" => "No Records"]]);
}
return response()->json($data, 200);
}
If I do not use foreach loop then in result is:
{
"status": {
"code": "100",
"message": "Success",
"data": [
{
"id": 66,
"tempimage": "template1.png"
},
{
"id": 67,
"tempimage": "template2.png"
},
But when I use foreach loop the result is:
{
"status": {
"code": "100",
"message": "Success",
"data": {
"key": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29
],
"value": [
"www.xyz.com/images/{\"id\":66,\"tempimage\":\"template1.png\"}",
"www.xyz.com/images/{\"id\":67,\"tempimage\":\"template2.png\"}",
"www.xyz.com/images/{\"id\":68,\"tempimage\":\"template3.png\"}",
"www.xyz.com/images/{\"id\":69,\"tempimage\":\"template4.png\"}",
"www.xyz.com/images/{\"id\":70,\"tempimage\":\"template5.png\"}",
"www.xyz.com/images/{\"id\":71,\"tempimage\":\"template6.png\"}",
"www.xyz.com/images/{\"id\":72,\"tempimage\":\"template7.png\"}",
"www.xyz.com/images/{\"id\":73,\"tempimage\":\"template8.png\"}",
"www.xyz.com/images/{\"id\":74,\"tempimage\":\"template9.png\"}",
"www.xyz.com/images/{\"id\":75,\"tempimage\":\"template10.png\"}",
"www.xyz.com/images/{\"id\":76,\"tempimage\":\"template11.png\"}",
"www.xyz.com/images/{\"id\":77,\"tempimage\":\"template12.png\"}",
"www.xyz.com/images/{\"id\":78,\"tempimage\":\"template13.png\"}",
"www.xyz.com/images/{\"id\":79,\"tempimage\":\"template14.png\"}",
"www.xyz.com/images/{\"id\":80,\"tempimage\":\"template15.png\"}",
"www.xyz.com/images/{\"id\":81,\"tempimage\":\"template16.png\"}",
"www.xyz.com/images/{\"id\":82,\"tempimage\":\"template17.png\"}",
"www.xyz.com/images/{\"id\":83,\"tempimage\":\"template18.png\"}",
"www.xyz.com/images/{\"id\":84,\"tempimage\":\"template19.png\"}",
"www.xyz.com/images/{\"id\":85,\"tempimage\":\"template20.png\"}",
"www.xyz.com/images/{\"id\":86,\"tempimage\":\"template21.png\"}",
"www.xyz.com/images/{\"id\":87,\"tempimage\":\"template22.png\"}",
"www.xyz.com/images/{\"id\":88,\"tempimage\":\"template23.png\"}",
"www.xyz.com/images/{\"id\":89,\"tempimage\":\"template24.png\"}",
"www.xyz.com/images/{\"id\":90,\"tempimage\":\"template25.png\"}",
"www.xyz.com/images/{\"id\":91,\"tempimage\":\"template26.png\"}",
"www.xyz.com/images/{\"id\":92,\"tempimage\":\"template27.png\"}",
"www.xyz.com/images/{\"id\":93,\"tempimage\":\"template28.png\"}",
"www.xyz.com/images/{\"id\":94,\"tempimage\":\"template29.png\"}",
"www.xyz.com/images/{\"id\":95,\"tempimage\":\"template30.png\"}"
]
}
}
}
The issue is in your foreach loop you are creating two new arrays with keys key and value, you need to put the data together as so:
public function TemplateList()
{
$items = array();
$templates = TemplateList::all();
foreach($templates as $key=>$value)
{
$items[] = [
'key' => $value['id'],
'value' => 'www.xyz.com/images/'.$value['tempimage']
];
}
if ($templates->count()) {
$data = collect(["status" => ["code" => "100", "message" => "Success", "data" => $items]]);
} else {
$data = collect(["status" => [ "code" => "101", "message" => "No Records"]]);
}
return response()->json($data, 200);
}

return array in PHP, Symfony 4 for REST API

I create my api restoration in symfony 4, but the array I return does not look like I want to.
Below I present my code, resultalt that is currently being performed and at the bottom is the result that I am trying to do.
Can I ask someone for help? I am not entirely sure how to achieve this effect.
This is my service php:
$data = $repository->findByData($fromDate, $toDate);
$i = 1;
$j = 1;
$resultArray = [];
foreach ($data as $key => $d) {
$date = $d['date'];
$dateString = $date->format('Y-m-d');
$resultIteration[$key] = [
'customerID' => $d['id'],
'customerName' => $d['customerName'],
'data' => [
'ordersAmount' . $i++ => $d['ordersAmount'],
'earnings' . $i++ => $d['earnings'],
'date' => $dateString,
],
'ordersAmount' . $j++ => $d['ordersAmount'],
'earnings' . $j++ => $d['earnings'],
];
array_push($resultArray,$resultIteration[$key]);
}
return $resultArray;
Current result:
[
{
"customerID": 1,
"customerName": "Client1",
"data": {
"ordersAmount1": 10,
"earnings2": 882.53,
"date": "2019-02-21"
},
"ordersAmount1": 10,
"earnings2": 882.53
},
{
"customerID": 1,
"customerName": "Client1",
"data": {
"ordersAmount3": 18,
"earnings4": 21,
"date": "2019-02-20"
},
"ordersAmount3": 18,
"earnings4": 21
},
{
"customerID": 2,
"customerName": "Client2",
"data": {
"ordersAmount5": 43,
"earnings6": 11,
"date": "2019-02-21"
},
"ordersAmount5": 43,
"earnings6": 11
},
{
"customerID": 2,
"customerName": "Client2",
"data": {
"ordersAmount7": 21,
"earnings8": 41,
"date": "2019-02-20"
},
"ordersAmount7": 21,
"earnings8": 41
}
]
I would like to this result:
[
{
customerID: 1,
customerName: "Client1",
data: [
{
date: "2019-02-20"
},
{
date: "2019-02-21"
}
],
ordersAmount1: 12,
earnings2: 3333,
ordersAmount3: 1,
earnings4: 2,
},
{
customerID: 2,
customerName: "Client2",
data: [
{
date: "2019-02-20"
},
date: "2019-02-21"
}
],
ordersAmount1: 3112,
earnings2: 44,
ordersAmount3: 121,
earnings4: 2543,
}
],
Edit: this is my $data:
[
{
"date": "2019-02-21T00:00:00+01:00",
"ordersAmount": 10,
"earnings": 882.53,
"id": 1,
"customerName": "Client1"
},
{
"date": "2019-02-20T00:00:00+01:00",
"ordersAmount": 18,
"earnings": 21,
"id": 1,
"customerName": "Client1"
},
{
"date": "2019-02-21T00:00:00+01:00",
"ordersAmount": 43,
"earnings": 11,
"id": 2,
"customerName": "Client2"
},
{
"date": "2019-02-20T00:00:00+01:00",
"ordersAmount": 21,
"earnings": 41,
"id": 2,
"customerName": "Client2"
}
]
See below code, It'll Solve your issue
$data = $repository->findByData($fromDate, $toDate);
// define $resultIteration array
$resultIteration = [];
foreach ($data as $key => $d) {
$i = 1;
$date = $d['date'];
//$dateString = $date->format('Y-m-d');
$dateString = date('Y-m-d', strtotime($date));
$resultIteration[$key] = [
'customerID' => $d['id'],
'customerName' => $d['customerName'],
'data' => [
[
'date' => $dateString,
], [
'date' => $dateString
]
],
'ordersAmount' . $i++ => $d['ordersAmount'],
'earnings' . $i++ => $d['earnings'],
'ordersAmount' . $i++ => $d['ordersAmount'],
'earnings' . $i++ => $d['earnings'],
];
// REMOVE THIS LINE
//array_push($resultArray,$resultIteration[$key]);
}
// RETURN $resultIteration in response
return $resultIteration;
This should do it, using array_reduce and array_map:
$data_by_customer = array_reduce($data, function ($result, $entry) {
$result[$entry['id']][] = $entry;
return $result;
}, []);
$result = array_values(array_map(function ($customer_entries) {
$first_entry = reset($customer_entries);
$entry = [
'customerID' => $first_entry['id'],
'customerName' => $first_entry['customerName'],
'data' => []
];
$index = 0;
foreach ($customer_entries as $customer_entry) {
$entry += [
'ordersAmount' . ++$index => $customer_entry['ordersAmount'],
'earnings' . ++$index => $customer_entry['earnings'],
];
$entry['data'][] = ['date' => $customer_entry['date']->format('Y-m-d')];
}
return $entry;
}, $data_by_customer));
Demo: https://3v4l.org/BStNF

merge array keys and add the values-PHP

I want to merge two same keys in an array and get the sum of the values.
I want the same structure as it is now.Because this data needs to be converted to JSON.
This is what i get now.
{
"data": [{
"count_of_invites": 5,
"user": "Rajesh",
"id": "53"
},
{
"count_of_invites": 9,
"user": "Student",
"id": "45"
},
{
"count_of_invites": 4,
"user": "Student",
"id": "45"
}
]
}
As you can see the id 45 are repeated.As i want the result as,
Expected output
{
"data": [{
"count_of_invites": 5,
"user": "Rajesh",
"id": "53"
},
{
"count_of_invites": 13,
"user": "Student",
"id": "45"
}
]
}
As you can see the duplicate entry should be removed as well as the count_of_invites of duplicate entry should be added.
<?php
$data = [
[
'id' => 2,
'name' => 'Paul',
'count' => 4
],
[
'id' => 3,
'name' => 'Peter',
'count' => 5
],
[
'id' => 3,
'name' => 'Peter',
'count' => 7
]
];
foreach($data as $array)
$counts[$array['id']][] = $array['count'];
$counts = array_map('array_sum', $counts);
foreach($data as $k => $array)
$data[$k]['count'] = $counts[$array['id']];
$data = array_unique($data, SORT_REGULAR);
print json_encode($data, JSON_PRETTY_PRINT);
Output:
[
{
"id": 2,
"name": "Paul",
"count": 4
},
{
"id": 3,
"name": "Peter",
"count": 12
}
]
You can achieve it this way:
$ids = array();
$output = array();
foreach ($input as $value) {
if (!isset($ids[$value["id"]])) {
$ids[$value["id"]]=$count($output);
$output[]=$value;
} else {
$output[$ids[$value["id"]]]["count_of_invites"] = $value["count_of_invites"];
$output[$ids[$value["id"]]]["user"] = $value["user"];
}
}
The count method was declared as variable and i've added with addition assignment operator.
Thank You for helping.
$ids = array();
$output = array();
foreach ($response as $value) {
if (!isset($ids[$value["id"]])) {
$ids[$value["id"]] = count($output);
$output[] = $value;
}
else {
$output[$ids[$value["id"]]]["count_of_invites"] += $value["count_of_invites"];
$output[$ids[$value["id"]]]["user"] = $value["user"];
}
}

Categories