How to add item to an object in php - php

I have a nested object which is generated by a base data in a function. the data generated is several levels deep (data_tree)
To enter each children I use a recursive function.
What I want is to add the data of the children2 item to children and remove children2
Next I show the data_tree in JSON format to get an idea of ​​how the structure is. remember that the data_tree is an object
{
"data_tree": [
{
"code":"PE",
"country":"Peruvian",
"language" :"spanish",
"children":[
{
"code": "DEP1" ,
"region":"Tumbes",
"children": [
{
"code": "PRO1",
"province":"Contralmirante Villar"
}
],
"children2": [
{
"code": "PRO2",
"province":"Zarumilla "
}
]
},
{
"code": "DEP2" ,
"region":"Piura",
"children": [],
"children2": [
{
"code": "PRO4",
"province" :"Paita"
},
{
"code": "PRO5",
"province":"Sullana"
}
]
},
{
"code": "DEP3" ,
"region":"Lambayeque"
}
],
"children2":[
{
"code": "DEP4" ,
"region":"La Libertad"
},
{
"code": "DEP5" ,
"region":"Lima"
}
]
},
{
"code":"EC"
"country":"Ecuador",
"language" :"spanish",
"children":[
{
"code": "4" ,
"province":"Quito"
},
{
"code": "5" ,
"province":"Guayaquil"
}
],
"children2":[]
}
]
}
the recursive function i use is: if it has children it keeps iterating.
$traverse = function ($data_tree) use (&$traverse) {
foreach ($data_tree as &$node) {
if (empty($node->children)) { //if the children is empty
unset($node->children); //I remove the children to add it with the data of children2
$node->children =$node->children2;
unset($node->children2);//I delete children2
}else{
//in case I have data, how do I add the data from dechildren2 to children?
}
$traverse($node->children);
}
};
$traverse($data_tree);
return $data_tree;

All problem solved using json decode mean in associative array
$data_json='[{"children":[],"children2":[{"children":[],"children2":[{"code":"PRO1","children":[],"children2":[{"code":"PRO1"}]}]}]},{"children":[],"children2":[{"children":[{"code":"PRO1","children":[],"children2":[{"code":"PRO1"}]}]}]}]';
//$data_tree=;
$data_tree =json_decode($data_json,true);
// var_dump($data_tree);
$traverse = function (&$data_tree) use (&$traverse) {
foreach ($data_tree as &$node) {
// var_dump($node);
if (empty($node['children']) && !empty($node['children2'])) { //if the children is empty
// var_dump($node);
$node['children'] =$node['children2'];
unset($node['children2']);//I delete children2
}else{
//in case I have data, how do I add the data from dechildren2 to children?
}
if(isset($node['children'])){
$traverse($node['children']);
}
if(isset($node['children2'])){
$traverse($node['children2']);
}
}
};
$traverse($data_tree);
Output
[{"children":[{"children":[{"code":"PRO1","children":[{"code":"PRO1"}]}]}]},{"children":[{"children":[{"code":"PRO1","children":[{"code":"PRO1"}]}]}]}]

Related

PHP array of objects traversing

