I have two variables like the following
$items1 =
[
[
"p_id" => 1000,
"value"=> 25
],
[
"p_id" => 2000,
"value"=> 15
],
[
"p_id" => 3000,
"value"=> 23
],
];
$items2 =
[
[
"p_id" => 1000,
"value"=> 5
],
[
"p_id" => 4000,
"value"=> 12
],
];
For a logging system, I want variable $items1 to be a reference and find its changes to the $items2 variable and finally have the following output:
$deleted = [
[
"p_id" => 2000,
"value"=> 15
]
];
$added = [
[
"p_id" => 4000,
"value"=> 12
],
];
$changed = [
[
"p_id" => 1000,
"value"=> 5
],
];
For a logging system may be a better suggested format, thank you for your help
working example
$items1 =
[
[
"p_id" => 1000,
"value"=> 25
],
[
"p_id" => 2000,
"value"=> 15
],
[
"p_id" => 3000,
"value"=> 23
],
];
$items2 =
[
[
"p_id" => 1000,
"value"=> 5
],
[
"p_id" => 4000,
"value"=> 12
],
];
function keyedByPidArray($items) {
$arr = [];
foreach($items as $item) {
$arr[$item['p_id']] = $item;
}
return $arr;
}
function changedItems($items1, $items2) {
$changed = [];
foreach($items1 as $item1) {
foreach($items2 as $k => $item2) {
if(($item1["p_id"] === $item2["p_id"]) && ($item1["value"] !== $item2["value"])) {
$changed[] = $item2;
unset($items2[$k]);
break;
}
}
}
return $changed;
}
$keyedByPidArr1 = keyedByPidArray($items1);
$keyedByPidArr2 = keyedByPidArray($items2);
$pids1 = array_column($items1, 'p_id');
$pids2 = array_column($items2, 'p_id');
$added = array_intersect_key($keyedByPidArr2, array_flip(array_diff($pids2, $pids1)));
$deleted = array_intersect_key($keyedByPidArr1, array_flip(array_diff($pids1, $pids2)));
$changed = changedItems($items1, $items2);
print_r($added);
print_r($deleted);
print_r($changed);
Related
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
Intuit integration.
With create invoice. I am needing to get items from a loop when I create the invoice.
I also tried by creating the loop first and using $items in the invoice create but also get an error. "Format Error. Expect an element of an array or an object."
Not liking my loop. How can I accomplish this
?
$theResourceObj = Invoice::create([
"TotalAmt" => 200.00,
"Line" => [
$queryitems = 'SELECT * FROM mydatabse',
$query_items = mysqli_query($con,$queryitems),
while($row = mysqli_fetch_array($query_items)) {
[
"Description"=> "Loop Description",
"DetailType"=> "SalesItemLineDetail",
"SalesItemLineDetail"=> [
"TaxCodeRef"=> [
"value"=> "TAX"
],
"Qty"=> 1,
"UnitPrice"=> 200,
"ItemRef"=> [
"name"=> "Loop Name",
"value"=> "5"
]
],
"LineNum"=> 1,
"Amount"=> 200.00,
"Id"=> "1"
],
}
],
"CustomerRef"=> [
"value"=> 1
],
"BillEmail" => [
"Address" => "email#somewhere.com"
]
]);
You can't put loops inside array literals.
Construct the array incrementally outside the call to Invoice::create().
$invoice = [
"TotalAmt" => 200.00,
"CustomerRef"=> [
"value"=> 1
],
"BillEmail" => [
"Address" => "email#somewhere.com"
]
];
$lines = [];
$queryitems = 'SELECT * FROM mydatabse';
$query_items = mysqli_query($con,$queryitems);
while($row = mysqli_fetch_array($query_items)) {
$lines[] = [
"Description"=> "Loop Description",
"DetailType"=> "SalesItemLineDetail",
"SalesItemLineDetail"=> [
"TaxCodeRef"=> [
"value"=> "TAX"
],
"Qty"=> 1,
"UnitPrice"=> 200,
"ItemRef"=> [
"name"=> "Loop Name",
"value"=> "5"
]
],
"LineNum"=> 1,
"Amount"=> 200.00,
"Id"=> "1"
];
}
$invoice['Line'] = $lines;
$theResourceObj = Invoice::create($invoice);
I have to create API for dynamic menu used in react js. The menu contains catgeory, subcategory and further subcategory. I have created the code, but it is not working as expected.
The required output is,
{
"data": [
{
"id": 15,
"name": "category 1",
"slug": "category-1",
"subcategory": [
{
"sub_id": 15,
"sub_name": "subcategory 1",
"sub_slug": "subcategory-1"
"fsubcategory": [
{
"fsub_id": 15,
"fsub_name": "fsubcategory 1",
"fsub_slug": "fsubcategory-1"
},
...
]
},
...
]
},
....
]
}
The code I have used to create the above result is,
$list = Category::select('id', 'name', 'slug')->where(array('in_menu' => 1, 'status' => 1, 'deleted_at' => null))->orderBy('id', 'desc')->get();
$data = [];
foreach ($list as $category) {
$sublist = Subcategory::select('id', 'name', 'slug')->where(array('category_id' => $category->id, 'status' => 1, 'deleted_at' => null))->orderBy('id', 'desc')->get();
$item = [
"id" => $category->id,
"name" => $category->name,
"slug" => $category->slug,
"subcategory" => [],
];
foreach($sublist as $subcategory) {
$fsublist = Fsubcategory::select('id', 'name', 'slug')->where(array('category_id' => $category->id, 'subcategory_id' => $subcategory->id, 'status' => 1, 'deleted_at' => null))->orderBy('id', 'desc')->get();
$item["subcategory"][] = [
"sub_id" => $subcategory->id,
"sub_name" => $subcategory->name,
"sub_slug" => $subcategory->slug,
"fsubcategory" => [],
];
foreach($fsublist as $fsubcategory) {
$item["subcategory"][]["fsubcategory"] = [
"fsub_id" => $fsubcategory->id,
"fsub_name" => $fsubcategory->name,
"fsub_slug" => $fsubcategory->slug,
];
}
}
$data[] = $item;
}
return response()->json(['data' => $data]);
But the above code is not getting the required output. The output for the above code is,
{
"data": [
{
"id": 11,
"name": "dhdf dfheryer",
"slug": "dhdf-dfheryer",
"subcategory": [
]
},
{
"id": 10,
"name": "dfhdfdf hery1----",
"slug": "fhdfdf-hery1",
"subcategory": [
{
"sub_id": 5,
"sub_name": "sdgwet gjsdg",
"sub_slug": "sdgwet-gjsdg",
"fsubcategory": [
]
}
]
},
{
"id": 1,
"name": "dfhdfh",
"slug": "dfhdf",
"subcategory": [
{
"sub_id": 7,
"sub_name": "FSubcategory 1",
"sub_slug": "fsubcategory-1",
"fsubcategory": [
]
},
{
"sub_id": 2,
"sub_name": "Test Subcategory",
"sub_slug": "test-subcategory",
"fsubcategory": [
]
},
[
{
"fsubcategory": {
"fsub_id": 2,
"fsub_name": "dfhdf dfhdfh",
"fsub_slug": "dfhdf-dfhdfh"
}
}
],
{
"sub_id": 1,
"sub_name": "ssdgsdg",
"sub_slug": "sgsdg",
"fsubcategory": [
]
},
[
{
"fsubcategory": {
"fsub_id": 3,
"fsub_name": "dfdfh",
"fsub_slug": "dfdfh"
}
}
],
[
{
"fsubcategory": {
"fsub_id": 1,
"fsub_name": "fdfd",
"fsub_slug": "fdfd"
}
}
]
]
}
]
}
fsubcategory is outside subcategory. How to get the required output. How to modify the code to achieve the correct result. I am really stuck here.
I have got the answer,
$list = Category::select('id', 'name', 'slug')
->where([
'in_menu' => 1,
'status' => 1,
'deleted_at' => null
])
->orderBy('id', 'desc')
->get();
$data = [];
foreach ($list as $category) {
$sublist = Subcategory::select('id', 'name', 'slug')
->where([
'category_id' => $category->id,
'status' => 1,
'deleted_at' => null
])
->orderBy('id', 'desc')
->get();
$item = [
"id" => $category->id,
"name" => $category->name,
"slug" => $category->slug,
"subcategory" => [],
];
foreach ($sublist as $subcategory) {
$fsublist = Fsubcategory::select('id', 'name', 'slug')->where(array('subcategory_id' => $subcategory->id, 'status' => 1, 'deleted_at' => null))->orderBy('id', 'desc')->get();
$subitems = [];
foreach ($fsublist as $fsubcategory) {
$subitems[] = [
"fsub_id" => $fsubcategory->id,
"fsub_name" => $fsubcategory->name,
"fsub_slug" => $fsubcategory->slug,
];
}
$item["subcategory"][] = [
"sub_id" => $subcategory->id,
"sub_name" => $subcategory->name,
"sub_slug" => $subcategory->slug,
"fsubcategory" => $subitems,
];
}
$data[] = $item;
}
return response()->json(['response' => 200, 'data' => $data]);
This will provide the required output
im new to mongodb after years with mysql and trying to figure this equivalent query in mongodb with php composer
select * from table where (x > 0 and x < 30) or x = 'half' and sid = 1
$query = [
'$and' => [
[
'sid'=> 1
], ['$and' => [[
'info.x' => [
'$lt' => '30'
]
], [
'info.x' => [
'$gt' => '0'
]
], [
'info.x' => [ /// i want to put this in $or
'half'
]
]]
]
]
];
i want to display all what is greater then 0 and less then 30 or equal to 'half' where sid is 1
thanks
It must be
db.collection.find({
"$or": [
{ "x": { "$gte": 0, "$lte": 30 }},
{ "x": "half" }
],
"sid": 1
})
Or
$query = [
'$or'=> [
[ 'x'=> [ '$gte'=> 0, '$lte'=> 30 ]],
[ 'x'=> 'half' ]
],
'sid'=> 1
]
I have an array like this
"entry a" => [
"type": 3,
"id": 1,
"content" => [
[
"name" => "somename a",
"date": => "2011-08-2"
],
[
"name" => "somename b",
"date": => "2012-04-20"
],
[
"name" => "somename c",
"date": => "2015-01-14"
],
]
],
"entry b" => [
"type": 3,
"id": 2,
"content" => [
[
"name" => "someothername a",
"date": => "2011-01-6"
],
[
"name" => "someothername b",
"date": => "2015-12-24"
],
[
"name" => "someothername c",
"date": => "2016-01-01"
],
]
],
...
I want to sort just the "content" array, by date, of each entry. I tried the following;
foreach ($cfArray as $cfEntry) {
if($cfEntry['type'] == '3' && !is_null($cfEntry['content'])) {
$content = $cfEntry['content'];
uasort($content, function($a, $b) {
$a_end = strtotime($a['date']);
$b_end = strtotime($b['date']);
return ($a_end > $b_end) ? -1 : 1;
});
$cfEntry['content'] = $content;
}
}
If I compare $content before and after the sort, it has changed but my $cfArray does not change. Why is that? Is there another way to sort this?
Your code is almost working, and you can create it fully working with saving changed item to $newCfArray array with this sample:
$newCfArray = array();
foreach ($cfArray as $key => $cfEntry) {
if($cfEntry['type'] == '3' && !is_null($cfEntry['content'])) {
$content = $cfEntry['content'];
uasort($content, function($a, $b) {
$a_end = strtotime($a['date']);
$b_end = strtotime($b['date']);
return ($a_end > $b_end) ? -1 : 1;
});
$cfEntry['content'] = $content;
}
$newCfArray[$key] = $cfEntry;
}
$cfArray = $newCfArray;