Modifying json with PHP not saving/updating - php

I am trying to modify data in a json file with php. The code I am using is below. It is able to successfully ready the file contents and in the foreach loop it will echo out in the if statement.
This is great, the if statement is hardcoded for now to test. What I want to do is modify various properties and write it back to the file. This does not seem to be working. When I load the page, then refresh to see if the new value was set it just keeps echoing the same values. I download the .json locally and nothing has changed.
Any thoughts on what I am doing wrong?
//Get file, decode
$filename = '../json/hartford.json';
$jsonString = file_get_contents($filename);
$data = json_decode($jsonString, true);
foreach ($data['features'] as $key => $segment) {
if ($segment['properties']['UID'] == '25301') {
//echo out properties for testing
echo("KEY: ".$key."<br/>");
echo("UID: ".$segment['properties']['UID']."<br/>");
echo("Full Name: ".$segment['properties']['FULLNAME']."<br/>");
echo("FCC: ".$segment['properties']['FCC']."<br/>");
echo("Render CL: ".$segment['properties']['RENDER_CL']."<br/>");
echo("<hr/>");
//set property to new value.... NOT WORKING?
$segment['properties']['RENDER_CL'] = 111;
}
}
//Test if file is writable to be sure
$writable = ( is_writable($filename) ) ? TRUE : chmod($filename, 0755);
if ( $writable ) {
$newJsonString = json_encode($data);
if (file_put_contents($filename, $newJsonString)) {
echo('Put File Content success');
} else {
echo('NOT put');
}
} else {
echo 'not writeable';
}
In the end it will echo out 'Put File Content success' which seems to indicate it was successful but it isn't... Thanks for any advice.

You need to understand how foreach cycle works. The thing is, that the value you're getting ($segment) is a copy of the real value in the source array. So when you assign to it ($segment['properties']['RENDER_CL'] = 111;), you don't really change the source array. You only change some local variable that goes out of scope when the cycel-loop ends.
There are several ways how to solve this issue. One of them is to add & before the value-variable:
foreach ($data['features'] as $key => &$segment)
This tells it to use the reference of the array-item, not to copy its value.

You should use $segment variable in foreach as a reference:
foreach ($data['features'] as $key => &$segment) {
...
$segment['properties']['RENDER_CL'] = 111;
}

Related

How to add an error handling to read an XML file in php?

I am developing a PHP script that allows me to modify tags in an XML file and move them once done.
My script works correctly but I would like to add error handling: So that if the result of my SQL query does not return anything display an error message or better, send a mail, and not move the file with the error and move to the next.
I did some tests but the code never displays the error and it moves the file anyway.
Can someone help me to understand why? Thanks
<?php
}
}
$xml->formatOutput = true;
$xml->save($source_file);
rename($source_file,$destination_file);
}
}
closedir($dir);
?>
Give this one a try
$result = odbc_fetch_array($exec);
if ($result === false || $result['GEAN'] === null) {
echo "GEAN not found for $SKU_CODE";
// continue;
}
$barcode = (string) $result['GEAN'];
echo $barcode; echo "<br>"; //9353970875729
$node->getElementsByTagName("SKU")->item(0)->nodeValue = "";
$node->getElementsByTagName("SKU")->item(0)->appendChild($xml->createTextNode($result[GEAN]));

Json file replaces the data instead of adding

I have a Json file which i'm using for my website, however when I fill out the form and send it over to my Json file it somehow replaces the old data with the new one instead of adding it with an increment.
my json/php set-up:
$id = '';
if(isset($_POST['submit'])) {
if(file_exists('json_files/database.json')) {
$current_data = file_get_contents('json_files/database.json');
$array_data = json_decode($current_data, true);
$last_item = end($array_data);
$last_item_id = $last_item['id'];
$arrExercise = array(
'id' => ++$last_item_id,
'exerciseTitle' => $Title,
'exerciseWord' => $question_takeAudio_exerciseWord,
'syllables' => $Syllables
);
$array_data[] = $extra;
$final_data = json_encode($array_data, JSON_PRETTY_PRINT);
if(file_put_contents('json_files/database.json', $final_data)) {
header("Location: exercise_CMS.php");
} else {
echo "Oopsie! Something went wrong!";
exit();
}
}
}
my json:
{
"id": 1,
"exerciseTitle": "Huisss",
"exerciseWord": [
"Huisarts"
],
"syllables": [
"Huis",
"arts"
]
}
now, if I would fill out my form again, the above would be REPLACED for the new data send over to my json file. I want it however, to add it underneath with the increment of +1. Am I missing out on something?
EDIT: the json/php set-up has been updated. but most likely I am still missing parts out because now it returns a "0 null" value. however it doesn't overwrite the old data.
The default behavior of file_put_contents is to replace the file. According to the docs, "the existing file is overwritten, unless the FILE_APPEND flag is set."
However, as #deceze pointed out, you don't actually want to append to your JSON file because it won't be valid JSON. You'll need to read in your existing JSON file, update it and then overwrite. You'll also need to add your objects to a top level array like this:
{
"exercises": []
}