I have this array of objects:
Array A:
[
{
"id":1,
"type":"title",
"data": "Title goes here"
},
{
"id":2,
"type":"repeat"
"number":3,
},
{
"id":3,
"type":"media"
"data": "path to media"
},
{
"id":4,
"type":"close_repeat"
},
{
"id":5,
"type":"repeat"
"number":3,
},
{
"id":6,
"type":"title",
"data": "Title goes here"
},
{
"id":7,
"type":"repeat"
"number":2,
},
{
"id":8,
"type":"text"
"data": "Text goes here"
},
{
"id":9,
"type":"close_repeat"
},
{
"id":10,
"type":"close_repeat"
},
{
"id":11,
"type":"cover",
"data": "Cover data goes here"
},
]
And I want to transfer it into:
Array B
[
{
"id":1,
"type":"title",
"data": "Title goes here",
"repeat":1
},
{
"id":3,
"type":"media"
"data": "path to media",
"repeat":1
},
{
"id":6,
"type":"title",
"data": "Title goes here",
"repeat":3
},
{
"id":8,
"type":"text"
"data": "Text goes here",
"repeat":6
},
{
"id":11,
"type":"cover",
"data": "Cover data goes here",
"repeat":1
},
]
The idea is that Array A (the original) has two special objects of type repeat and close_repeat. Objects of type repeat have an extra attribute called number. The value of this attribute specifies how many times the objects between repeat and close_repeat should be repeated. Further more, repeat and close_repeat can be nested so that if we strat repeat then before closing it we start another repeat then the objects that follows have to be repeated based on the multiples of the two repeats. So in the Array A, object with id:8 should be repeated 6 times because the repeat of the repeat of object with id:5 and id:7 in which 3*2 = 6. Now I don't want yet to repeat the objects in the resulting array but simply add a new attribute to each object which says how many times an object should be repeated. As it can be seen in array B object with id:8: it should have a new attribute called repeatand should have the value of6`. I'm struggling to wrap my head around it.
I tried with loops and recursions but I was never even close to anything.
public function loopOver($data, &$newData, &$repeat, &$previousRepeat, $i){
$dataCount = count($data);
for( ; $i<$dataCount; $i++){
if($data[$i]['type']=='repeat'){
$previousRepeat = $data[$i]['number'];
$repeat = $repeat * $data[$i]['number'];
return $this->loopOver($data, $newData, $repeat, $previousRepeat, $i+1);
}
if($data[$i]['type']=='close_repeat'){
$repeat = $repeat/$previousRepeat;
return $this->loopOver($data, $newData, $repeat, $previousRepeat, $i+1);
}
if($i >= $dataCount){
return $newData;
}
$tmpData = $data[$i];
$tmpData['repeat'] = $repeat;
$newData [] = $tmpData;
}
}
The above codes returns the correct list but the repeat is not accurate.
$data = [
[
"id"=>1,
"type"=>"title",
"data"=> "Title goes here"
],
[
"id"=>2,
"type"=>"repeat",
"number"=>3,
],
[
"id"=>3,
"type"=>"media",
"data"=> "path to media"
],
[
"id"=>4,
"type"=>"close_repeat"
],
[
"id"=>5,
"type"=>"repeat",
"number"=>3,
],
[
"id"=>6,
"type"=>"title",
"data"=> "Title goes here"
],
[
"id"=>7,
"type"=>"repeat",
"number"=>2,
],
[
"id"=>8,
"type"=>"text",
"data"=> "Text goes here"
],
[
"id"=>9,
"type"=>"close_repeat"
],
[
"id"=>10,
"type"=>"close_repeat"
],
[
"id"=>11,
"type"=>"cover",
"data"=> "Cover data goes here"
],
];
$newData = array();
$new_arr = array();
$count_arr = 0;
foreach ($data as $arr) {
if (key_exists('data', $arr)) {
$new_arr[$count_arr++] = $arr;
}
}
$count_arr = 0;
$repeat = 0;
$first_key = array_key_first($new_arr);
$last_key = array_key_last($new_arr);
foreach ($new_arr as $key => $value) {
$newData[$key] = $value;
// Create repeat key and set value
if ($key == $first_key) {
// repeat key value for first arr
$newData[$count_arr++]['repeat'] = $new_arr[$repeat++]['id'];
} elseif ($key == $last_key) {
// repeat key value for last arr (same as first repeat key value)
$newData[$count_arr++]['repeat'] = $new_arr[$first_key]['id'];
} else {
// repeat key value for others array
$newData[$count_arr++]['repeat'] = $new_arr[$repeat++ - 1]['id'];
}
}
// new data
echo '<pre>';
print_r($newData);
echo '</pre>';

