Insert multiple rows into database from json containing multidimensional data - php

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

Related

Parsing JSON data and inserting to MySQL

So basically I want to parse a JSON file in PHP and insert the data into specific tables/columns. At the moment I have a working script but requires me to modify the JSON largely until it works. However, it won't end up working because the JSON data I'm collecting can vary in size having more data rows.
The JSON file is structured differently to most I have seen. Maybe because its output data from sensor units. I want to insert the data and the serial number into the data table, and have an error_log table where I can store the serial number and error messages as strings. How can I achieve this?
JSON File:
{
"device": {
"sn": 5165654,
"name": "FDI_AWS_DEMO",
"v": "2.7B3"
},
"channels": [
{
"code": "RH",
"name": "Relative Humidity",
"unit": "%"
},
{
"code": "AT",
"name": "Air Temperature",
"unit": "C"
},
{
"code": "MINVi",
"name": "Min voltage",
"unit": "V"
},
{
"code": "PTi",
"name": "Processor temperature",
"unit": "C"
},
{
"code": "SDB",
"name": "Network signal dB",
"unit": "dB"
},
{
"code": "LWS",
"name": "Leaf Wetness",
"unit": "%"
},
{
"code": "WSAV",
"name": "Wind Speed Avg",
"unit": "km/h"
},
{
"code": "WSMX",
"name": "Wind Speed Max",
"unit": "km/h"
},
{
"code": "WSMN",
"name": "Wind Speed Min",
"unit": "km/h"
},
{
"code": "PR_TOT",
"name": "PR Tot",
"unit": "mm"
},
{
"code": "RAIN",
"name": "Rain",
"unit": "mm"
},
{
"code": "FDI",
"name": "fdi",
"unit": "Unit"
},
{
"code": "DT",
"name": "Delta-T",
"unit": "C"
},
{
"code": "LAT",
"name": "Latitude",
"unit": "deg"
},
{
"code": "LON",
"name": "Longitude",
"unit": "deg"
},
{
"code": "WD",
"name": "Wind Direction",
"unit": "Degrees"
},
{
"code": "P1",
"name": "Par1",
"unit": ""
},
{
"code": "AVGCi",
"name": "Average Current",
"unit": "mA"
},
{}
],
"data": [
{
"$ts": 170801164400,
"$msg": "SD_FAIL;1"
},
{
"$ts": 170801170000,
"$msg": "WDT;WV01"
},
{
"$ts": 170801170000,
"$msg": "WDT;SDI12"
},
{
"$ts": 170801170000,
"$msg": "WDT;LWS"
},
{
"$ts": 170801170000,
"RH": 67.15,
"AT": 12.87,
"MINVi": 3.81,
"PTi": 23.4,
"LWS": "0*T",
"WSAV": 0,
"WSMX": 0,
"WSMN": 0,
"PR_TOT": 156,
"RAIN": 0,
"FDI": 0.239,
"DT": 2.881,
"WD": "0*T",
"P1": "0*T",
"AVGCi": 175
},
{}
]
}
PHP Code:
<?php
//connect to mysql db
$myConnection= mysqli_connect("localhost","root","******", "ii") or die ("could not connect to mysql");
//read the json file contents
$jsondata = file_get_contents('test.json');
//convert json object to php associative array
$data = json_decode($jsondata, true);
$id = $data['device']['sn'];
$ts = $data['data']['$ts'];
$RH = $data['data']['RH'];
$AT = $data['data']['AT'];
$MINVi = $data['data']['MINVi'];
$PTi = $data['data']['PTi'];
$SDB = $data['data']['SDB'];
$LWS = $data['data']['LWS'];
$WSAV = $data['data']['WSAV'];
$WSMX = $data['data']['WSMX'];
$WSMN = $data['data']['WSMN'];
$PR_TOT = $data['data']['PR_TOT'];
$RAIN = $data['data']['RAIN'];
$FDI = $data['data']['FDI'];
$DT = $data['data']['DT'];
$LAT = $data['data']['LAT'];
$LON = $data['data']['LON'];
$WD = $data['data']['WD'];
$P1 = $data['data']['P1'];
$AVGCi = $data['data']['AVGCi'];
//insert into mysql table
$sql = "INSERT INTO test(sn, date, RH, AT, MINVi, PTi, SDB, LWS, WSAV, WSMX, WSMN, PR_TOT, RAIN, FDI, DT, LAT, LON, WD, P1, AVGCi)
VALUES('$id', '$ts', '$RH','$AT', '$MINVi', '$PTi', '$SDB', '$LWS', '$WSAV', '$WSMX', '$WSMN', '$PR_TOT', '$RAIN', '$FDI', '$DT', '$LAT', '$LON', '$WD', '$P1', '$AVGCi')";
$query=mysqli_query($myConnection, $sql) or die(mysqli_error($myConnection));
?>
Tables Test data table and error_log table
JSON array var_dump - JSON var dump
Any help would be great
(After i get the general gist i want to incorporate PDO)
Do not convert json to associative array blindly. It creates more problems.
For accessing properties containing special characters or reserved
words use placeholders like $data->{'$ts'}
Loop through arrays and objects if needed.
Adding an auto increment id column to tables helps to store data
for one device.
It is a good idea to add time to error_log table as well
Tested bellow short version of your original question and it works.
<?php
$_user = 'root';
$_password= 'root';
$_db = 'localtest';
$_host = 'localhost';
$_port = 3306;
$con = new mysqli($_host, $_user, $_password, $_db) or die(mysql_error);
//read the json file contents
$jsondata = file_get_contents('test.json');
//do not convert to array
$json = json_decode($jsondata);
$id = $json->device->sn;
foreach($json->data as $key => $data){
if(empty($data) || !isset($data->{'$ts'})){
continue;
}
if (isset($data->{'$msg'})){
$msg = $data->{'$msg'};
$time = $data->{'$ts'};
$sql="INSERT into error_log (sn, time, MSG) VALUES (?,?,?); ";
$stmt = $con-> prepare($sql);
$stmt -> bind_param("iss", $id,$time, $msg);
$stmt -> execute();
}else{
$time = (isset($data->{'$ts'}))? $data->{'$ts'}:'';
$RH = (isset($data->RH))? $data->RH:'';
$AT = (isset($data->AT))? $data->AT:'';
$MINVi = (isset($data->MINVi))? $data->MINVi:'';
//insert into mysql table
$sql="INSERT into test (sn, date, RH, AT, MINVi) VALUES (?,?,?,?,?); ";
$stmt = $con-> prepare($sql);
$stmt -> bind_param("issss", $id,$time,$RH,$AT,$MINVi);
$stmt -> execute();
}
}
mysqli_close($con);
?>
looks like the json decode is turning the array into one that is object based...run the $data through the function below to turn it into more of a relational array that is setup the way you are trying to read it....
I cannot find the function i had for this at the moment but If you read the array more like this:
$newvar = $data->node;
//to echo this try this...
echo '<pre style="text-align:left;">';
print_r($data);
echo '</pre>';
OR try fb logs for php to see the arrays in console of ya browser - use firephp for the addon.
it should work just fine...
Hope that helps.
Consider building dynamic SQL calls conditionally depending on the error output. The array keys create the columns in INSERT clause and array values are quote wrapped in VALUES clause. Below echoes the sql statements just to demonstrate.
This should work for any change to JSON suffice no other new keys are added. Also, the array_splice is used to remove the $ts value the second time since you pass it in date column.
$jsondata = file_get_contents('Input.json');
$data = json_decode($jsondata, true);
$id = $data['device']['sn'];
foreach ($data['data'] as $k=>$v){
if (array_key_exists("\$msg",$v) & !empty($v)){
$sql = "INSERT INTO error_log (sn, msg)"
." VALUES('$id', '". $v["\$msg"] ."')";
echo $sql."\n";
// INSERT INTO error_log (sn, msg) VALUES('5165654', 'SD_FAIL;1')
// INSERT INTO error_log (sn, msg) VALUES('5165654', 'WDT;WV01')
// INSERT INTO error_log (sn, msg) VALUES('5165654', 'WDT;SDI12')
// INSERT INTO error_log (sn, msg) VALUES('5165654', 'WDT;LWS')
$query = mysqli_query(...);
}
if (!array_key_exists("\$msg",$v) & !empty($v)) {
$keysArray = array_keys($v);
$keysArray = array_splice($keysArray, 1);
$vVals = array_splice($v, 1);
$sql = "INSERT INTO test(sn, date, ". implode(", ", $keysArray) .")\n"
." VALUES('$id', '". $v['$ts'] ."',". implode("', '", $vVals) .")";
echo $sql."\n";
// INSERT INTO test(sn, date, RH, AT, MINVi, PTi, LWS, WSAV, WSMX, WSMN,
// PR_TOT, RAIN, FDI, DT, WD, P1, AVGCi)
// VALUES('5165654', '170801170000',67.15', '12.87', '3.81', '23.4', '0*T',
// '0', '0', '0', '156', '0', '0.239', '2.881', '0*T', '0*T', '175)
$query=mysqli_query(...)
}
}
Maybe something like this can get you on track... One thing I did notice is there doesn't appear to be an SDB entry in the given JSON data (FYI).
<?php
//connect to mysql db
$myConnection= mysqli_connect("localhost","root","******", "ii") or die ("could not connect to mysql");
//read the json file contents
$jsondata = file_get_contents('test.json');
//convert json object to php associative array
$data = json_decode($jsondata, true);
// Make sure $data has values
if (empty($data)) {
// Process error here
}
else {
// Make sure the proper keys have been set
if (!(isset($data['device']) && !empty($data['device']) && isset($data['data']) && !empty($data['data']))) {
// Process error here if not set
}
// If so, make sure the sn key has been set
elseif (!isset($data['device']['sn']) || empty($data['device']['sn'])) {
// Process error here if not set
}
else {
$data_arr = $data['data'];
foreach ($data_arr as $key => $arr) {
// Iterate through for loop
for ($i = 0; $i < count($data_arr); $i++) {
// Make sure every single key is set
if (!(isset($data_arr[$i]['$ts']) && isset($data_arr[$i]['RH']) && isset($data_arr[$i]['AT']) && isset($data_arr[$i]['MINVi']) && isset($data_arr[$i]['PTi']) && isset($data_arr[$i]['SDB']) && isset($data_arr[$i]['LWS']) && isset($data_arr[$i]['WSAV']) && isset($data_arr[$i]['WSMX']) && isset($data_arr[$i]['WSMN']) && isset($data_arr[$i]['PR_TOT']) && isset($data_arr[$i]['RAIN']) && isset($data_arr[$i]['FDI']) && isset($data_arr[$i]['DT']) && isset($data_arr[$i]['LAT']) && isset($data_arr[$i]['LON']) && isset($data_arr[$i]['WD']) && isset($data_arr[$i]['P1']) && isset($data_arr[$i]['AVGCi']) && isset($data_arr[$i]['DT']) && isset($data_arr[$i]['DT']))) {
// Process error here if not set
}
else {
// If all is well, perform the query
$id[$key][$i] = $arr['device']['sn'];
$ts[$key][$i] = $data_arr[$i]['$ts'];
$RH[$key][$i] = $data_arr[$i]['RH'];
$AT[$key][$i] = $data_arr[$i]['AT'];
$MINVi[$key][$i] = $data_arr[$i]['MINVi'];
$PTi[$key][$i] = $data_arr[$i]['PTi'];
$SDB[$key][$i] = $data_arr[$i]['SDB'];
$LWS[$key][$i] = $data_arr[$i]['LWS'];
$WSAV[$key][$i] = $data_arr[$i]['WSAV'];
$WSMX[$key][$i] = $data_arr[$i]['WSMX'];
$WSMN[$key][$i] = $data_arr[$i]['WSMN'];
$PR_TOT[$key][$i] = $data_arr[$i]['PR_TOT'];
$RAIN[$key][$i] = $data_arr[$i]['RAIN'];
$FDI[$key][$i] = $data_arr[$i]['FDI'];
$DT[$key][$i] = $data_arr[$i]['DT'];
$LAT[$key][$i] = $data_arr[$i]['LAT'];
$LON[$key][$i] = $data_arr[$i]['LON'];
$WD[$key][$i] = $data_arr[$i]['WD'];
$P1[$key][$i] = $data_arr[$i]['P1'];
$AVGCi[$key][$i] = $data_arr[$i]['AVGCi'];
$sql[$key][$i] = "INSERT INTO test(sn, date, RH, AT, MINVi, PTi, SDB, LWS, WSAV, WSMX, WSMN, PR_TOT, RAIN, FDI, DT, LAT, LON, WD, P1, AVGCi)
VALUES('{$id[$key][$i]}', '{$ts[$key][$i]}', '{$RH[$key][$i]}','{$AT[$key][$i]}', '{$MINVi[$key][$i]}', '{$PTi[$key][$i]}', '{$SDB[$key][$i]}', '{$LWS[$key][$i]}', '{$WSAV[$key][$i]}', '{$WSMX[$key][$i]}', '{$WSMN[$key][$i]}', '{$PR_TOT[$key][$i]}', '{$RAIN[$key][$i]}', '{$FDI[$key][$i]}', '{$DT[$key][$i]}', '{$LAT[$key][$i]}', '{$LON[$key][$i]}', '{$WD[$key][$i]}', '{$P1[$key][$i]}', '{$AVGCi[$key][$i]}')";
//insert into mysql table
$query[$key][$i] = mysqli_query($myConnection, $sql[$key][$i]) or die(mysqli_error($myConnection));
}
}
}
}
}
?>

