mongodb pull element from multidimensional array - php

Hi i have the following array and i want to pull the array with productId 100343
Array(
[_id] => MongoId Object
(
[$id] => 5388a02c8ead0ebf048b4569
)
[cartId] => 14ce496ac194d5d8ee8d0cd11bd3ef5a
[products] => Array
(
[100343] => Array
(
[productId] => 100343
[quantity] => 13
[name] => a
)
[100344] => Array
(
[productId] => 100344
[quantity] => 3
[name] => ab
)
[100345] => Array
(
[productId] => 100345
[quantity] => 1
[name] => abc
)
)
)
I've tried like this but it doesn't work
$c->update(
$aQuery,
array(
'$pull' => array('products'=>array('productId'=>'100343'))
)
);

That is not an array. Arrays in MongoDB are different in concept to what PHP calls an array, so the structure you have there is the same as this JSON representation:
{
"products": {
"100343": {
"productId": 100343,
"quantity": 13,
"name": "a"
},
"100344": {
"productId": 100344,
"quantity": 3,
"name": "ab"
},
"100345": {
"productId": 100345,
"quantity": 1,
"name": "abc"
}
}
}
That sort of structure is just a use of sub-documents and is not an array in the sense as used by MongoDB. To remove the entry as you want with this structure you use the $unset operator.
$c->update(
$aQuery,
array(
'$unset' => array('products.productId.100343' => "")
)
);
But really you need to change your data, so to serialize a proper array for MongoDB you need to structure code like this:
$data = array(
"products" => array(
array(
"productId" => 100343,
"quantity" => 13,
"name" => "a"
),
array(
"productId" => 100344,
"quantity" => 3,
"name" => "ab"
),
array(
"productId" => 100345,
"quantity" => 1,
"name" => "abc"
)
)
);
That produces a JSON structure that looks like this:
{
"products":[
{
"productId":100343,
"quantity":13,
"name":"a"
},
{
"productId":100344,
"quantity":3,
"name":"ab"
},
{
"productId":100345,
"quantity":1,
"name":"abc"
}
]
}
That is what MongoDB calls an array, so now you can use the $pull operator correctly:
$c->update(
$aQuery,
array(
'$pull' => array( 'products.productId' => 100343 )
)
);

Related

PHP Array to multidimensional json data

I have the following php code that produces a json data set
$json_data = array(
"code"=>"200",
"name"=>"My Name",
"serial_number"=>"serial"
);
$result = json_encode($json_data);
The dataset is only one level. As I am creating this data set with a php loop. I want to be able to have multiple people but the code element be outside the users. So basically I want the json data to look like this:
{
"code": "404",
"people": [
{
"name": "Person 1",
"serial_number": "xyz"
},
{
"name": "Person Two",
"serial_number": "123"
}
]
}
Basically you want to group array of objects by property "code". There are many questions about this. Here's one of the possible methods using array_reduce.
$json_data = [
[
"code" => "200",
"name" => "My Name1",
"serial_number" => "serial1",
], [
"code" => "200",
"name" => "My Name2",
"serial_number" => "serial2",
], [
"code" => "400",
"name" => "My Name3",
"serial_number" => "serial3",
],
];
$result = array_values(array_reduce($json_data, function ($agg, $item) {
if (!isset($agg[$item['code']])) {
$agg[$item['code']] = [
"code" => $item['code'],
"people" => [],
];
}
$agg[$item['code']]['people'][] = [
"name" => $item["name"],
"serial_number" => $item["serial_number"],
];
return $agg;
}, []));
print_r($result);
Output:
Array
(
[0] => Array
(
[code] => 200
[people] => Array
(
[0] => Array
(
[name] => My Name1
[serial_number] => serial1
)
[1] => Array
(
[name] => My Name2
[serial_number] => serial2
)
)
)
[1] => Array
(
[code] => 400
[people] => Array
(
[0] => Array
(
[name] => My Name3
[serial_number] => serial3
)
)
)
)

How to remove any sub array and keep only two top levels of a multidimensional array?

