Adding array elements with a for(reach) loop - php

(First a bit/lot of context at the bottom is the question)
I am writing an API that returns a planning amongst other things. The response is in JSON and should be as followed:
"Planning":
[
{
"Name": "Overview",
"Dates":
[
{
"Date": "yyyy-mm-dd",
"Division1": "type",
"Division2": "type"
},
{
"Date": "yyyy-mm-dd",
"Division1": "type",
"Division2": "type"
},
...
]
},
{
"Name": "Division1",
"Dates":
[
{
"Date": "yyyy-mm-dd",
"Type": "type",
"Description": "type"
},
...
]
},
...
There is the standard blok "Name": "Overview" this is always returned, and for each division the requester is a part of, a block with "Name":"Divisionname" is added to the response.
The issue I have is that the amount or names of the divisions aren't set in stone. There can be more or less depending on the deployment.
To cover for this I wrote the following code:
<?php
...
$stmt = $conn->prepare("SELECT `idDivision` FROM Division;");
$stmt->execute();
$stmt->bind_result($idDivision);
while($stmt->fetch()){
$Divisions[] = $idDivision;
$$idDivision = array();
}
...
?>
This should create an array for each division with the array name being the id of that division (correct?).
Then I get the planning data from the DB which i store in the multiple arrays that I will later use for the response building:
<?php
$stmt->bind_result($type, $date, $idDivision, $day, $description, $note);
while($stmt->fetch()){
if(checkarray($date, $arr_date) != true){
array_push($arr_date, $date);
array_push($arr_day, $day);
}
array_push($$idDivision, $type); //This should push it into the correct array.
}
?>
At the end I want to combine all this into the respons ofcourse (This is where I am lost):
<?php
for($i = 0; $i <= count($arr_date); $i++){
$planning[0]['Dates'][] = array(
"Date" => $arr_date[$i],
// How to add every division with "arrayname" => "$type" here?
);
}
?>
As in the comment above, i don't know how to add a key:value for each division that i found dynamically so that it becomes:
<?php
for($i = 0; $i <= count($arr_date); $i++){
$planning[0]['Dates'][] = array(
"Date" => $arr_date[$i],
"Division1" => $value,
"Division2" => $value,
"Division3" => $value,
// and so on for every division
);
}
?>
Is there a way to do this or should I even go about doing this a different way? I feel like I should/could use the $Divisions array.

Try out this.
for($i = 0; $i <= count($arr_date); $i++){
$planning[0]['Dates'][$i]["Date"] = $arr_date[$i];
for($j=0;$j<count($division);$j++){
$planning[0]['Dates'][$i]["division$j"] = $division[$j];
}
}
?>

Related

Insert multiple rows into database from json containing multidimensional data

This is the following JSON I am working with. I have everything being pulled and added correctly except the content under "tactics" -- which comes out as Array.
My goal is to store the "tactics" values as a comma-delimited string.
'[
{
"queryFrequency": "P1D",
"queryPeriod": "P1D",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0,
"eventGroupingSettings": {
"aggregationKind": "SingleAlert"
},
"severity": "Medium",
"query": "let extess",
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"Execution",
"Persistence"
],
"displayName": "MFA disabled for a user",
"enabled": true,
"description": "Multi-Factor Authentication (MFA) helps prevent credential compromise. This alert identifies when an attempt has been made to diable MFA for a user ",
"alertRuleTemplateName": "65c78944-930b-4cae-bd79-c3664ae30ba7",
"lastModifiedUtc": "2021-06-16T16:29:52.6974983Z",
"name": "1ada95bc-b4d5-4776-bc3e-2dbb3684c0b1",
"id": "/sc0b1",
"kind": "Scheduled",
"createIncident": true,
"groupingConfiguration": {
"enabled": false,
"reopenClosedIncident": false,
"lookbackDuration": "PT5H",
"entitiesMatchingMethod": "All",
"groupByEntities": [
"Account",
"Ip",
"Host",
"Url",
"FileHash"
]
},
"playbookName": ""
},
{
"queryFrequency": "P1D",
"queryPeriod": "P1D",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0,
"eventGroupingSettings": {
"aggregationKind": "SingleAlert"
},
"severity": "Medium",
"query": "StppUsed",
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"Execution",
"Persistence"
],
"displayName": "Explicit MFA Deny",
"enabled": true,
"description": "User explicitly denies MFA push, indicating that login was not expected and the account\'s password may be compromised.",
"alertRuleTemplateName": "a22740ec-fc1e-4c91-8de6-c29c6450ad00",
"lastModifiedUtc": "2021-06-16T16:29:54.0826821Z",
"name": "bba57ceb-dd33-4297-8080-b19b1bd07a21",
"id": "/suobba5d07a21",
"kind": "Scheduled",
"createIncident": true,
"groupingConfiguration": {
"enabled": false,
"reopenClosedIncident": false,
"lookbackDuration": "PT5H",
"entitiesMatchingMethod": "All",
"groupByEntities": [
"Account",
"Ip",
"Host",
"Url",
"FileHash"
]
},
"playbookName": ""
} ]'
This is my code:
...
$dep_cols=array("queryFrequency","queryPeriod","triggerOperator","triggerThreshold","aggregationKind","severity","query","suppressionDuration","suppressionEnabled","tactics","displayName","enabled","description","kind","createIncident","playbookName"); // declare columns
$dep_keys=array_map(function($v){return ":$v";},$dep_cols); // build :keys
$dep_cols=array_combine($dep_keys,$dep_cols); // assign :keys
var_export($dep_cols);
$dep_query="INSERT INTO `template_rules` (`id`,`".implode('`,`',$dep_cols)."`)"; // list columns as csv
$dep_query.=" VALUES ('',".implode(',',array_keys($dep_cols)).");";
echo "<div>$dep_query</div>";
$stmt_add_dep=$db->prepare($dep_query);
foreach(json_decode($json) as $d){
foreach($dep_cols as $k=>$v){
if($k==':tactics'){$v=json_decode($v);}
$stmt_add_dep->bindValue($k,(property_exists($d,$v)?$d->$v:""));
echo "<div>$k => {$d->$v}</div>";
}
$stmt_add_dep->execute();
echo "<div>Dep Affected Rows: ",$stmt_add_dep->rowCount(),"</div><br>";
}
...
If I remove the if($k==':tactics') statement, I just get Array. I'm not sure how to pull those values out as they look to just be a string in an array.
Current results look like this:
...
:suppressionDuration => PT1H
:suppressionEnabled =>
:tactics =>
:displayName => MFA disabled for a user
:enabled => 1
...
Here's a working refactor of your script.
Create arrays of the whitelisted column names and a number of placeholders (I prefer the vague ?, but you can use named placeholders if you like).
Create separate payloads of values to be fed to the prepared statement when execute() is called.
You don't need to mention id if you are autoincrementing that column.
Code: (PHPize.online Demo)
$whitelist = [
"queryFrequency", "queryPeriod", "triggerOperator", "triggerThreshold",
"aggregationKind", "severity", "query", "suppressionDuration",
"suppressionEnabled", "tactics", "displayName", "enabled",
"description", "kind", "createIncident", "playbookName"
];
$columns = [];
$placeholders = [];
$valueSets = [];
foreach ($whitelist as $column) {
$columns[] = "`$column`";
$placeholders[] = "?";
}
foreach (json_decode($json) as $i => $obj) {
$obj->aggregationKind = $obj->eventGroupingSettings->aggregationKind ?? null;
$obj->tactics = property_exists($obj, 'tactics') ? implode(',', $obj->tactics) : null;
foreach ($whitelist as $column) {
$valueSets[$i][] = $obj->$column ?? null;
}
}
$stmt = $pdo->prepare(
sprintf(
'INSERT INTO `template_rules` (%s) VALUES (%s)',
implode(',', $columns),
implode(',', $placeholders)
)
);
foreach ($valueSets as $values) {
$stmt->execute($values);
printf("<div>New autoincremented Id: %d</div><br>\n\n", $pdo->lastInsertId());
}
echo json_encode($pdo->query('SELECT * FROM template_rules')->fetchAll(PDO::FETCH_ASSOC), JSON_PRETTY_PRINT);

