Php - creating json object - php

I am trying to create a json object from the data that I get from Ninja Forms that would look like this:
{
"title": "Contact Me",
"fields": [
{
"label": "Name",
"type": "textbox",
"required": "1"
},
{
"label": "Email",
"type": "email",
"required": "1"
}
]
}
I am trying to do so, like this:
$settings = ['label', 'type', 'required'];
$formTitle = Ninja_Forms()->form( 1 )->get()->get_setting('title');
$formFields = Ninja_Forms()->form(1)->get_fields();
$data = ['title' => $formTitle];
foreach ($formFields as $formField) {
$key = $formField->get_setting('key');
foreach ($settings as $setting) {
$data['fields'][$key][][$setting] = $formField->get_setting($setting);
}
}
return $data;
But, the result of that looks like this:
{
"title": "Contact Me",
"fields": {
"name": [
{ "label": "Name" },
{ "type": "textbox" },
{ "required": "1"}
],
"email": [
{ "label": "Email" },
{ "type": "email" },
{ "required": "1" }
],
How can I do this, so that the result looks like the one I have shown above?
I have also tried like this:
foreach ($settings as $setting) {
$data['fields'][] = $formField->get_setting($setting);
}
But, that gave me this kind of result:
{
"title": "Contact Me",
"fields": [
"Name",
"textbox",
"1",
"Email",
"email",
"1",
"Message",
"textarea",
"1",
"Submit",
"submit",
null
]
}

This gave me the wanted result:
foreach ($formFields as $formField) {
$key = $formField->get_setting('key');
foreach ($settings as $setting) {
$object[$setting] = $formField->get_setting($setting);
}
$data['fields'][] = $object;
}
return $data;

One way to look at this is to count the dimensions of the data. In your desired format, the deepest item is:
{ "fields": [ { "label": "Name"
So you have object -> array -> object.
If we indent each array in your code, we have:
$data // outermost array
['fields']
[$key]
[] // innermost array
[$setting] = $value; // key in innermost array
Or if we were to declare it with just one value:
$data = array(
'field' => array(
$key => array(
0 => array(
$setting => $value
)
)
)
);
So you have 4 levels of array, instead of 3.
Comparing to the JSON, taking an array with numeric keys as "array" and one with non-numeric keys as "object", the pattern is object -> object -> array -> object.
So it's the [$key] we need to eliminate, because it's creating an extra object dimension.
But we don't want to increment the key at [] for each item either, so we need to either make our value in advance...
foreach ($settings as $setting) {
$object[$setting] = $formField->get_setting($setting);
}
$data['fields'][] = $object;
...or choose our key in advance:
$i++;
foreach ($settings as $setting) {
$data['fields'][$i] = $formField->get_setting($setting);
}

Related

PHP change a function from from loops to recursion

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)
];
}
}

Search with fragment of a string in multidimensional array

I have PHP array defined like this:
{
"data": [
{
"content": "Build your communication",
"property": null,
"name": "description"
},
{
"content": "simplify it",
"property": "og:title",
"name": null
},
{
"content": "unleash the effectiveness",
"property": "og:description",
"name": null
},
{
"content": "https:\/\/uploads-ssl.webflow.com\/\/%%20SETTINGS.png",
"property": "og:image",
"name": null
}
}
How can I search trough property keys and return just array groups where property field with values og: as a part of the string is defined.
$crawler = new Crawler(file_get_contents($url));
$items = $crawler->filter('meta');
$metaData = [];
foreach ($items as $item) {
$itemCrawler = new Crawler($item);
$content = $itemCrawler->eq(0)->attr('content');
$property = $itemCrawler->eq(0)->attr('property');
$name = $itemCrawler->eq(0)->attr('name');
$metaData = [
'content' => $content,
'property' => $property,
'name' => $name,
];
}
return $metaData;;
Tried with :
if(substr( $data['property'], 0, 3 ) === 'og:') {}
Returns just first one.
Can someone help?
This should work for you. $ret will hold all objects where the property "property" contains "og:".
$items = json_decode('{
"data": [
{
"content": "Build your communication",
"property": null,
"name": "description"
},
{
"content": "simplify it",
"property": "og:title",
"name": null
},
{
"content": "unleash the effectiveness",
"property": "og:description",
"name": null
},
{
"content": "https:\/\/uploads-ssl.webflow.com\/\/%%20SETTINGS.png",
"property": "og:image",
"name": null
}
]}');
$ret = array_filter($items->data, function($item) {
return strstr($item->property, "og:");
});
$data = [];
foreach ($items["data"] as $item) {
$content = item['content'];
$property = item['property'];
$name = item['name'];
$temp= [
'content' => $content,
'property' => $property,
'name' => $name,
];
array_push($data,$temp);
}
You have a "data" keyword before the array. Try this

PHP to split array of objects with title in array

I have an array of objects like below:
[
{
"TYPE": "food",
"NAME": "abc"
},
{
"TYPE": "fruit",
"NAME": "xyz"
},
{
"TYPE": "food",
"NAME": "def"
},
{
"TYPE": "food",
"NAME": "ghi"
},
]
How can I split this array of objects into multiple arrays such that the desired output looks like:
[
{
"TYPE": "food",
"ITEMS":
[
{
"TYPE": "food",
"NAME": "abc"
},
{
"TYPE": "food",
"NAME": "def"
},
{
"TYPE": "food",
"NAME": "ghi"
},
]
},
{
"TYPE": "fruit",
"ITEMS":
[
{
"TYPE": "fruit",
"NAME": "xyz"
},
]
},
]
Note that the parent object has its own identifier (TYPE)
I tried this:
$result = [];
foreach ($DT_DATA as $key => $value) {
$group = $value->TYPE;
if (!isset($result[$group])) {
$result[$group] = [];
}
$result[$group][] = $value;
}
$result = array_values($result);
But the parent group does not contain "TYPE" and also "ITEMS" array
Some improvements that will do the job:
$result = [];
foreach ($DT_DATA as $key => $value) {
$group = $value->TYPE;
if (!isset($result[$group])) {
// init with array of required structure
$result[$group] = [
'TYPE' => $group,
'ITEMS' => [],
];
}
// add $value to `ITEMS` subarray
$result[$group]['ITEMS'][] = $value;
}
$result = array_values($result);

With Php in a JSON array how to retrieve the value of an item according to another associated value?

I use json_decode Php function to get a JSON array of countries datas.
{
"Countries":
[
{
"Code": "AD",
"Name": "Andorre"
},
{
"Code": "AE",
"Name": "Émirats Arabes Unis"
},
{
"Code": "AF",
"Name": "Afghanistan"
},
{
"Code": "AG",
"Name": "Antigua-Et-Barbuda"
},
If I want to retrieve the Code of the 1st element I can do:
$result = json_decode($sXML);
$final = $result->Countries[0]->Name;
And $final will have the value of 'Andorre'.
But what if I want to retrieve the same value 'Andorre' using its correspoding Code ?
Is it possible to do it ?
I know there is an option for the json_function() to obtain an associative array instead of a JSON array, but how would you use it to get the value 'Andorre' using its Code ?
Thank you
<?php
$s = '{
"Countries":
[
{
"Code": "AD",
"Name": "Andorre"
},
{
"Code": "AE",
"Name": "Émirats Arabes Unis"
},
{
"Code": "AF",
"Name": "Afghanistan"
},
{
"Code": "AG",
"Name": "Antigua-Et-Barbuda"
}
]
}';
$arr = json_decode($s, true);
print_r(array_column($arr['Countries'], "Name", "Code"));
?>
yields
Array
(
[AD] => Andorre
[AE] => Émirats Arabes Unis
[AF] => Afghanistan
[AG] => Antigua-Et-Barbuda
)
Here we are using two function for achieving this array_column and array_combine to retrieve the expected output.
Try this code snippet here
<?php
ini_set('display_errors', 1);
$string='{
"Countries":
[
{
"Code": "AD",
"Name": "Andorre"
},
{
"Code": "AE",
"Name": "Émirats Arabes Unis"
},
{
"Code": "AF",
"Name": "Afghanistan"
},
{
"Code": "AG",
"Name": "Antigua-Et-Barbuda"
}
]
}';
$array=json_decode($string,true);
$codes= array_column($array["Countries"], "Code");//Retrieving column code
$names= array_column($array["Countries"], "Name");//Retrieving column name
$data= array_combine($codes, $names); //combining array with code as keys and names as values.
print_r($data);`
Output:
Array
(
[AD] => Andorre
[AE] => Émirats Arabes Unis
[AF] => Afghanistan
[AG] => Antigua-Et-Barbuda
)
I guess you can use something like:
function search_json($obj, $field, $value) {
foreach($obj as $item) {
foreach($item as $child) {
if(isset($child->$field) && $child->$field == $value) {
return $child->Name;
}
}
}
return null;
}
print_r(search_json($result, "Code", "AD"));
# Andorre

Finding a value in php multidimensional array and adding data to that array

I have a multidimensional JSON array that I need to add values to. The JSON array is external and I cannot change its format.
I've tried doing 3 foreach loops, but then I get myself lost in how to add data to the array. I keep catching myself stuck in a loop.
Here's the JSON:
{
"positions": [{
"report_at": "2017-03-13 20:04:10",
"elev": "0",
"dir": "0",
"id": "1"
}, {
"report_at": "2017-03-07 00:28:14",
"elev": "1240",
"dir": "89",
"id": "2"
}]
}
I have unique data I need to add to id 1, and another set of unique data I need to add to id 2.
Here's what I've tried:
$data = json_decode( $result, true );
foreach ( $data as $d ) {
foreach ( $d as $key => $data ) {
if ( $data['id'] == '1' ) {
$data[] = array(
"online_status" => "1",
"name" => "Test User",
);
} elseif ( $data['id'] == '2' ) {
$data[] = array(
"online_status" => "0",
"name" => "Another User",
);
}
}
}
$json = json_encode( $data );
echo $json;
I think once I can get this figured out, then I can pull data from MySQL, build small arrays based off that data, then add those to these sub-arrays where the ID matches the SQL ID. Any help is appreciated.
JSON seems to be just object with "positions" field which is array, you need to modify.
$data = json_decode($json, TRUE);
foreach ($data['positions'] as &$userInfo) {
if ($userInfo['id'] == 1) {
$userInfo['online_status'] = 'offline';
$userInfo['name'] = 'Test user';
}
}
echo json_encode($data);
Notice "&" sign in foreach, which means, that modification made within foreach, will be stored to original array.
Also you should be aware of key=>value naming in foreach. Your second foreach creates variable named $data, which means, that you are loosing pointer to original array!
Use the following approach:
$data = json_decode($result, true);
foreach ($data['positions'] as &$item) {
if ($item['id'] == "1") {
$item = array_merge($item, ["online_status" => "1", "name" => "Test User"]);
} else if ($item['id'] == "2") {
$item = array_merge($item, ["online_status" => "0", "name" => "Another User"]);
}
}
$json = json_encode($data, JSON_PRETTY_PRINT);
echo $json;
The output:
{
"positions": [
{
"report_at": "2017-03-13 20:04:10",
"elev": "0",
"dir": "0",
"id": "1",
"online_status": "1",
"name": "Test User"
},
{
"report_at": "2017-03-07 00:28:14",
"elev": "1240",
"dir": "89",
"id": "2",
"online_status": "0",
"name": "Another User"
}
]
}

Categories