Sort documents based on array field size - php

I'm trying to use the size of an array called "empofthemonth" to sort each field returned by their amount of employee of the month wins.
Here is the insert code:
$db->users->insert(
["firstname" => "firstname1",
"lastname" => "test",
"email" => "test#email.org.uk",
"keyinfo" =>
["age" => 22,
"gender" => "Male",
"yearsemployed" => 1,
"empofthemonth" => ["Apr"]]
]);
$db->users->insert(
["firstname" => "firstname2",
"lastname" => "test2",
"email" => "test#email.co.uk",
"keyinfo" =>
["age" => 24,
"gender" => "Female",
"yearsemployed" => 5,
"empofthemonth" => ["Feb", "Mar"]]
]);
$db->users->insert(
["firstname" => "firstname3",
"lastname" => "test2",
"email" => "test#email.com",
"keyinfo" =>
["age" => 31,
"gender" => "Female",
"yearsemployed" => 2,
"empofthemonth" => ["Jan", "May", "Jun"]]
]);
I realise that aggregation might be used but i cannot work out the full syntax.
To conclude the query results should be in this order:
firstname3 (3 emp of the months)
firstname2 (2)
firstname1 (1)

We need to $project our documents and return the $size then $sort each document by that "size" in descending order. Note that to access the array field, we need to use the "dot notation".
db.users.aggregate(
[
{ "$project": {
"firstname": 1,
"lastname": 1,
"email": 1,
"keyinfo": 1,
"sz": { "$size": "$keyinfo.empofthemonth" }
}},
{ "$sort": { "sz": -1 } }
]
)
Everything in PHP:
$db->users->aggregate(
[
[ "$project" => [
"firstname" => 1,
"lastname" => 1,
"email" => 1,
"keyinfo" => 1,
"sz" => [ "$size" => "$keyinfo.empofthemonth" ]
]],
[ "$sort" => [ "sz" => -1 ] ]
]
)

Related

Print Group Name above the list [duplicate]

This question already has an answer here:
Reorganize array in twig
(1 answer)
Closed 8 months ago.
I have following array
[
{
id: 1,
group_name: 'usa',
state : 'San Francisco'
},
{
id: 2,
group_name: 'usa',
state : 'Texas'
},
{
id: 3,
group_name: 'usa',
state : 'North Carolina'
}, {
id: 4,
group_name: 'aus',
state : 'Darwin'
},
{
id: 5,
group_name: 'aus',
state : 'Melbourne'
},
{
id: 6,
group_name: 'usa',
state : 'Perth'
}
]
I want to print as following:
Group Name: USA
State: San Francisco
State: Texas
State: North Carolina
Group Name: AUS
State: Darwin
State: Perth
State: Sydney
I tried following in twig but lacked in logic
{% for place in places %}
<tr>
<td>{{ dump(place.getGroupName()) }}</td>
</tr>
<tr>
<td>{{ place.state}}</td>
</tr>
{% endif %}
In the loop I want to put the country above the list of states. In the list of states the country must be top following by the states and same with the other countries as well.
Solution:
"GroupBy" Array.
$groups = [
[
"id"=>1,
"group_name"=>"usa",
"state" => "San Franciso"
],
[
"id" => 2,
"group_name" => "usa" ,
"state"=> "Texas"
],
[
"id"=>3,
"group_name"=>"usa",
"state"=>"North Carolina"
],
[
"id" => 4,
"group_name" => "aus",
"state" => "Darwin"
],
[
"id" => 5,
"group_name" => "aus",
"state" => "Melbourne"
]
];
This is one of simple ways to GroupBy items in array, you should GroupBy "group_name" field. (https://www.delftstack.com/howto/php/php-group-arrays)
$grouped = array();
foreach ($groups as $element) {
$grouped[$element['group_name']][] = $element;
}
You should get something like this:
[
"usa" => [
["id" => 1, "state" => "Texas", "group_name" => "usa"],
["id" => 2, "state" => "North Carolina", "group_name" => "usa"],
["id" => 3, "state" => "Texas", "group_name" => "usa"],
],
"aus" => [
["id" => 4, "state" => "Melbourne", "group_name" => "aus"],
["id" => 5, "state" => "Darwin", "group_name" => "aus"]
]
]
Suggestion:
Before you send array to Twig, try to structure that array in this way:
$groups = [
'usa' => [
[ "id" => 1, "state" => "Texas" ],
[ "id" => 2, "state" => "North Carolina" ],
[ "id" => 3, "state" => "Texas" ],
],
'aus" => [
[ "id" => 4, "state" => "Darwin" ],
[ "id" => 5, "state" => "Melbourne" ],
]
]
And after that creation, you only need to iterate over the array and display values without GroupingBy array in Twig.

