Differentiate Array base on Value And Sum Of Array in Laravel - php

I have array and first of all I want to differentiate base on site(key) and site is not limited to 1 or 2
And then sum of opening balance and closing balance of site
like all site(888) total_balance = opening_balance + closing_balance
(999) total_balance = opening_balance + closing_balance
"games": [
{
"id": 240,
"user_id": 1,
"site": "888",
"opening_balance": 5,
"closing_balance": 6
},
{
"id": 243,
"user_id": 1,
"site": "999",
"opening_balance": 3,
"closing_balance": 4
},
{
"id": 244,
"user_id": 1,
"site": "888",
"opening_balance": 5,
"closing_balance": 6
},
And want output like
(site => 888, total_balance => 22 , site => 999, total_balance => 7
(it could b string))
And code I tried:
{
$collection = collect(Site::all())->map(function($item , $key){
return $item["name"];
});
$record = Game::whereIn('site',$collection)->get();
dd($record);
/*$bySite = array();
foreach ($record as $key => $item) {
if(!isset($bySite[$item['site']])) {
$bySite[$item['site']] = array();
}
$bySite[$item['site']][$key] = $item;
}*/
}
after this code which I commented output is
but then I don't know how sum of this
{
"888": {
"0": {
"id": 240,
"user_id": 1,
"site": "888",
"opening_balance": 5,
"closing_balance": 6
},
"2": {
"id": 244,
"user_id": 1,
"site": "888",
"opening_balance": 5,
"closing_balance": 6
},
},
"999": {
"1": {
"id": 243,
"user_id": 1,
"site": "999",
"opening_balance": 3,
"closing_balance": 4,

You can achieve this using Laravel Collection.
$games = [
[
"id" => 240,
"user_id" => 1,
"site" => "888",
"opening_balance" => 5,
"closing_balance" => 6
],
[
"id" => 243,
"user_id" => 1,
"site" => "999",
"opening_balance" => 3,
"closing_balance" => 4
],
[
"id" => 244,
"user_id" => 1,
"site" => "888",
"opening_balance" => 5,
"closing_balance" => 6
]
];
$games = collect($games);
$games = $games->groupBy('site')->map(function($game, $key){
return [
'site' => $key,
'total_balance' => $game->sum('opening_balance') + $game->sum('closing_balance'),
];
})->values();
dd($games->toArray());
And the output would be,
array:2 [▼
0 => array:2 [▼
"site" => 888
"total_balance" => 22
]
1 => array:2 [▼
"site" => 999
"total_balance" => 7
]
]
Code Snippet : https://implode.io/5aPGeH

step
1. foreach ($collection)
2. sum the value and store in array like ($collection->sum('opening_balance'), ($collection->sum('closing_balance')
3. then sum the variable
4. stop loop
5. then $final = $final['site'] . " => " . $final['sum'];

Related

how to merge two collection when value is same in laravel

I have following data which I want to merge when it repeats:
{
"employee_id": 7,
"organization_id": 1,
"year": 2021,
"tenure_id": 1,
"leave_name": "Annual Leaves",
"leaves": 26,
"lates": "1",
"leave_id": 1,
"assigned_quota": 99,
"available_quota": "12",
"is_default_leave": 1,
"exceeding": 14
},
{
"employee_id": 15,
"organization_id": 1,
"year": 2021,
"tenure_id": 1,
"leave_name": "test",
"leaves": "25",
"lates": "0",
"leave_id": 16,
"assigned_quota": 50,
"available_quota": "4",
"is_default_leave": 0,
"exceeding": 21
},
{
"employee_id": 15,
"organization_id": 1,
"year": 2021,
"tenure_id": 1,
"leave_name": "Annual Leaves",
"leaves": 25,
"lates": "0",
"leave_id": 1,
"assigned_quota": 99,
"available_quota": "9",
"is_default_leave": 1,
"exceeding": 16
}
know I want it to like this when it merge:
{
"employee_id": 15,
"organization_id": 1,
"year": 2021,
"tenure_id": 1,
"leaves": [
{
"leave_name": "Annual Leaves",
"leaves": 25,
"lates": "0",
"leave_id": 1,
"assigned_quota": 99,
"available_quota": "9",
"is_default_leave": 1,
"exceeding": 16
},
{
"leave_name": "test",
"leaves": "25",
"lates": "0",
"leave_id": 16,
"assigned_quota": 50,
"available_quota": "4",
"is_default_leave": 0,
"exceeding": 21
}
]
}
I have tried using groupby with "employee_id" however it but it gives data with id as parent and and array inside which I dont want anyone here please explain how can I achieve this.
merge method returns merged collection
$c1 = new Collection(['foo']);
$c2 = new Collection(['bar']);
$merged = $c1->merge($c2); // Contains foo and bar.
$c1 = CollectionA::all();
$c2 = CollectionB::all();
$merged = $c1->merge($c2);
Not sure the builting collection methods will do that for you, but some simple PHP code will
$jstring = '[{
"employee_id": 7, "organization_id": 1, "year": 2021,
"tenure_id": 1, "leave_name": "Annual Leaves", "leaves": 26,
"lates": "1", "leave_id": 1, "assigned_quota": 99,
"available_quota": "12", "is_default_leave": 1, "exceeding": 14
},
{
"employee_id": 15, "organization_id": 1, "year": 2021,
"tenure_id": 1, "leave_name": "test", "leaves": "25",
"lates": "0", "leave_id": 16, "assigned_quota": 50,
"available_quota": "4", "is_default_leave": 0, "exceeding": 21
},
{
"employee_id": 15, "organization_id": 1, "year": 2021,
"tenure_id": 1, "leave_name": "Annual Leaves", "leaves": 25,
"lates": "0", "leave_id": 1, "assigned_quota": 99,
"available_quota": "9", "is_default_leave": 1, "exceeding": 16
}]';
$json = json_decode($jstring);
$merged = [];
foreach ($json as $jobj){
if ( array_key_exists($jobj->employee_id, $merged) ) {
// we saw this one before so add to the employee's leaves array
$merged[$jobj->employee_id]->leaves[] = [ "leave_name" => $jobj->leave_name,
"leaves" => $jobj->leaves,
"lates" => $jobj->lates,
"leave_id" => $jobj->leave_id,
"assigned_quota" => $jobj->assigned_quota,
"available_quota" => $jobj->available_quota,
"is_default_leave" => $jobj->is_default_leave,
"exceeding" => $jobj->exceeding
];
} else {
$leaves = [ "leave_name" => $jobj->leave_name,
"leaves" => $jobj->leaves,
"lates" => $jobj->lates,
"leave_id" => $jobj->leave_id,
"assigned_quota" => $jobj->assigned_quota,
"available_quota" => $jobj->available_quota,
"is_default_leave" => $jobj->is_default_leave,
"exceeding" => $jobj->exceeding
];
$obj = new stdClass;
$obj->employee_id = $jobj->employee_id;
$obj->organization_id = $jobj->organization_id;
$obj->year = $jobj->year;
$obj->tenure_id = $jobj->tenure_id;
$obj->leaves[] = $leaves;
$merged[$jobj->employee_id] = $obj;
}
}
print_r($merged);
RESULTS
Array (
[7] => stdClass Object (
[employee_id] => 7
[organization_id] => 1
[year] => 2021
[tenure_id] => 1
[leaves] => Array (
[0] => Array (
[leave_name] => Annual Leaves
[leaves] => 26
[lates] => 1
[leave_id] => 1
[assigned_quota] => 99
[available_quota] => 12
[is_default_leave] => 1
[exceeding] => 14
)
}
)
[15] => stdClass Object (
[employee_id] => 15
[organization_id] => 1
[year] => 2021
[tenure_id] => 1
[leaves] => Array (
[0] => Array {
[leave_name] => test
[leaves] => 25
[lates] => 0
[leave_id] => 16
[assigned_quota] => 50
[available_quota] => 4
[is_default_leave] => 0
[exceeding] => 21
)
[1] => Array (
[leave_name] => Annual Leaves
[leaves] => 25
[lates] => 0
[leave_id] => 1
[assigned_quota] => 99
[available_quota] => 9
[is_default_leave] => 1
[exceeding] => 16
)
)
)
)

Flat/Merge Array of Arrays and primitve types

i have an Array like this:
[ [ "id": 1, "name": "Kategorie 1", "parent_id": null, [ "id": 2, "name": "Kategorie 1.1", "parent_id": 1, [ "id": 5, "name": "Kategorie 1.1.1", "parent_id": 2, [ "id": 11, "name": "Kategorie 1.1.1.1", "parent_id": 5, [] ], [ "id": 12, "name": "Kategorie 1.1.1.2", "parent_id": 5, [] ] , ........]
So this is a Category Hierachy like:
Category 1
Category 1.1
Category 1.2
Category 1.2.1
Category 1.2.1.1.
Category 2
Category 2.1.
Category 2.1.1.
Category 2.2
Category 2.3.
But the depth of the Categories is variable.
So is there a way to flat/merge the Array to:
[ [ "id": 1, "name": "Kategorie 1", "parent_id": null], [ "id": 2, "name": "Kategorie 1.1", "parent_id": 1], [ "id": 5, "name": "Kategorie 1.1.1", "parent_id": 2], [ "id": 11, "name": "Kategorie 1.1.1.1", "parent_id": 5], [ "id": 12, "name": "Kategorie 1.1.1.2", "parent_id": 5] ]
There you go:
<?php
$array = [
[
"id" => 1, "name" => "Kategorie 1", "parent_id" => null,
[
"id" => 2, "name" => "Kategorie 1.1", "parent_id" => 1,
[
"id" => 5, "name" => "Kategorie 1.1.1", "parent_id" => 2,
[
"id" => 11, "name" => "Kategorie 1.1.1.1", "parent_id" => 5, []
],
[
"id" => 12, "name" => "Kategorie 1.1.1.2", "parent_id" => 5, []
]
]
]
]
];
function flatMerge(array $array, array &$result = [])
{
$subResult = [];
foreach ($array as $key => $sub) {
if (is_array($sub)) {
flatMerge($sub, $result);
} else {
$subResult[$key] = $sub;
}
}
$result[] = $subResult;
return $result;
}
$result = flatMerge($array); // flat merge the array
var_dump($result);
$result = array_filter($result, static function (array $array) { // remove empty arrays
return !empty($array);
});
var_dump($result);
$result = array_values($result); // reset array keys
var_dump($result);
You can see the result of this code here: http://sandbox.onlinephpfunctions.com/code/b4eaddb4a52f5e9cf9a80644190e526613381c60
Supposing your array like this:
$arr = [
[
"id" => 1, "name" => "Kategorie 1", "parent_id" => null,
"children" => [
"id" => 2, "name" => "Kategorie 1.1", "parent_id" => 1,
"children" => [
"id" => 5, "name" => "Kategorie 1.1.1", "parent_id" => 2,
children => [
[ "id" => 11, "name" => "Kategorie 1.1.1.1", "parent_id" => 5, "children" => [] ],
[ "id" => 12, "name" => "Kategorie 1.1.1.2", "parent_id"=> 5, "children" => [] ]
]
]
]
]
];
The following function may work in your case, using recursion function:
function flatten(array $array) {
$branch = [];
foreach ($array as $item) {
$children = [];
if (isset($item["children"]) && is_array($item["children"])) {
$children = flatten($item["children"]);
unset($item["children"]);
}
$branch = array_merge($branch, [$item], $children);
}
return $branch;
}

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 manually map collection using laravel/php and get total amount

I currently have the below json response that the API is returning. I am able to return it using Laravel Eloquent. There are several users and each user has a several receipts. A receipt has types and status. I want to try to get the total sum amount for each receipt that is related to its type and status. I was able to return the below json response using
$this->user->with('receipts')->has('receipts')->get(['id', 'name']);
I have tried using multiple laravel collections methods https://laravel.com/docs/5.8/collections#available-methods But I am still unable to get the desired response.
[
{
"id": 1,
"name": "kent",
"receipts": [
{
"id": 1,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 100
},
{
"id": 2,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 100
},
{
"id": 3,
"user_id": 1,
"type_id": 2,
"status": 1,
"amount": 50
},
{
"id": 4,
"user_id": 1,
"type_id": 2,
"status": 0,
"amount": 30
},
{
"id": 5,
"user_id": 1,
"type_id": 2,
"status": 0,
"amount": 30
},
{
"id": 6,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 20
},
{
"id": 7,
"user_id": 1,
"type_id": 1,
"status": 1,
"amount": 10
}
]
},
{
"id": 2,
"name": "allison",
"receipts": [
{
"id": 9,
"user_id": 2,
"type_id": 1,
"status": 0,
"amount": 20
}
]
}
]
I expect to get this:
[
{
"id": 1,
"name": "kent",
"receipts": [
{
"performance and deleted": 220,
"performance and not deleted": 10,
"project and deleted": 60,
"project and deleted": 50
}
]
},
{
"id": 2,
"name": "allison",
"receipts": [
{
"performance and deleted": 20,
"performance and not deleted": 0,
"project and deleted": 0,
"project and not deleted": 0
}
]
}
]
My main concern is to use laravel collection methods and easy to read code to get my expected result
In this way, I believe you get your expected result with nice readable code.
I'll assume that you have $users variable which contains a list of users in collection (And probably the receipts are already loaded).
// You need to name the keys as you desire. (I can't figure out the labels by the type_id and status numbers).
$statusPair = collect([
'performance and deleted' => [
'type_id' => 1,
'status' => 0,
],
'something' => [
'type_id' => 1,
'status' => 1,
],
'something 2' => [
'type_id' => 2,
'status' => 0,
],
'something 3' => [
'type_id' => 2,
'status' => 1,
],
]);
$data = $users->map(function ($user) use ($statusPair) {
$receipts = $user->receipts;
$sums = $statusPair->mapWithKeys(function ($pair, $statusLabel) use ($receipts) {
$filtered = $receipts;
foreach ($pair as $key => $value) {
$filtered = $filtered->where($key, $value);
}
$sum = $filtered->sum('amount');
return [
$statusLabel => $sum,
];
});
return [
'id' => $user->id,
'name' => $user->name,
'receipts' => $sums->toArray(),
];
});
i think this will help
$user->receipts->sum('amount');

Assign the values of one array to another not merging

I need to append certain values of Second array to the first array
I.e.,
In the First Array i create two elements such as name and price and get the values from Second Array and give it to first array
Here is my First Array
[
{
"id": 8,
"user_id": 21,
"category_id": 1,
"juice_id": 2,
"count": "100",
"status": "1",
"created_at": "2016-02-23 07:12:14",
"updated_at": "2016-02-23 07:12:14"
},
{
"id": 9,
"user_id": 21,
"category_id": 1,
"juice_id": 1,
"count": "100",
"status": "1",
"created_at": "2016-02-23 07:15:47",
"updated_at": "2016-02-23 07:15:47"
}
]
And the Second array is
{
"1": {
"id": 2,
"store_id": 1,
"category_id": 1,
"name": "Cashew Butter Baby",
"image": "http://greenhoppingbucket.s3.amazonaws.com/juice/1455719144rebV3iRUlj.png",
"description": "Cashew, Butter and Milk",
"price": "12.00",
"status": 1,
"created_at": "2016-02-17 19:56:11",
"updated_at": "2016-02-17 19:56:11"
},
"2": {
"id": 1,
"store_id": 1,
"category_id": 1,
"name": "Kalekolada",
"image": "http://greenhoppingbucket.s3.amazonaws.com/juice/1455719105WAVB3SGxT7.png",
"description": "Pulp of Kale",
"price": "10.00",
"status": 1,
"created_at": "2016-02-17 19:55:34",
"updated_at": "2016-02-17 19:55:34"
}
}
My Expected result is
[
{
"id": 8,
"user_id": 21,
"category_id": 1,
"juice_id": 2,
"count": "100",
"status": "1",
"created_at": "2016-02-23 07:12:14",
"updated_at": "2016-02-23 07:12:14"
"name": "Cashew Butter Baby",
"price": "12.00",
},
{
"id": 9,
"user_id": 21,
"category_id": 1,
"juice_id": 1,
"count": "100",
"status": "1",
"created_at": "2016-02-23 07:15:47",
"updated_at": "2016-02-23 07:15:47",
"name": "Kalekolada",
"price": "10.00",
}
]
I tried to do $newArray = array_merge($cartData, $juiceData);
But it is simply merging two arrays.
What is the mistake and how can i do that ?
Here's some code for merging those arrays. You should have a common index for them though (a different order may lead to unexpected behavior).
<?php
$a = array(
array(
"id" => 8,
"user_id" => 21,
"category_id" => 1,
"juice_id" => 2,
"count" => "100",
"status" => "1",
"created_at" => "2016-02-23 07:12:14",
"updated_at" => "2016-02-23 07:12:14"
),
array(
"id" => 9,
"user_id" => 21,
"category_id" => 1,
"juice_id" => 1,
"count" => "100",
"status" => "1",
"created_at" => "2016-02-23 07:15:47",
"updated_at" => "2016-02-23 07:15:47"
)
);
$b = array(
array(
"id" => 2,
"store_id" => 1,
"category_id" => 1,
"name" => "Cashew Butter Baby",
"image" => "http://greenhoppingbucket.s3.amazonaws.com/juice/1455719144rebV3iRUlj.png",
"description" => "Cashew, Butter and Milk",
"price" => "12.00",
"status" => 1,
"created_at" => "2016-02-17 19:56:11",
"updated_at" => "2016-02-17 19:56:11"
),
array(
"id" => 1,
"store_id" => 1,
"category_id" => 1,
"name" => "Kalekolada",
"image" => "http://greenhoppingbucket.s3.amazonaws.com/juice/1455719105WAVB3SGxT7.png",
"description" => "Pulp of Kale",
"price" => "10.00",
"status" => 1,
"created_at" => "2016-02-17 19:55:34",
"updated_at" => "2016-02-17 19:55:34"
)
);
// For this to work the arrays need to have the same string keys
// $merge = array_merge_recursive( $a, $b );
$merge = array();
foreach( $b as $key => $entry ) {
if( isset($a[$key]) ) {
$entry += $a[$key];
}
$merge[] = $entry;
}
var_dump( $merge );
EDIT:
New info in comments would give us something like:
$categories = array();
foreach( $b as &$entry ) {
$categories[$entry['id']] =& $entry;
}
$products = array();
foreach( $a as &$entry ) {
if( isset($categories[$entry['juice_id']]) ) {
$entry['category'] =& $categories[$entry['juice_id']];
}
$products[] =& $entry;
}
var_dump( $products );
No need to pass them by reference but should save some memory.

Categories