Converting JSON to UTF-8 issues in PHP

So I have this program that allows a user to enter information into a form and upon submission turns that information into a JSON file. When a user goes to a different part of the program, the programs retrieves the JSON file and builds a questionnaire out of it.
The building of the JSON file works fine but whenever I try to retrieve the file I'm getting an error that the JSON is returning as ASCII and as NULL. I've done my homework and saw that this usually happens when their is an encoding conflict(even though ASCII is a subset of UTF-8...).
So I made sure that when creating the file I'm using using mb_convert_encoding($x, 'UTF-8', 'auto');
to ensure that the JSON is properly being encoded as UTF-8.
I was also using mb_convert_encoding when retrieving the JSON, but saw that double encoding can cause issues so when I removed that piece it no longer echoed out what the encoding was(using mb_detect_encoding) but it is still NULL.
I even went so far as to pull down the JSON file, save it as UTF-8 and re-upload it.
Any and all help on this is much appreciated it. I've banged my head for two days over this. This is built in Code Ignitor, if that makes a difference
Here is the code to create the JSON file:
$thisClient = $this->input->cookie('client');
$date = "%m-%Y";
$date = mdate($date);
$clientDir = *********PATH TO CREATE THE DIRECTORIES IN;
$dialogDir = $clientDir."/".$date;
$d_file_name = $thisClient.'-'.$date;
//check to see if client directory exists, if it doesn't then it creates it
if(!is_dir($clientDir)){
mkdir($clientDir, 0755, TRUE);
echo "Client Directory Created!<br>";
} else{
echo "No Client Directory Created!<br>";
}
//check to see if client directory exists, if it doesn't then it creates it
if(!is_dir($dialogDir)){
mkdir($dialogDir, 0755, TRUE);
echo "DIALOG Directory Created!<br>";
} else{
echo "No DIALOG Directory Created!<br>";
}
$custDialog = array();
if(isset($_POST['cust-dialog-title'])){
function encodeMe($x){
//this ensure proper encoding
return mb_convert_encoding($x, 'UTF-8', 'auto');
}
$customDialog = array();
for($i = 0; $i < count($_POST['cust-dialog-title']); $i++){
$customDialog[$i]["title"] = encodeMe($_POST['cust-dialog-title'][$i]);
$customDialog[$i]["intro"] = encodeMe($_POST['cust-dialog-intro'][$i]);
for($ii = 0; $ii < count($_POST['cust-dialog-quest-'.$i]); $ii++){
$customDialog[$i]["questions"]["q".$ii] = encodeMe($_POST['cust-dialog-quest-'.$i][$ii]);
if($_POST["cust-dialog-pos-".$i."-".$ii] == "TRUE"){
//if the question is a true positive
$customDialog[$i]["questions"]["agree"] = -5;
$customDialog[$i]["questions"]["disagree"] = 5;
} else{
//if the question is a false positive
$customDialog[$i]["questions"]["agree"] = 5;
$customDialog[$i]["questions"]["disagree"] = -5;
}
}
$jsonDIALOG = json_encode($customDialog);
$jsonDIALOG = str_replace("[", " ", str_replace("]", " ", $jsonDIALOG));
if ( ! write_file($dialogDir."/".$d_file_name.".json", $jsonDIALOG )) {
echo 'Unable to write the file';
} else {
echo 'File written!';
}
//save Custom DIALOG info in database
***********DATABASE INFO**************
}
}
Here is the code to retrieve the JSON object:
if($row["custom"] !== null){ //If the Dialog is a Custom Dialog
$path = str_replace(*****removes an unnecessary portion from the path string**);
$thisDialog = file_get_contents(****PATH TO JSON FILES*****);
//THE FOLLOWING helps debug issues with the JSON -- displays order number and dialog being called -- uncomment to use
//echo $i.' is '.$curDialog[$i]. '<br>';
//$thisDialog = substr($thisDialog,1);
//echo $thisDialog;
//THIS IS THE CODE FOR DEBUGGING ENCODING ISSUES
//$thisDialog = mb_convert_encoding($thisDialog, 'UTF-8', 'ASCII');
//echo mb_detect_encoding($thisDialog);
$jsonDialog = json_decode($thisDialog, true);
echo var_dump($jsonDialog);
if($jsonDialog){
$allDialogs = $jsonDialog;
} else {
echo "Error: Invalid Dialog. Call Order# 0<br>" ;
}
return $allDialogs;
}
I've included some debugging things that I've tried and commented out. Thanks!!
You should probably add JSON_UNESCAPED_UNICODE as an option to json_encode. Keep in mind that this constant is available since PHP 5.4.0

Removing specific elements from JSON encoded array by use of PHP