Php Recursivity: Convert a multidimensional associative array into an array that contains each level of data

I am looking for the best way to convert a multidimensional associative array into a new array, where each row is the concatenation of each column ex :
$datas[] = [
"id" => "1000",
"parent" => "0",
"level" => "1",
"children" => [
[
"id" => "1001",
"parent" => "1000",
"level" => "2",
"children" => [
[
"id" => "1002",
"parent" => "1001",
"level" => "3",
"children" => [
[
"id" => "1003",
"parent" => "1002",
"niveau" => "4",
],
[
"id" => "1004",
"parent" => "1002",
"niveau" => "4",
],
[
"id" => "1005",
"parent" => "1002",
"niveau" => "4",
]
]
],
[
]
]
],
[
"id" => "1006",
"parent" => "1000",
"level" => "2"
]
],
[
"id" => "1007",
"parent" => "0",
"level" => "1"
]
];
Here's my method :
public function recursData(array $datas, &$str ="", &$row =[], int $level = 0)
{
$level++;
foreach ($datas as $data) {
foreach($data as $key => $d) {
if (is_array($d)) {
$this->recursData($d, $str, $row,$level);
} else {
$str.= "{$level}_{$key}_{$d}|";
if ($key == "parent") {
$row[] = $str;
}
}
}
}
return $row;
}
Output (not what i'm looking for) :
array:8 [
0 => "1_id_1000|1_parent_0|"
1 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|"
2 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|"
3 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|"
4 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|4_id_1004|4_parent_1002|"
5 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|4_id_1004|4_parent_1002|4_id_1005|4_parent_1002|"
6 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|4_id_1004|4_parent_1002|4_id_1005|4_parent_1002|2_id_1006|2_parent_1000|"
7 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|4_parent_1002|4_id_1004|4_parent_1002|4_id_1005|4_parent_1002|2_id_1006|2_parent_1000|1_id_1007|1_parent_0|"
]
The output i'm looking for:
array:8 [
0 => "1_id_1000|1_parent_0"
1 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000"
2 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001"
3 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1003|3_parent_1002"
4 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1004|3_parent_1002"
5 => "1_id_1000|1_parent_0|2_id_1001|2_parent_1000|3_id_1002|3_parent_1001|4_id_1005|3_parent_1002"
6 => "1_id_1000|1_parent_0|2_id_1006|2_parent_1000"
7 => "1_id_1007|1_parent_0"
]
I'm stuck to finish this properly, I tried lot of things, but can't understand what to do obtain what I want to resolve this. Hope someone could help :)

Unexpected token while deserializing object: when using Click and Drop API - Royal Mail

I am making a POST request to create an order for Royal Mail Click and Drop:
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'Authorization' => 'Bearer secret-123'
])->post('https://api.parcel.royalmail.com/api/v1/orders/', [
'items' => [
'recipient' => [
'address' => [
"fullName" => 'Tom',
"companyName" => "Test",
"addressLine1" => "150",
"addressLine2" => "Valley Close",
"addressLine3" => "Elmdom",
"city" => "Birmingham",
"county" => "West Midlands",
"postcode" => "B12 2YT",
"countryCode" => "GB"
],
"emailAddress" => "test#test.com"
],
"billing" => [
"address" => [
"fullName" => 'Tom',
"companyName" => "Test",
"addressLine1" => "150",
"addressLine2" => "Valley Close",
"addressLine3" => "Elmdom",
"city" => "Birmingham",
"county" => "West Midlands",
"postcode" => "B12 2YT",
"countryCode" => "GB"
],
"phoneNumber" => "42425 5252552",
"emailAddress" => "test#test.com"
],
"orderDate" => "2021-05-18T16:39:01Z",
"subtotal" => 0,
"shippingCostCharged" => 0,
"total" => 0,
]
])->json();
dd($response);
but keep getting
'Unexpected token while deserializing object: PropertyName. Path 'items.recipient', line 1, position 22. Failed to deserialize following order request'
I keep getting the same error for all required fields...
API docs do not provide much details https://api.parcel.royalmail.com/. The same payload works in Insomnia. I am using Laravel Http client.
The API shows that items is an array of objects.
items": [
{
"orderReference": "string",
"recipient": {},
"sender": {},
"billing": {},
"packages": [],
"orderDate": "2019-08-24T14:15:22Z",
"plannedDespatchDate": "2019-08-24T14:15:22Z",
"specialInstructions": "string",
"subtotal": 0,
"shippingCostCharged": 0,
"otherCosts": 0,
"customsDutyCosts": 0,
"total": 0,
"currencyCode": "str",
"postageDetails": {},
"tags": [],
"label": {}
}
]
So you just need to wrap everything in items in another set of brackets.
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'Authorization' => 'Bearer secret-123'
])->post('https://api.parcel.royalmail.com/api/v1/orders/', [
'items' => [[
'recipient' => [
'address' => [
"fullName" => 'Tom',
"companyName" => "Test",
"addressLine1" => "150",
"addressLine2" => "Valley Close",
"addressLine3" => "Elmdom",
"city" => "Birmingham",
"county" => "West Midlands",
"postcode" => "B12 2YT",
"countryCode" => "GB"
],
"emailAddress" => "test#test.com"
],
"billing" => [
"address" => [
"fullName" => 'Tom',
"companyName" => "Test",
"addressLine1" => "150",
"addressLine2" => "Valley Close",
"addressLine3" => "Elmdom",
"city" => "Birmingham",
"county" => "West Midlands",
"postcode" => "B12 2YT",
"countryCode" => "GB"
],
"phoneNumber" => "42425 5252552",
"emailAddress" => "test#test.com"
],
"orderDate" => "2021-05-18T16:39:01Z",
"subtotal" => 0,
"shippingCostCharged" => 0,
"total" => 0,
]]
])->json();