I need to modify an array with subarrays and keep only the top two arrays (array -> results - x) and remove any subarray below. For example array "location" & "syncState" should be removed.
Original array:
$device_array = [
"totalCount" => "3",
"results" => [
[
"id" => "2",
"serialNumber" => "DX",
"location" => ["id" => "5", "locationName" => "US"]
],
[
"id" => "4",
"serialNumber" => "DM",
"syncState" => ["id" => "7", "locationName" => "DE"]
],
[
"id" => "5",
"serialNumber" => "C0"
]
]
];
The array should look like this:
Array
(
[totalCount] => 3
[results] => Array
(
[0] => Array
(
[id] => 2
[serialNumber] => DX
)
[1] => Array
(
[id] => 4
[serialNumber] => DM
)
[2] => Array
(
[id] => 5
[serialNumber] => C0
)
)
)
I'm trying to loop through the arrays (sub arrays included) but I can't remove all of the subarrays that sit under $device_array['results'][x].
foreach ($device_array as $key => $value) {
if(is_array($value)) {
unset($device_array['results'][0]['location']);
}
}
You can just loop the results subarray directly and write a custom filter which will modify each entry by reference. Any of the associative elements that hold array type data will be filtered out.
Code: (Demo)
$array = [
"totalCount" => "3",
"results" => [
[
"id" => "2",
"serialNumber" => "DX",
"location" => ["id" => "5", "locationName" => "US"]
],
[
"id" => "4",
"serialNumber" => "DM",
"syncState" => ["id" => "7", "locationName" => "DE"]
],
[
"id" => "5",
"serialNumber" => "C0"
]
]
];
foreach ($array['results'] as &$entry) {
$entry = array_filter($entry, 'is_scalar');
}
var_export($array);
Output:
array (
'totalCount' => '3',
'results' =>
array (
0 =>
array (
'id' => '2',
'serialNumber' => 'DX',
),
1 =>
array (
'id' => '4',
'serialNumber' => 'DM',
),
2 =>
array (
'id' => '5',
'serialNumber' => 'C0',
),
),
)
Or completely functional style: (Demo)
$array['results'] = array_map(
function($entry) {
return array_filter($entry, 'is_scalar');
},
$array['results']
);
var_export($array);
This is how you obtain the output, but I am not so sure if this is what you need in your case
<?php
$array = [
'total' => 2,
'result' => [
[
'id' => 1,
'serialNumber' => 'DX',
'location' => ['id'=>1, 'locationName'=>'US']
],
[
'id' => 2 ,
'serialNumber' => 'DO',
'syncState' => ['id'=>7, 'locationName'=>'DE']
]
]
];
foreach( $array['result'] as $key => $value ){
foreach($value as $key2=>$subarray){
if(is_array($subarray)){
unset($value[$key2]);
}
}
$array['result'][$key] = $value;
}
print_r($array);

Grouping same name in json using php

I'm trying to create a timeline with an apex chart.
I can't literally print the Json data.
$temp[$r["Durum"]]['data'][] = array(
'x' => $r['Basladı'],
'y' => array(
strtotime($r['Saat']),
strtotime($r['Bitis'])
)
);
output
{
"P": {
"data": [
{
"x": "Basladi",
"y": [
1602418875,
1602418884
]
},
{
"x": "Basladi",
"y": [
1602418887,
1602418902
]
},
]
}
}
output I want
{
{
"name" : "P",
"data": [
{
"x": "Basladi",
"y": [
1602418875,
1602418884
]
},
{
"x": "Basladi",
"y": [
1602418887,
1602418902
]
},
]
}
}
Here is a code example with some sample input that will work for you.
Sample data (in your case the data from your database):
$yourdata = array(
array(
'Durum' => 'p',
'Basladı' => 'Basladı',
'Saat' => '12.12.2020',
'Bitis' => '12.12.2020'
),
array(
'Durum' => 'p',
'Basladı' => 'Basladı',
'Saat' => '12.12.2020',
'Bitis' => '12.12.2020'
),
array(
'Durum' => 's',
'Basladı' => 'Basladı',
'Saat' => '12.12.2020',
'Bitis' => '12.12.2020'
)
);
Code snippet:
// create empty temp array for the result
$temp = [];
// loop through your data (only an example - replace with your data)
foreach($yourdata as $r) {
// defines a temp data array to add
$temp_data = array(
'x' => $r['Basladı'],
'y' => array(
strtotime($r['Saat']),
strtotime($r['Bitis'])
)
);
// check if there is already an entry with that name
if(($key = array_search($r["Durum"], array_column($temp, 'name'))) !== false) {
// if there is, only add the data to it
$temp[$key]['data'][] = $temp_data;
} else {
// otherwise push a new array with the name and data to temp
$temp[] = array(
'name' => $r["Durum"],
'data' => array($temp_data)
);
}
}
var_dump($temp); // process with the data
The content of the variable $temp:
Array
(
[0] => Array
(
[name] => p
[data] => Array
(
[0] => Array
(
[x] => Basladı
[y] => Array
(
[0] => 1607731200
[1] => 1607731200
)
)
[1] => Array
(
[x] => Basladı
[y] => Array
(
[0] => 1607731200
[1] => 1607731200
)
)
)
)
[1] => Array
(
[name] => s
[data] => Array
(
[0] => Array
(
[x] => Basladı
[y] => Array
(
[0] => 1607731200
[1] => 1607731200
)
)
)
)
)