Firestore document not incrementing using REST API

I am trying to increment my Cloud Firestore using the REST API, however the documentation is unclear as to how this works. Here is my current implementation:-
I am trying to increment the integer value 'c' by 2, so if server value stored is 10 I want it to become 12 with this. Please help.
{
"writes": [
{
"currentDocument": {
"exists": true
}
},
{
"transform": {
"document": "projects/project_name/databases/(default)/documents/collection_name/user_id",
"fieldTransforms": [
{
"increment": {
"c": {
"integerValue": "2"
}
}
}
]
}
}
]
}
Error I keep getting:-
{
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"\": Root element must be a message.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"\": Root element must be a message."
}
]
}
]
}
}
Edit: Here's the error after fixing my payload:
{
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"writes\" at 'document': Cannot find field.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "document",
"description": "Invalid JSON payload received. Unknown name \"writes\" at 'document': Cannot find field."
}
]
}
]
}
}
As per the FieldTransform documentation, you must set a fieldPath on your JSON representation. Here's the list of possible types for union field transform_type:
{
"fieldPath": string,
// Union field transform_type can be only one of the following:
"setToServerValue": enum (ServerValue),
"increment": {
object (Value)
},
"maximum": {
object (Value)
},
"minimum": {
object (Value)
},
"appendMissingElements": {
object (ArrayValue)
},
"removeAllFromArray": {
object (ArrayValue)
}
// End of list of possible types for union field transform_type.
}
You should remove the fieldPath which is c inside the increment:
"fieldTransforms": [
{
"increment": {
"c": {
"integerValue": "2"
}
}
}
]
and change it to this structure:
"fieldTransforms": [
{
"fieldPath": "<FieldName>",
"increment": {
"integerValue": "2"
}
}
]
And also, just want to note that currentDocument and transform should be both inside the objects of writes. For reference, here's the full JSON representation based on your given JSON representation above:
{
"writes": [
{
"currentDocument": {
"exists": true
},
"transform": {
"document": "projects/project_name/databases/(default)/documents/collection_name/user_id",
"fieldTransforms": [
{
"fieldPath": "c",
"increment": {
"integerValue": "2"
}
}
]
}
}
]
}
Here's the result by using the Postman:
For more information, you may want to check Firebase REST API: Write.

PHP Select Data from Json

My JSON Data
{
"users": [
{
"userid": 1,
"username": "Admin",
"usermail": "admin#admin.com",
"authority": [
{
"authorityid": 1,
"authoritytext": "Admin",
"mission": [
{
"permission": "add"
},
{
"permission": "delete"
},
{
"permission": "move"
}
]
},
{
"authorityid": 1,
"authoritytext": "Super Admin",
"mission": [
{
"permission": "no add"
},
{
"permission": "no delete"
},
{
"permission": "only moderate"
}
]
}
]
}
]
}
MY PHP
foreach($result->users as $ok) {
foreach($ok->authority as $okey) {
foreach($okey->mission as $okeyokey) {
$test = $okeyokey->permission;
echo $test;
}
}
}
How to make this?
I want show parse json only authority{0} -> misson{0} show "permission" "add" please help me .
Maybe look ScreenShot >>>>>
I want filter {0}{1}{2} and select 0 -> show parse json
enter image description here
Is this what you are looking for?
<?php
$jsonData = '{
"users": [
{
"userid": 1,
"username": "Admin",
"usermail": "admin#admin.com",
"authority": [
{
"authorityid": 1,
"authoritytext": "Admin",
"mission": [
{
"permission": "add"
},
{
"permission": "delete"
},
{
"permission": "move"
}
]
},
{
"authorityid": 1,
"authoritytext": "Super Admin",
"mission": [
{
"permission": "no add"
},
{
"permission": "no delete"
},
{
"permission": "only moderate"
}
]
}
]
}
]
}';
$data = json_decode($jsonData);
echo($data->users[0]->authority[0]->mission[0]->permission);
You are getting objects and arrays confused
foreach($result->users as $currentUser){
$auths = $currentUser->authority;
foreach($auths as $currentAuth){
foreach($currentAuth->mission as $permission){
foreach($permission as $positionLabel => $permissionValue){
if($permissionValue == "add"){
// code here
}
}
}
}
}
Make sure you are using good labels. Dummy placeholders can be fine, but it makes tracking bugs really hard. I assume you want to check if they hold permission using a database, using PDO?
// array
$arr = ["this", "is", "an", "array"];
echo $arr[0] // prints out the word this.
$json = { "attribute": "value"}
echo $json->attribute // prints out the word value.
You can have arrays in JSON objects, and JSON Objects in arrays. How you access them are different.