Using a form to create JSON

I have an API which expects a JSON string in the following format:
{
"Title": "Mr",
"Forenames": "Steve",
"Surname": "Williams",
"CountryOfBirth": 1,
"EmailAddress": "john.doe#email.com",
"EmailType": "Personal",
"BirthDate": "\/Date(632880000000)\/",
"Suffix": null,
"NationalInsuranceNumber": null,
"PrimaryAddress": {
"Address1": "Flat 1",
"Address2": "Oxford Street",
"City": "London",
"County": "London",
"Postcode": "L12456",
"Country": 1
},
"AdditionalAddresses": [
{
"Address1": null,
"Address2": null,
"City": null,
"County": null,
"Postcode": null,
"Country": 0,
"AddressType": 0
}
],
"PrimaryTelephone": {
"Number": "123456789",
"DialingCode": 1,
"TelephoneType": 1
},
"AdditionalTelephone": [
{
"Number": null,
"DialingCode": 0,
"TelephoneType": 0
}
],
"BankAccount": {
"AccountName": "John Doe Account",
"AccountNumber": "123456789",
"SortCode": "123456"
},
"PrimaryCitizenship": {
"CountryOfResidency": 1,
"TaxIdentificationNumber": "AB12CD34EF56"
},
"AdditionalCitizenship": [
{
"CountryOfResidency": 0,
"TaxIdentificationNumber": null
}
],
"ExternalCustomerId": "151",
"ExternalPlanId": "151",
"PlanType": 10
}
As you can see there are some inner nested elements where each value can itself be an array, such as AdditionalTelephone
I re-created this JSON string in PHP with the following:
<?php
$dataArray = array(
"Title" => "Mr",
"Forename" => "Jesse",
"Surname" => "Orange",
"CountryOfBirth" => 1,
"EmailAddress" => "email#gmail.com",
"EmailType" => "Personal",
"BirthDate" => "\/Date(632880000000)\/",
"Suffix" => null,
"PrimaryAddress" => array(
"Address1" => "Flat 1",
"Address2" => "Oxford Street",
"City" => "London",
"County" => "London",
"Postcode" => "L12456",
"Country" => 1
),
"AdditionalAddresses" => array(
array(
"Address1" => null,
"Address2" => null,
"City" => null,
"County" => null,
"Postcode" => null,
"Country" => 0,
"AddressType" => 0
)
),
"PrimaryTelephone" => array(
"Number" => "123456789",
"DialingCode" => 1,
"TelephoneType" => 1
),
"AdditionalTelephone" => array(
array(
"Number" => "123456789",
"DialingCode" => 1,
"TelephoneType" => 1
)
),
"BankAccount" => array(
"AccountName" => "John Doe Account",
"AccountNumber" => "123456789",
"SortCode" => "123456"
),
"PrimaryCitizenship" => array(
"CountryOfResidency" => 1,
"TaxIdentificationNumber" => "AB12CD34EF56"
),
"AdditionalCitizenship" => array(
array(
"CountryOfResidency" => 0,
"TaxIdentificationNumber" => null
)
),
"ExternalCustomerId" => "151",
"ExternalPlanId" => "151",
"PlanType" => 10
);
header("Content-type:application/json");
$jsonDataArray = json_encode($dataArray, JSON_PRETTY_PRINT);
echo $jsonDataArray;
die();
?>
This prints the same kind of thing.
Now, I have a form that a user fills in and the data is POSTed, so I wanted to use these values in the array I had created.
For example:
$dataArray = array(
"Title" => POST['Title'],
etc
)
The question is: when a value is a list of inner arrays such as the case with AdditionalCitizenship can I use names of inputs as arrays?
<input type="text" name=AdditionalCitizenship[Array1]['CountryOfResidency']>
<input type="text" name=AdditionalCitizenship[Array2]['CountryOfResidency']>
Yes, except you would use
<input type="text" name="AdditionalCitizenship[0][CountryOfResidency]">
<input type="text" name="AdditionalCitizenship[0][TaxIdentificationNumber]">
<input type="text" name="AdditionalCitizenship[1][CountryOfResidency]">
<input type="text" name="AdditionalCitizenship[1][TaxIdentificationNumber]">
In your $_POST array this will look like
"AdditionalCitizenship" => array(
array(
"CountryOfResidency" => 0,
"TaxIdentificationNumber" => null
),
array(
"CountryOfResidency" => 0,
"TaxIdentificationNumber" => null
)
)

