I tried to use ORM to find list of provinces and their cities.
the result is same as this list:
"provinces": [
{
"name": "Prov.1",
"Cities": {
"name": "City.1"
}
},
{
"name": "Prov.1",
"Cities": {
"name": "City.2"
}
},
]
what is expected:
"provinces": [
{
"name": "Prov.1",
"Cities": [
{
"name": "City.1"
},
{
"name": "City.2"
}
]
},
]
used ORM:
Provinces::find('all', [
'with' => ['Cities']
]);
Something like
$array = [];
foreach($provinces as $province){
$key = $province['name'];
if(!isset($array[$key])){
$array[$key] = [
'name' => $province['name'],
'Cities' => [
[ 'name' => $province['Cities']['name']];
]
];
}else{
$array[$key]['Cities'][] = ['name' => $province['Cities']['name']];
}
}
//strip keys
$array = array_values($array);
Because you don't have an actual PHP array posted I'm just guessing at what it should be.
Related
I have the following JSON object:
{
"id": 1,
"name": null,
"block": {
"type": "none",
"descends": [
{
"operation":"sum",
"descends":[
{
"label":2,
"value":false
}
]
},
{
"label": 1,
"value": 3,
},
{
"label": 2,
"value": 2
}
],
"label": 1,
"value": true
}
}
I want to collect all the label and value attributes and store them in an array, so I created the following function:
public function collectValues($arr){
$finalValues = [];
foreach($arr as $key => $element){
if($key=='block'){
foreach($element as $key2 => $block){
if($key2=='descends'){
foreach($block as $key3 => $node_block){
if($key3=='descends'){
foreach($node_block as $key4 => $anotherNode){
if($key4 == 'descends'){
foreach($anotherNode as $finalNode){
$finalValues [] = array('lable'=>$finalNode->label, 'value' =>$finalNode->value);
}
}
}
}
else{
$finalValues [] = array('lable' => $node_block->label, 'value' => $node_block->value);
}
}
}
}
$finalValues [] = array('lable'=> $element->label, 'value' => $element->value);
}
}
return $finalValues;
}
The function works and I get the following:
[
{
"lable": 2,
"value": false
},
{
"lable": 1,
"value": 3
},
{
"lable": 2,
"value": 2
},
{
"lable": 1,
"value": true
}
]
The problem is that the JSON object can contain more descends like:
{
"id": 1,
"name": null,
"block": {
"type": "none",
"descends": [
{
"operation":"sum",
"descends":[
{
"operation":"sum",
"descends":[
{
"label":2,
"value":false
}
],
"label":2,
"value":false
}
]
},
{
"operation":"sum",
"descends":[
{
"label":2,
"value":false
}
],
"label": 1,
"value": 3,
},
{
"label": 2,
"value": 2
}
],
"label": 1,
"value": true
}
}
This means I will have to add more foreach loops. A good way to handle such a situation is by using recursive. How can I transform the function above into a recursive one?
Your looped function does not make sense to change. Easier to rewrite from scratch
Here is my use case for recursion. Maybe there is an easier option, but I didn’t chase optimization
$array = json_decode($json, true); //in $json your JSON)
$result = []; // array for result
checkLabel($array, $result);
print_r($result);
function checkLabel(array $array, &$result){
//first check every element on nested array
foreach ($array as $key => $value){
if (is_array($value)) {
//if found call recursive function
checkLabel($value, $result);
}
}
//then check 'label' key.. its mean we have attribute
if (array_key_exists('label', $array)) {
//save it
$result[] = [
'label' => $array['label'],
'value' => $array['value']??'' //if have label but without value)
];
}
}
I need to send Json with one of the parameters being an array . The following code works perfectly .
$html = $client->post($url,
['json'=>[ 'requestData'=>
[
'sessionID'=>'261-7306141-0539957'
]
,
'productTargets'=>
[
[ 'ProductID'=>$data[0] ],
[ 'ProductID'=>$data[1] ],
[ 'ProductID'=>$data[2] ],
[ 'ProductID'=>$data[3] ],
[ 'ProductID'=>$data[4] ],
],
] ]
);
As you can see I am manually entering data[0],data[1],data[2] in productTargets . I need to send multiple like 100's of
'ProductID' object . I tried using
json_encode( [ [ 'ProductID'=>$data[0] ],
['ProductID'=>$data[2] ],
['ProductID'=>$data[3] ],
['ProductID'=>$data[4] ], ]
)
But it's not working . How do I send the data
Perhaps an approach like this:
<?php
$data =
[
'json' =>
[
'requestData'=>
[
'sessionID'=>'261-7306141-0539957'
]
]
];
$ids = range(1, 4); // Some dummy ids.
shuffle($ids);
$product_ids = array_map(function($v) {
return ['ProductID' => $v];
}, $ids);
$data['json']['productTargets'] = $product_ids;
var_dump(json_encode($data, JSON_PRETTY_PRINT));
Example output:
string(383) "{
"json": {
"requestData": {
"sessionID": "261-7306141-0539957"
},
"productTargets": [
{
"ProductID": 4
},
{
"ProductID": 3
},
{
"ProductID": 1
},
{
"ProductID": 2
}
]
}
}"
I'm trying to use a PHP mongo library to "aggregate" on a data structure like this:
{
"_id": 100,
"name": "Joe",
"pets":[
{
"name": "Kill me",
"animal": "Frog"
},
{
"name": "Petrov",
"animal": "Cat"
},
{
"name": "Joe",
"animal": "Frog"
}
]
},
{
"_id": 101,
"name": "Jane",
"pets":[
{
"name": "James",
"animal": "Hedgehog"
},
{
"name": "Franklin",
"animal": "Frog"
}
}
For example, if I want to get all subdocuments where the animal is a frog. Note that I do NOT want all matching "super-documents" (i.e. the ones with _id). I want to get an ARRAY that looks like this:
[
{
"name": "Kill me",
"animal": "Frog"
},
{
"name": "Joe",
"animal": "Frog"
},
{
"name": "Franklin",
"animal": "Frog"
}
]
What syntax am I supposed to use (in PHP) to accomplish this? I know it has to do with aggregate, but I couldn't find anything that matches this specific scenario.
You can use below aggregation. $match to find documents where array has a value of Frog and $unwind the pets array. $match where document has Frog and final step is to group the matching documents into array.
<?php
$mongo = new MongoDB\Driver\Manager("mongodb://localhost:27017");
$pipeline =
[
[
'$match' =>
[
'pets.animal' => 'Frog',
],
],
[
'$unwind' =>'$pets',
],
[
'$match' =>
[
'pets.animal' => 'Frog',
],
],
[
'$group' =>
[
'_id' => null,
'animals' => ['$push' => '$pets'],
],
],
];
$command = new \MongoDB\Driver\Command([
'aggregate' => 'insert_collection_name',
'pipeline' => $pipeline
]);
$cursor = $mongo->executeCommand('insert_db_name', $command);
foreach($cursor as $key => $document) {
//do something
}
?>
How can I add an array to array position:
Something like a:
<?php
$newArr = array('email' => array("id" => "5678", "token" => "fghjk"));
$arr = array(
"auth"=>
array(
'users'=>
array(
'id' =>"456yhjoiu",
'token' => "asdfghjkrtyui678"
)
)
);
somefunction($arr['auth'], $newArr);
I've tried array_push() but it added zero (0) before 'email' instead.~
I'm doing this to get a json output, something like this:
}
"auth": {
"users": {
"id": "456yhjoiu",
"token": "asdfghjkrtyui678"
},
"email": {
"id": "5678",
"token": "fghjk"
}
}
}
but I have this output:
{
"auth": {
"users": {
"id": "456yhjoiu",
"token": "asdfghjkrtyui678"
},
"0": {
"email": {
"id": "5678",
"token": "fghjk"
}
}
}
$data = ['auth' => array_merge($arr['auth'], $newArr)];
or old array notation <= PHP5.3
$data = array('auth' => array_merge($arr['auth'], $newArr));
How to get the polygon coordinates of a specific property. It's very a huge file so the time to parse the file is a factor.
Is there a library to do that?
Sample of the geojson:
{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:EPSG::37001" } },
"features": [
{ "type": "Feature", "properties": { "HOOD_ID": 2799.000000, "HOOD_NAME": "Overtown", "MARKET_ID": "MK1245000", "MARKET": "Miami", "STATE": "12", "STATENAME": "Florida", "LATITUDE": 25.784659, "LONGITUDE": -80.202625, "AREA": 1.495920, "HLEVEL": 2.000000, "DATE_ADDED": "2012\/08\/04", "FLAG1": 0, "OB_GEO_ID": "NH2799" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -80.21463341110001, 25.782154451300002 ], [ -80.21588353300001, 25.782696872700001 ], [ -80.217973576800006, 25.7833078056 ], [ -80.219539583200003, 25.784199528800002 ], [ -80.211531118000011, 25.787386122500003 ], [ -80.20836940560001, 25.789128957700001 ], [ -80.206422272200001, 25.789848709300003 ], [ -80.2060101207, 25.7907922853 ], [ -80.206013661300005, 25.793566844899999 ], [ -80.206013794, 25.7968569831 ], [ -80.202368489099996, 25.796952708299997 ], [ -80.202379, 25.797313 ], [ -80.199836, 25.797309 ], [ -80.199819759600004, 25.7970196375 ], [ -80.1993398571, 25.797032239699998 ], [ -80.193583490500004, 25.797234161599999 ], [ -80.193806159800005, 25.796203267299997 ], [ -80.194272724399994, 25.7951752727 ], [ -80.193944, 25.795182 ], [ -80.194266, 25.793434 ], [ -80.195336, 25.789592 ], [ -80.195534, 25.787847 ], [ -80.195514, 25.778409 ], [ -80.195969425200005, 25.778397321299998 ], [ -80.19557104899999, 25.773179598799999 ], [ -80.195360063199999, 25.768486166300001 ], [ -80.196768768399991, 25.7682545324 ], [ -80.198226099099998, 25.768721241800002 ], [ -80.199164023899996, 25.769800189500003 ], [ -80.199997701599997, 25.770738292499999 ], [ -80.200414826200003, 25.772286616100001 ], [ -80.200936435800003, 25.773272690900001 ], [ -80.202343232900006, 25.7749143389 ], [ -80.204375245, 25.776884093299998 ], [ -80.205990323199998, 25.777259031 ], [ -80.206835373600001, 25.777897973199998 ], [ -80.207587, 25.777601 ], [ -80.210881, 25.78 ], [ -80.21463341110001, 25.782154451300002 ] ] ] } },
{ "type": "Feature", "properties": { "HOOD_ID": 2169.000000, "HOOD_NAME": "Church District", "MARKET_ID": "MK1235000", "MARKET": "Jacksonville", "STATE": "12", "STATENAME": "Florida", "LATITUDE": 30.332174, "LONGITUDE": -81.660212, "AREA": 0.131745, "HLEVEL": 1.000000, "DATE_ADDED": "2012\/08\/04", "FLAG1": 0, "OB_GEO_ID": "NH2169" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -81.664799, 30.331204 ], [ -81.663868, 30.334826 ], [ -81.655617, 30.333239 ], [ -81.656717, 30.329439 ], [ -81.664799, 30.331204 ] ] ] } }
}
Large files can best be parsed using an event-based JSON parser (here I use one by kuma-giyomu). The idea is to use callbacks when a certain token is encountered, so that the processing of the data can be done in between parsing.
In the following code, the property "coordinates" is used to trigger the creation of a new polygon object, and then the start function of the array handler to start a new coordinate array and it is submitted to the polygon object when an array end token is encountered.
<?php
include "JSONParser.php";
class Polygon {
public $coordinates = array();
}
$coords = null;
$polygons = array();
$polygon = null;
$j = new JSONParser();
$j->setPropertyHandler(function($value, $property) {
global $polygons, $polygon;
if ($value != "coordinates") {
if (!is_null($polygon)) {
$polygons[] = $polygon;
$polygon = null;
}
return;
}
if (is_null($polygon)) {
$polygon = new Polygon;
}
});
$j->setArrayHandlers(function($value, $property) {
global $coords, $polygon;
if (!is_null($polygon)) {
$coords = array();
}
}, function($value, $property) {
global $coords, $polygon;
if (!is_null($coords)) {
if (!is_null($polygon)) {
$polygon->coordinates[] = $coords;
}
$coords = null;
}
});
$j->setScalarHandler(function($value, $property) {
global $coords;
if (!is_null($coords)) {
$coords[] = $value;
}
});
try {
$j->parseDocument("test.json");
} catch (JSONParserException $e) {
}
if (!is_null($polygon)) {
$polygons[] = $polygon;
$polygon = null;
}
print_r($polygons);
outputs
Array
(
[0] => Polygon Object
(
[coordinates] => Array
(
[0] => Array
(
[0] => -80.21463341110001
[1] => 25.782154451300002
)
[1] => Array
(
[0] => -80.21588353300001
[1] => 25.782696872700001
)
[...]