How to wrap part of my JSON with brackets using PHP?

I have some JSON that looks like this:
{
"order_id":"59.1595",
"quantity":"1",
"orderline":"61b9f15a158ee",
"customer_id":"59",
"product_thumbnail":"https:\/\/website.nl\/cms\/images\/producten\/deelpaneel\/afbeeldingen\/_deelpaneel_foto_op_rvs.jpg",
"rulers":"cm",
"product_data":{
"id":"custom",
"dpi":"50",
"name":"Deelpaneel",
"size":"1000x550",
"bleed":"10",
"sides":{
"id":1,
"name":"Frontside",
"name_nl":"Voorkant",
"template_overlay":"https:\/\/website.nl\/cms\/images\/producten\/deelpaneel\/templates\/2_deelpaneel_100x55cm1cmafstandhouders.svg"
}
},
"safety":"",
"has_contour":"false",
"preview_link":"",
"redirect_link":"https:\/\/website.nl\/winkelwagen",
"procheck":"n"
}
I create it with PHP and use json_encode.
My question is how do I get brackets around the inside of sides?
Like in this example:
"sides": [
{
"id": 1,
"name": "Frontside",
"name_nl": "Voorkant",
"template_overlay": null
},
{
"id": 2,
"name": "2 side en",
"name_nl": "2 side nl",
"template_overlay": null
},
{
"id": 3,
"name": "3 side en",
"name_nl": "3 side nl",
"template_overlay": null
}
],
"safety": 10,
This is how I create that part with PHP:
<?PHP
if(!empty($uploadarray['product_data']['sides'])){
// Multiple sides
}else{
$uploadarray['product_data']['sides']['id'] = 1;
$uploadarray['product_data']['sides']['name'] = 'Frontside';
$uploadarray['product_data']['sides']['name_nl'] = 'Voorkant';
$uploadarray['product_data']['sides']['template_overlay'] = $templateoverlay;
}
?>
Then I create the entire JSON with: $json = json_encode($uploadarray);
I've read that you need to wrap it in another array but I can't get it to work.
For example:
array(array($uploadarray['product_data']['sides']['id'] = 1));
Or
array($uploadarray['product_data']['sides']['name'] = 'Frontside');
Just output the same json result.
First create your array
$side = [
'id' => 1,
'name' => 'Frontside',
'name_nl' => 'Voorkant',
'template_overlay' => $templateoverlay
];
Then, add it :
// Check this -----------------------vv
$uploadarray['product_data']['sides'][] = $side;
Your $sides variable does not contain an array with multiple entities but just one "dictionary" (one JSON object). If you e.g. add a loop around, it should work:
<?php
// loop over whatever generates the sides
$sides_array = [];
$sides_array['id'] = 1;
$sides_array['name'] = 'Frontside';
$sides_array['name_nl'] = 'Voorkant';
$sides_array['template_overlay'] = $templateoverlay;
if(empty($uploadarray['product_data']['sides'])){
// initialize "sides"
$uploadarray['product_data']['sides'] = [];
}
$uploadarray['product_data']['sides'][] = $sides_array;
?>