Array multisort not working for an array

$artists = [
0 => [
"id" => "3",
"plan_id" => "1",
"name" => "Artist-A",
"views" => "1189189",
"soundcloud" => "42",
"facebook" => "59881948",
"twitter" => "21760757",
"youtube" => 0,
"instagram" => "3429017"
],
1 => [
"id" => "10",
"plan_id" => "1",
"name" => "Artist-B",
"views" => "1",
"soundcloud" => 0,
"facebook" => 0,
"twitter" => 0,
"youtube" => 0,
"instagram" => 0
],
2 => [
"id" => "2",
"plan_id" => "1",
"name" => "Artist-C",
"views" => "1629",
"soundcloud" => "20",
"facebook" => "5025158",
"twitter" => "582899",
"youtube" => 0,
"instagram" => "112127"
],
3 => [
"id" => "4",
"plan_id" => "2",
"name" => "Artist-D",
"views" => "484353",
"soundcloud" => "7",
"facebook" => "104449606",
"twitter" => "36820201",
"youtube" => 0,
"instagram" => "16483226"
],
4 => [
"id" => "5",
"plan_id" => "2",
"name" => "Artist-E",
"views" => "98765432",
"soundcloud" => "13",
"facebook" => "59551072",
"twitter" => "38995648",
"youtube" => 0,
"instagram" => "64997436"
]
]
foreach ($remaining_artists as $key => $value) {
$soundcloud[$key] = $value['soundcloud'];
}
array_multisort($soundcloud, SORT_ASC, $artists);
I use array_multisort to sort array. It's working perfectly fine. But there is an error 'array_multisort(): Array sizes are inconsistent' for the above array. I really can't figure out what's the problem here and its solution.
Your array_multisort() parameters were out of order.
http://php.net/manual/en/function.array-multisort.php
Also, syntax problems.
This works
<?php
$artists = [
0 => [
"id" => "3",
"plan_id" => "1",
"name" => "Artist-A",
"views" => "1189189",
"soundcloud" => "42",
"facebook" => "59881948",
"twitter" => "21760757",
"youtube" => 0,
"instagram" => "3429017"
],
1 => [
"id" => "10",
"plan_id" => "1",
"name" => "Artist-B",
"views" => "1",
"soundcloud" => 0,
"facebook" => 0,
"twitter" => 0,
"youtube" => 0,
"instagram" => 0
],
2 => [
"id" => "2",
"plan_id" => "1",
"name" => "Artist-C",
"views" => "1629",
"soundcloud" => "20",
"facebook" => "5025158",
"twitter" => "582899",
"youtube" => 0,
"instagram" => "112127"
],
3 => [
"id" => "4",
"plan_id" => "2",
"name" => "Artist-D",
"views" => "484353",
"soundcloud" => "7",
"facebook" => "104449606",
"twitter" => "36820201",
"youtube" => 0,
"instagram" => "16483226"
],
4 => [
"id" => "5",
"plan_id" => "2",
"name" => "Artist-E",
"views" => "98765432",
"soundcloud" => "13",
"facebook" => "59551072",
"twitter" => "38995648",
"youtube" => 0,
"instagram" => "64997436"
]
];
$soundcloud = [];
foreach ($artists as $key => $value) {
$soundcloud[$key] = $value['soundcloud'];
}
array_multisort($soundcloud, $artists, SORT_ASC);
print_r($artists);

Categories