I have a JSON file that looks a little like this:
[
{
"uniqid":"sd54sd54f",
"Make":"Toyota",
"Start Prod":258147369,
"End Prod":369147258
},
{
"uniqid":"6sdf46sd",
"Make":"BMW",
"Start Prod":789456123,
"End Prod":159487263
},
]
What I need to do is remove an entire entry (uniqid, make, start prod and end prod) based on a uniqid that will be passed in through an HTTP POST request. So far all I have is:
$var1 = $_GET['uniqid'];
$file = 'cars.json';
$json = json_decode(file_get_contents($file), true); //im not sure if file_get_contnets is necessary...
$unset_queue = array();
foreach ( $json as $i => $item )
{
if ($item->uniquid == $var1)
{
$unset_queue[] = $i;
}
}
foreach ( $unset_queue as $index )
{
unset($json->json[$index]);
}
$json = array_values($json);
$new_json_string = json_encode($json);
When I run the code, I get no errors but the item is not removed...
EDIT: Here is the output issue at this point. Note the numbering of each car:
{"1":
{
"uniqid":"sd54sd54f",
"make":"Toyota",
"start prod":"258147369",
"end prod":"369147258"
},
"2":
{
"uniqid":"5372ab2109b05",
"make":"6sdf46sd",
"start prod":"789456123",
"end prod":"159487263"},
}
}
You have mentioned that you will be passing your request through HTTP POST. In that case , in order to make your code to work, you should change $var1 = $_GET['uniqid']; to $var1 = $_POST['uniqid'];
You can use a simple function with the JSON variable passed by reference:
function removeNode($uniqid, &$json) {
$json = json_decode($json, true); // get associative array from json
foreach($json as $key => $each) { // loop through
if($each['uniqid'] == $uniqid) // find matching unique
unset($json[$key]); // remove node from array
}
$json = json_encode($json); // re-encode array as json
}
And use like this:
removeNode('6sdf46sd', $json);
Example: https://eval.in/150341
Specific use case for you:
$var1 = $_POST['uniqid']; // you're posting the data right?
$file = 'cars.json';
$json = file_get_contents($file);
removeNode($var1, $json);
echo $json; // updated JSON
// or if you want to update the file:
// file_put_contents($file, $json);
Well, there are a couple of things wrong:
You are not checking that your code does what you think it does. It is important to check for errors.
You can unset the item inside the first loop. The second loop is not necessary.
Inside the second loop you are accessing an object and property that does not exist. When you decoded the JSON you specifically told it to return arrays.
First of all you should put this at the top of your script:
error_reporting(-1);
ini_set('display_errors', 'On');
That will show you every single error that occurs.
Second, you should fix your code. I just rewrote and commented your code. It is easier to show you than explain.
// Make sure that you are notified of all errors
error_reporting(-1);
ini_set('display_errors', 'On');
// Get 'uniqid' from POST/GET array; show error if
// it is not set
$var1 = filter_input(INPUT_POST, 'uniqid', FILTER_UNSAFE_RAW);
if ($var1 === null) {
die('The "uniqid" parameter is not set');
}
// Read data from file; show error if it does not work
$data = file_get_contents('cars.json');
if ($data === false) {
die('An error occurred when opening "cars.json"');
}
// Decode JSON; show error if invalid JSON
$json = json_decode($data, true);
if ( ! isset($json[0]['uniqid'])) {
die("The JSON was not decoded correctly");
}
// Go over each item in the array
foreach ($json as $key => $value) {
// If the 'uniqid' equals GET parameter
if ($value['uniqid'] == $var1) {
// Then unset it using the item's $key position
unset($json[$key]);
}
}
// Encode it again
$new_json_string = json_encode($json);
If it is a GET request then you can use this instead:
// ...
$var1 = filter_input(INPUT_GET, 'uniqid', FILTER_UNSAFE_RAW);
// ...
When you are done with the code, and you make it live, you should disable errors:
ini_set('display_errors', 'Off');
That makes sure that people cannot see the errors. Error messages often include file names and such, which is not something people should see.
$inputDatabase = array_values(json);

php unset causing internal server error

function deleteThing() {
if($_REQUEST ['entry'] == "") {
exit;
}
$entry = $_REQUEST ['entry'];
$file = 'entries.json';
$json = json_decode(file_get_contents($file));
unset($json[$entry]);
file_put_contents($file, json_encode($json));
}
This code is trying to delete a JSON sub item at the index $entry which is passed as a number. I'm unsure if im using unset properly or not
it seems that you need to try like this:
passing second parameter as true will return array that you have used.
$json = json_decode(file_get_contents($file),true);//assign as array
if(isset($json[$entry])) { //check if it is set
unset($json[$entry]);
}
if you not willing to using second param as true then you will get object.In that case you need to access like this:
$json->{$entry}
I think you are unsetting a variable not set at all.
May be $json is not getting value.
Do this:
$json = json_decode(file_get_contents($file));
if (! empty($json[$entry])) {
unset($json[$entry]);
}

Categories