How to format json to what I need?

ok, Going to get this out of the way right now. I suck at php. I am building an angular app that is going to populate a mobile app with data from the database. I having it pull from the database just fine but I need the json formatted in a special way and I have no idea how to do it.
Using json_encode this is how it is coming from the database:
[
{
"id":"1",
"date":"2014-10-03",
"time":"2014-10-03 10:45:05",
"amount":"5"
},
{
"id":"2",
"date":"2014-10-03",
"time":"2014-10-03 12:21:05",
"amount":"2"
}
]
This is how I need it organized (this is just dummy data im using in on the angular side)
[
{
date: '2014-09-04',
feeding: [
{
id: '1',
time: '1409852728000',
amount: '3'
},
{
id: '2',
time: '1409874328000',
amount: '4'
},
]
},
{
date: '2014-09-05',
feeding: [
{
id: '3',
time: '1409915908000',
amount: '3.5'
},
{
id: '4',
time: '1409957908000',
amount: '5'
},
]
},
]
I needs to be seperated out and grouped by date. How would I go about doing this?
Airtech was just about there. Small update to the function though. The feeding value needs to be an array of objects rather than an object. You then need to push individual objects into that array.
function dateparse($in) {
$in = json_decode($in);
$out = array();
for ($i = 0; $i < sizeof($in); $i++) {
$date = $in[$i]->date;
$isFound = false;
for ($i2 = 0; $i2 < sizeof($out); $i2++) {
if ($date == $out[$i2]["date"]) {
// We've already run into this search value before
// So add the the elements
$isFound = true;
$out[$i2]["feeding"][] = array(
"id" => $in[$i]->id,
"time" => $in[$i]->time,
"amount" => $in[$i]->amount);
break;
}
}
if (!$isFound) {
// No matches yet
// We need to add this one to the array
$feeding = array("id" => $in[$i]->id, "time" => $in[$i]->time, "amount" => $in[$i]->amount);
$out[] = array("date" => $in[$i]->date, "feeding" => array($feeding));
}
}
return json_encode($out);
}
How about the following? I tested it on your json input example and it ran fine.
function parse($in)
{
$in = json_decode($in);
$out = array();
for ($i = 0; $i < sizeof($in); $i++) {
$date = $in[$i]->date;
$isFound = false;
for ($i2 = 0; $i2 < sizeof($out); $i2++) {
if ($date == $out[$i2]["date"]) {
// We've already run into this search value before
// So add the the elements
$isFound = true;
$out[$i2][]["feeding"] = array(
"id" => $in[$i]->id,
"time" => $in[$i]->time,
"amount" => $in[$i]->amount);
break;
}
}
if (!$isFound) {
// No matches yet
// We need to add this one to the array
$out[] = array("date" => $in[$i]->date, "feeding" => array(
"id" => $in[$i]->id,
"time" => $in[$i]->time,
"amount" => $in[$i]->amount));
}
}
return json_encode($out);
}
How about this ? This works fine and works as expected :) :-
function dateparse($var)
{
$counter=0; $var = json_decode($var); $date=array();
foreach($var as $key=>$value){foreach($value as $val1=>$val2)
{if($val1 == "date")
{foreach($value as $val3=>$val4)
{if($val3!="date") //because we don't want date again
{
$date[$val2]["feeding"][$counter][$val3] = $val4; continue;
}}continue;
}
}$counter++;}
return json_encode($date);}