Adding array elements with a for(reach) loop

(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];
}
}
?>

Speeding up PHP Calls

so I have some PHP code which is displaying an email list (Name, Surname & Email) from a list I have hosted via API.
The problem I have is that in order to display the name of the subscriber, I have to separately pass the email through the API... and the only way to get the email is to use a separate function.
So, for a list of 100 people, I'm basically hitting calling their API 300 times... so it is taking forever to echo the information (and over 30ish people the server just times out).
Is there a way I can edit the blow code so that I'm not pulling their info EVERY time, and instead bring it all down at once?
Here's my code:
<?php
require('Mailin.php');
/////////Total Subscriber Count $subscribers
$mailin = new Mailin('https://api.sendinblue.com/v2.0','UNIQUEKEY');
$datacount = array( "id"=>13 );
$subscribercount = $mailin->get_list($datacount);
$subscribers = $subscribercount['data']['total_subscribers'] - 1;
/////////Get Emails of Subscribers
$dataemail = array( "listids" => array(2),
"page" => 1,
"page_limit" => 500
);
$getemails = $mailin->display_list_users($dataemail);
/////////Get Name of Subscribers
foreach (range(0, $subscribers) as $number) {
$subscriberemail = $getemails['data']['data'][$number]['email'];
echo $subscriberemail;
echo '<br/>';
$dataname = array( "email" => $subscriberemail );
$getname = $mailin->get_user($dataname);
$subscribername = $getname['data']['attributes']['NAME'];
$subscribersurname = $getname['data']['attributes']['SURNAME'];
echo $subscribername;
echo '<br/>';
echo $subscribersurname;
echo '<br/>';
}
?>
Here is the output you get calling the display_list_users:
{
"code":"success",
"message":"Retrieved details of all users for the given lists",
"data":{
"data":[
{
"blacklisted":0,
"email":"email1#domain.com",
"id":1,
"listid":[1],
"blacklisted_sms":1,
"last_modified" : "2015-05-22 15:30:00"
},
{
"blacklisted":1,
"email":"email2#domain.com",
"id":2,
"listid":[1,2],
"blacklisted_sms":0 ,
"last_modified" : "2015-05-25 19:10:30"
}
],
"page":1,
"page_limit":2,
"total_list_records":100
}
}
And the output you get calling the get_user:
{
"code":"success",
"message":"Data retrieved for email",
"data":{
"attributes":{
"EMAIL":"example#example.net",
"NAME" : "Name",
"SURNAME" : "surname"
},
"blacklisted":1,
"email":"example#example.net",
"entered":"2014-01-15",
"listid":[8],
"message_sent":[{
"camp_id" : 2,
"event_time" : "2013-12-18"
},
{ "camp_id" : 8,
"event_time" : "2014-01-03"
},
{ "camp_id" : 11,
"event_time" : "2014-01-07"
}],
"hard_bounces":[{
"camp_id" : 11,
"event_time" : "2014-01-07"
}],
"soft_bounces":[],
"spam":[{
"camp_id" : 2,
"event_time" : "2014-01-09"
}],
"unsubscription":{
"user_unsubscribe":[
{
"event_time":"2014-02-06",
"camp_id":2,
"ip":"1.2.3.4"
},
{
"event_time":"2014-03-06",
"camp_id":8,
"ip":"1.2.3.4"
}
],
"admin_unsubscribe":[
{
"event_time":"2014-04-06",
"ip":"5.6.7.8"
},
{
"event_time":"2014-04-16",
"ip":"5.6.7.8"
}
]
},
"opened":[{
"camp_id" : 8,
"event_time" : "2014-01-03",
"ip" : "1.2.3.4"
}],
"clicks":[],
"transactional_attributes":[
{
"ORDER_DATE":"2015-07-01",
"ORDER_PRICE":100000,
"ORDER_ID":"1"
},
{
"ORDER_DATE":"2015-07-05",
"ORDER_PRICE":500000,
"ORDER_ID":"2"
}
],
"blacklisted_sms":1
}
}

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.