JSON data should not have key value in numeric and result not coming as per expected result

I am creating JSON with nested set model using recursion. My result is not coming as expected, as this JSON helps me to generate a tree. The brackets are not coming as in required JSON.
i am trying to create a json like this http://fperucic.github.io/treant-js/examples/evolution-tree/example6.js . i am interested in nodeStructure: { }
Issue:
every children has { } but required [ ]
Not required numeric keys
json keys should not come in quotes like "text", "children, "name" , its should come witout quotes
Online compiler: https://3v4l.org/UsXPv
<?php
$category = '{"9":{"id":"9","btc_mlm_user_id":"0","lft":"1","rht":"16","lvl":"0","name":"Root","created":"2017-06-27 05:56:11","modified":"2017-06-27 05:56:11","first_name":"","last_name":"","username":""},"42":{"id":"42","btc_mlm_user_id":"25","lft":"2","rht":"13","lvl":"1","name":"naresh","created":"2017-11-02 10:22:24","modified":"2017-11-02 10:22:24","first_name":"","last_name":"","username":"naresh"},"44":{"id":"44","btc_mlm_user_id":"27","lft":"3","rht":"4","lvl":"2","name":"rahul1","created":"2017-11-02 10:25:53","modified":"2017-11-02 10:25:53","first_name":"","last_name":"","username":"rahul1"},"45":{"id":"45","btc_mlm_user_id":"28","lft":"5","rht":"6","lvl":"2","name":"rahul123","created":"2017-11-02 10:27:19","modified":"2017-11-02 10:27:19","first_name":"","last_name":"","username":"rahul123"},"46":{"id":"46","btc_mlm_user_id":"29","lft":"7","rht":"12","lvl":"2","name":"kapil1","created":"2017-11-02 10:28:20","modified":"2017-11-02 10:28:20","first_name":"","last_name":"","username":"kapil1"},"47":{"id":"47","btc_mlm_user_id":"30","lft":"8","rht":"11","lvl":"3","name":"priya12","created":"2017-11-02 10:30:30","modified":"2017-11-02 10:30:30","first_name":"","last_name":"","username":"priya12"},"48":{"id":"48","btc_mlm_user_id":"31","lft":"9","rht":"10","lvl":"4","name":"amit12","created":"2017-11-02 10:32:00","modified":"2017-11-02 10:32:00","first_name":"","last_name":"","username":"amit12"},"43":{"id":"43","btc_mlm_user_id":"26","lft":"14","rht":"15","lvl":"1","name":"roshan","created":"2017-11-02 10:24:27","modified":"2017-11-02 10:24:27","first_name":"","last_name":"","username":"roshan"}}';
function tree($data, $left = 0, $right = null)
{
$tree = array();
foreach ($data as $key => $value)
{
if ($value['lft'] == $left + 1 && (is_null($right) || $value['rht'] < $right))
{
$tree[$key]['text'] = ['name' => $value['name']];
$tree[$key]['children'] = tree($data, $value['lft'], $value['rht']);
$left = $value['rht'];
}
}
return $tree;
}
$tree = tree(json_decode($category, true));
echo json_encode($tree);
Output:
{
"9": {
"text": {
"name": "Root"
},
"children": {
"42": {
"text": {
"name": "naresh"
},
"children": {
"44": {
"text": {
"name": "rahul1"
},
"children": []
},
"45": {
"text": {
"name": "rahul123"
},
"children": []
},
"46": {
"text": {
"name": "kapil1"
},
"children": {
"47": {
"text": {
"name": "priya12"
},
"children": {
"48": {
"text": {
"name": "amit12"
},
"children": []
}
}
}
}
}
}
},
"43": {
"text": {
"name": "roshan"
},
"children": []
}
}
}
}
Required output:
{
text: {
name: "Root"
},
children: [{
text: {
name: "naresh"
},
children: [{
text: {
name: "rahul1"
},
children: [
[]
],
text: {
name: "rahul123"
},
children: [
[]
],
text: {
name: "kapil1"
},
children: [{
text: {
name: "priya12"
},
children: [{
text: {
name: "amit12"
},
children: [
[]
]
}]
}]
}],
text: {
name: "roshan"
},
children: [
[]
]
}]
}
Here is my MySql records which are i am fetching here to show you in $category json in start.
If you want to get the output you linked, rather than the one in your question (which is invalid as pointed by #RoryMcCrossan, because it contains multiple equal keys per object), then you can change your code to this:
function tree($data, $left = 0, $right = null) {
$tree = array();
foreach ($data as $key => $value) {
if ($value['lft'] == $left + 1 && (is_null($right) || $value['rht'] < $right)) {
$child = []; // Let's make a new child
$child['text'] = ['name' => $value['name']]; // The text is required
$childTree = tree($data, $value['lft'], $value['rht']); // Let's find its children
if (!empty($childTree)) { // If it has children
$child['children'] = $childTree; // Let's save the children
}
$tree[] = $child; // Put the child in the tree
$left = $value['rht'];
}
}
return $tree;
}
$tree = tree(json_decode($category, true))[0]; // Since there's only one root, you want the first element of the tree
Here's the full code: https://3v4l.org/AYCGt
That just leaves you with one problem, according to you, the keys shouldn't have quotes around them. Although I don't really know your motives and it should work with the quotes in Javascript, you could do some replacements using preg_replace, like this:
echo preg_replace('/"(\w+)":/','$1:',json_encode($tree));
This would be the complete code: https://3v4l.org/ZaXip

elasticsearch query by array of id result returned is not sorted by the array of id pass in

I am using elastica and below is my query :
$query = new Query();
$query->setSize(5);
$qb = new \Elastica\Query\Ids();
$qb->addId("id_5");
$qb->addId("id_3");
$qb->addId("id_4");
$qb->addId("id_1");
$qb->addId("id_2");
return $query->setQuery($qb)
I want the result return in the same order as what I passed in for example in this case it will be "id_5, id_3, id_4, id_1, id_2"
however what i get is the sorting is not the same as what I wanted
I see this as two solution
1. if you have id as part of document then you can do
POST indexName/_search
{
"sort": [
{
"_script": {
"type": "number",
"script": "sortOrder.indexOf(doc['Id'].value)",
"params": {
"sortOrder": [
"AVMX9sHTyNVr4SjF3oRt",
"AVMTc1fSyNVr4SjF3WpF",
"AVMYuGLOyNVr4SjF3rKm"
]
},
"order": "asc"
}
}
],
"query": {
"ids": {
"values": [
"AVMX9sHTyNVr4SjF3oRt",
"AVMTc1fSyNVr4SjF3WpF",
"AVMYuGLOyNVr4SjF3rKm"
]
}
}
}
If not then you need to update mapping for your type to be
{
"mappings": {
"YOUR_TYPE": {
"_id": {
"index": "not_analyzed"
}
}
}
}
Then you can use "script": "sortOrder.indexOf(doc['_id'].value)"

Categories