Why I can't return a proper json structure?

I'm facing an issue regarding the json structure.
I have this:
function loadActiveTrackers($host_l, $username_l, $password_l, $dbName_l, $companyId_l){
$trackerId = 0;
$trackerName = "";
$trackerCreator = "";
$projectName = "";
$dataArray = [];
$trackerIdsArray = [];
$trackerNamesArray = [];
$trackerCreatorsArray = [];
$projectNamesArray = [];
$mysqli = new mysqli($host_l, $username_l, $password_l, $dbName_l);
$getActiveTrackersQuery = "SELECT tracker_id, tracker_name, tracker_creator, project_name FROM trackers WHERE "
. "company_id = ? AND is_active=1 ORDER BY tracker_creation_date";
if($stmt = $mysqli->prepare($getActiveTrackersQuery)){
$stmt->bind_param('s',$companyId_l);
$stmt->execute();
/* Store the result (to get properties) */
$stmt->store_result();
/* Bind the result to variables */
$stmt->bind_result($trackerId, $trackerName, $trackerCreator, $projectName);
while ($stmt->fetch()) {
$trackerIdsArray[] = $trackerId;
$trackerNamesArray[] = $trackerName;
$trackerCreatorsArray[] = $trackerCreator;
$projectNamesArray[] = $projectName;
}
$dataArray['ids'] = $trackerIdsArray;
$dataArray['names'] = $trackerNamesArray;
$dataArray['creators'] = $trackerCreatorsArray;
$dataArray['projectNames'] = $projectNamesArray;
// print_r($trackerIdsArray);
/* free results */
$stmt->free_result();
/* close statement */
$stmt->close();
}
/* close connection */
$mysqli->close();
echo json_encode($dataArray);
}
The above code works ok, but the structure is not valid.
What I mean is that it returns:
{
"ids": [1,2,3,4],
"names": ["1","2","test tracker","test1"],
"creators": ["1","test","test","test"],
"projectNames": ["1","1","test project","test"]
}
But it is supposed to return:
[
{"id": 1, "name": "1", "creator": "1", "projectName": "1"},
{"id": 2, "name": "2", "creator": "test", "projectName": "1"},
{"id": 3, "name": "test tracker", "creator": "test", "projectName": "test project"},
{"id": 4, "name": "test1", "creator": "test", "projectName": "test"}
]
Can you guide me trough it? I know that it's something really small, but I'm not able to spot it as a php newbie. In java the json library is pretty strong and with a single push() it can be achieved, but here I really can't find the way.
The current code creates arrays of the ids, names, creators, and project names.
So, instead of this code:
while ($stmt->fetch()) {
$trackerIdsArray[] = $trackerId;
$trackerNamesArray[] = $trackerName;
$trackerCreatorsArray[] = $trackerCreator;
$projectNamesArray[] = $projectName;
}
$dataArray['ids'] = $trackerIdsArray;
$dataArray['names'] = $trackerNamesArray;
$dataArray['creators'] = $trackerCreatorsArray;
$dataArray['projectNames'] = $projectNamesArray;
Change your structure to be like so:
while ($stmt->fetch()) {
$dataArray[] = array( 'id' => $trackerId,
'name' => $trackerName,
'creator' => $trackerCreator,
'projectName' => $projectName
);
}
echo json_encode($dataArray);
This will return the structure you desire, which is arrays of the ids, names, creators, and project names.

