PHP array of objects traversing - php

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>';

Related

How to add item to an object in 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"}]}]}]}]

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

array of objects selecting object based on attribute value

I am working with the Mailchimp API at the moment, I have a list of campaigns that have been run, or are due to be run, and I wanting to get the link for the most recently run campaign. How would I go about comparing the attribute "send_time" to find the most recent and it's attributed parent object?
The campaigns array looks like this,
{
"campaigns": [
{
"id": 1,
"type": "regular",
"status": "save",
"send_time": ""
},
{
"id": 2,
"type": "regular",
"status": "sent",
"send_time": "2015-11-11T14:42:58+00:00"
},
{
"id": 3,
"type": "regular",
"status": "sent",
"send_time": "2016-01-01T14:42:58+00:00"
},
{
"id": 4,
"type": "regular",
"status": "sent",
"send_time": "2016-06-12T14:42:58+00:00"
}
]
}
So in that above array, the final object has the most recent send_time, how would I assess this, and then grab that object? I have a semi solution, but it seems long winded.
<?php
//Build an array of send_times
$dates = [];
foreach($result['campaigns'] as $campaign) {
$dates[$campaign['id']] = $campaign['send_time'];
}
//Get the most recent date
$mostRecent = 0;
foreach($dates as $k => $v) {
$curDate = strtotime($v);
if($curDate > $mostRecent) {
$mostRecent = $curDate
$currentId = $k;
}
}
//Get the object
foreach($results['campaigns'] as $campaign) {
if($campaign['id'] == $currentId) {
$c = $campaign;
}
}
?>
Use array_multisort() like below (single line code):-
<?php
$data = '{
"campaigns": [
{
"id": 1,
"type": "regular",
"status": "save",
"send_time": ""
},
{
"id": 2,
"type": "regular",
"status": "sent",
"send_time": "2015-11-11T14:42:58+00:00"
},
{
"id": 3,
"type": "regular",
"status": "sent",
"send_time": "2016-01-01T14:42:58+00:00"
},
{
"id": 4,
"type": "regular",
"status": "sent",
"send_time": "2016-06-12T14:42:58+00:00"
}
]
}';
$array = json_decode($data,true)['campaigns']; // decode json string to array
array_multisort($array,SORT_DESC, SORT_STRING); // use of array_multisort
echo "<pre/>";print_r($array); // this will returns you indexed array like 0,1,2... you can again convert it to campaigns array like $final_array['campaigns'] = $array;
?>
Output:- https://eval.in/598349
Note:-
1.If your given data is in array already then no need to use json_decode(), directly use array_multisort() on it
https://eval.in/598355
For more reference:-
http://sg2.php.net/manual/en/function.array-multisort.php
<?php
$dates = [];
$recent_campaign = null;
$recent_time = 0;
foreach($result['campaigns'] as $campaign) {
$curDate = strtotime($campaign['send_time']);
if($curDate > $recent_time) {
$recent_time = $curDate
$recent_campaign = $campaign;
}
}
//$recent_campaign is the most recent campaign
?>
You can try this approach. Else you can use usort by send_time (direct solution).
I have not executed this code!
You can sort your objects by that property (I'd suggest usort, so that you can define your own sorting) and then get the first item in that array.
usort($result, function ($campaign1, $campaign2) {
if ($campaign1['send_time'] == $campaign2['send_time']) {
return 0;
}
return (strtotime($campaign1['send_time']) > strtotime($campaign2['send_time'])) ? -1 : 1;
});
$mostRecentCampaign = $campaign[0];
Note: I haven't run this, so you might have to tweak the return on the compare function if it's sorting in the wrong order.
If you just want to grab the max element and want to use fewer lines of code, try this:
Grab the max time by mapping the "send time" column to an epoch time and getting the max value
Filter your array by the entries that correspond to that max time
Profit
Example:
$dataArray = /* your array */
$maxTime = max(array_map('strtotime',array_column($dataArray["campaigns"], 'send_time')));
$maxEntry = array_filter($dataArray["campaigns"], function ($arr) use ($maxTime) { return strtotime($arr["send_time"])==$maxTime; });
print_r($maxEntry);
Would print:
Array
(
[3] => Array
(
[id] => 4
[type] => regular
[status] => sent
[send_time] => 2016-06-12T14:42:58+00:00
)
)
Note The advantage of this is that it doesn't need sorting. The disadvantage is that sorting and then getting the last element would be faster. However with sorting you lose the original array order which is sometimes needed.

PHP: get data from json array without loop

I have data i want to get from array without loop.
I want to get "value" of "link_click" for example, how can i make this work?
I tried: but this not working.
$stats = json_decode($data, false);
$link_click= $stats->data->actions->action_type->['link_click']->value;
{
"data": [
{
"actions": [
{
"action_type": "comment",
"value": 2
},
{
"action_type": "link_click",
"value": 636
},
{
"action_type": "post_like",
"value": 2
},
{
"action_type": "page_engagement",
"value": 640
},
{
"action_type": "post_engagement",
"value": 640
}
],
The only way you can make it possible only if you know the index of the action_type:link_click. If you know the index, you can do it by. (Answer is with respect to the data you have shown above).
$stats = json_decode($data, true);
$link_click= $stats['data']['actions'][1]['value'];
Loop example (on request):
$stats = json_decode($data, true);
$value = 0;
foreach($stats['data']['actions'] as $action) {
if ($action->action_type == 'link_click') {
$value = $action->value;
}
}
echo $value; //This is your value
You can use something like JsonPath to get the value

Categories