Json_decode returning empty value - json object to php array

I have a basic form where I am storing (in the client side) the values in a json format inside a textarea. I then plan to store these values in mysql database. I am using json_decode to place the json object into a regular php array. But when I check print_r($personArray) there is nothing. Therefore everytime I submit the form nothing gets stored in mysql database because the php array is empty. How can I store the values in the text area in mysql database? Here is a LIVE DEMO
if(isset($_POST['submit'])) {
$data = $_POST['data'];
echo $data;
$personArray = json_decode($data, true);
print_r($personArray);
foreach($personArray as $key => $value){
$main_role1 = ($value['main1'] == "true") ? 1 : 0;
$main_role2 = ($value['main2'] == "true") ? 1 : 0;
$person_fname = $value['firstName'];
$person_lname = $value['lastName'];
$person_phone = $value['phone'];
$query_init2 = "INSERT INTO person (main_role1, main_role2, first_name, last_name, person_phone) VALUES (:main_role1, :main_role2,:person_fname,:person_lname, :person_phone);";
$query_prep2 = $db_con->prepare($query_init2);
$insert_result2 = $query_prep2->execute(array(
"main_role1" => $main_role1,
"nmain_role2" => $main_role2,
"person_fname" => $person_fname,
"person_lname" => $person_lname,
"person_phone" => $person_phone
));
}
}
HTML
<textarea name="data" rows='5' cols='60'>
JSON Object
[
{
"firstName": "Danny",
"lastName": "LaRusso",
"ciscoID": "123",
"academyID": "1",
"email": "test1#email.com",
"phone": "(555) 121-2121",
"fax": "(123) 123-4567",
"contact_role": true,
"netacadContact": true,
"netacadStaff": false,
"netacadSuccess": false,
"instructor_role": false
},
{
"firstName": "Sensei",
"lastName": "Miyagi",
"ciscoID": "456",
"academyID": "1",
"email": "test2#email.com",
"phone": "(555) 444-2222",
"fax": "(123) 123-4567",
"contact_role": false,
"netacadContact": false,
"netacadStaff": false,
"netacadSuccess": false,
"instructor_role": true
}
]
The json_decode is working fine. The problem is when you are binding values into your SQL Statement.
$insert_result2 = $query_prep2->execute(array(
":main_role1" => $main_role1,
":nmain_role2" => $main_role2,
":person_fname" => $person_fname,
":person_lname" => $person_lname,
":person_phone" => $person_phone
));
You should include the ':' in the keys of the array.
Also, at the end of you query, you do not need another ;.
$query_init2 = "INSERT INTO person (main_role1, main_role2, first_name, last_name, person_phone) VALUES (:main_role1, :main_role2, :person_fname, :person_lname, :person_phone)";

Categories