Inserting data into associative array

I have a class property where i define an associative array
private $jsonArray = array('Friends' => array());
Im trying to have the array have each friend be put into the array Friends
[Accepted] = test
$query = "SELECT Username, Status
FROM Users
INNER JOIN Friends
ON Users.idUser = Friends.idFriend
WHERE Friends.idUser = ? ";
// Prepares and excutes the query
if($stmt = $this->connection->prepare($query))
{
$stmt->bind_param('s', $this->id);
$stmt->execute();
$stmt->bind_result($friend, $status);
for ($i=0; $stmt->fetch(); $i++)
{
$this->jsonArray['Friends'][$status] = $friend;
}
}
Is this the correct way to define the key for the friend it works but when i json encode its a dict and no longer an array
{
"response": {
"status":"Success",
"friends": [
"Andrew",
"Jake",
"Matt",
"Phil",
"Colton"
],
"groups": [
{
"GroupId": "12",
"GroupMembers": [
"Andrew",
"Matt",
"Colton"
],
"GroupName": “Group1”
},
{
"GroupId": "12",
"GroupMembers": [
"Phil",
"Matt",
"Colton"
],
"GroupName": "Room 201"
}
]
}
}
With this you'll always have one $friend per [$status] - if that is wanted, then it's ok. But from the looks, you'd be better off with something like this
for ($i=0; $stmt->fetch(); $i++) {
$this->jsonArray['Friends'][$status][] = $friend;
}
Now you'll have an array of $friends inside [$status].
...
Friends: {
"Accepted": ["friend1", "friend2", ...]
}
...
Or this
for ($i=0; $stmt->fetch(); $i++) {
$this->jsonArray['Friends'][] = $friend;
}
Since you know their $status - why even use it?
...
Friends: ["friend1", "friend2", ...]
...

Categories