How to fetch record from an array if we have concept of array index, using array_column function?

I have an array of cryptocoin rates.
The array is looking as:
$array = Array ( [0] => Array ( [code] => BTC [name] => Bitcoin [rate] => 1 )
[1] => Array ( [code] => BCH [name] => Bitcoin Cash [rate] => 7.06364 )
[2] => Array ( [code] => USD [name] => US Dollar [rate] => 8185.84 ) )
I get results using $array[1]['rate'];
But i want to get result by [code] .
Like $array['USD']['rate']
Like $array['BCH']['rate']
How i can get the rate using currency code e.g USD
You can loop the array and build a new associative array to use in the rest of the project.
$array = Array( 0 => Array( "code" => "BTC", "name" => "Bitcoin", "rate" => 1 ),
"1" => Array ( "code" => "BCH", "name" => "Bitcoin Cash", "rate" => 7.06364 ),
"2" => Array ( "code" => "USD", "name" => "US Dollar", "rate" => 8185.84 ) );
foreach($array as $val){
$rates[$val["code"]] = $val;
}
echo $rates['USD']['rate']; // 8185.84
https://3v4l.org/0qs0n
Another option is to use array_column and array_combine to do it without loops.
$array = Array( 0 => Array( "code" => "BTC", "name" => "Bitcoin", "rate" => 1 ),
"1" => Array ( "code" => "BCH", "name" => "Bitcoin Cash", "rate" => 7.06364 ),
"2" => Array ( "code" => "USD", "name" => "US Dollar", "rate" => 8185.84 ) );
$keys = array_column($array, "code");
$rates = array_combine($keys, $array);
echo $rates['USD']['rate'];
You could use array_reduce and set the key to the value of code in the callback function:
$array = array_reduce($array, function($carry, $item) {
$carry[$item["code"]] = $item;
return $carry;
});
echo $array["USD"]["rate"]; //8185.84
Demo

How to loop through a multi-layer array and replace some associate values in it?

How can I loop through a multi-layer array and replace some associate values in it?
For instance, this is my array,
$items = array(
0 => array(
"id" => "1",
"title" => "parent 1",
"children" => array()
),
1 => array(
"id" => "2",
"title" => "parent 2",
"children" => array (
0 => array(
"id" => "4",
"title" => "children 1",
"granchildren" => array(
0 => array(
"id" => "7",
"title" => "granchildren 1"
),
1 => array(
"id" => "8",
"title" => "granchildren 2"
)
)
),
1 => array(
"id" => "5",
"title" => "children 2",
"granchildren" => array()
)
),
),
3 => array(
"id" => "3",
"title" => "parent 3",
"children" => array()
)
);
These are two working functions I have,
function translate ($id){
$items = array(
0 => array(
"id" => 1,
"title" => "parent 1 en"
),
1 => array(
"id" => 4,
"title" => "children 1 en"
),
2 => array(
"id" => 8,
"title" => "granchildren 2 en"
)
);
foreach($items as $item) {
if($id === $item['id'])
{
return $item['title'];
}
}
}
function looper ($items){
$new_items = array();
foreach($items as $key => $item) {
if(isset($key) && is_array($key)){
$new_items[$key] = translate($item['id']);
}else {
//looper($item);
}
}
return $new_items;
}
print_r(looper ($items));
This is the result I am after,
Array
(
[0] => Array
(
[id] => 1
[title] => parent 1 en // translated
[children] => Array
(
)
)
[1] => Array
(
[id] => 2
[title] => parent 2
[children] => Array
(
[0] => Array
(
[id] => 4
[title] => children 1 en // translated
[granchildren] => Array
(
[0] => Array
(
[id] => 7
[title] => granchildren 1
)
[1] => Array
(
[id] => 8
[title] => granchildren 2 en // translated
)
)
)
[1] => Array
(
[id] => 5
[title] => children 2
[granchildren] => Array
(
)
)
)
)
[3] => Array
(
[id] => 3
[title] => parent 3
[children] => Array
(
)
)
)
Is it possible?
Sounds like a job for array_walk or array_walk_recursive.
It will call a user-supplied function for every item in an array. You can have it modify the array by reference to achieve what you're after.

Categories