Removing specific elements from JSON encoded array by use of PHP - 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);

Related

loop a file_get_contents until getting a non empty JSON in php

I have the following code:
<?php
$json = file_get_contents("https://api.nanopool.org/v1/eth/payments/0x218494b2284a5f165ff30d097d3d7a542ff0023B");
$decode = json_decode($json,true);
foreach($decode['data'] as $val){
echo date('Y-m-d',$val['date']).' -- '.$val['amount'].' -- '.$val['txHash'].' -- '.$val['confirmed'];
echo "<br/>";
}
The API used (nanopool) being extremely unreliable, I get a non empty json (success) every 2 to 10 calls.
I tried to loop the file_get_contents (do... while) until getting a non empty json without success. What can you recommend to loop until I get an answer?
Maybe you can try something like this, still I don't recommend using this within a synchronous script (eg a web page) because you can't control the time needed to get a successfull answer.
<?php
function getFileFTW($url)
{
$fuse = 10;//maximum attempts
$pause = 1;//time between 2 attempts
do {
if($fuse < 10)
sleep($pause);
$s = #file_get_contents($url);
}
while($s===false && $fuse--);
return $s;
}
$json = getFileFTW("https://api.nanopool.org/v1/eth/payments/0x218494b2284a5f165ff30d097d3d7a542ff0023B");
if($json) {
$decode = json_decode($json,true);
//...
}
else {
//json not loaded : handle error
}

Modifying json with PHP not saving/updating

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

php: receive json from POST and save to file

I want to receive a POST request from a JS client with a json body (i.e. this is not form data), and save the .gigs (javascript) array to a file, after checking the .password field. This is all my code (based on Receive JSON POST with PHP)
$json_params = file_get_contents("php://input");
if (strlen($json_params) > 0 && isValidJSON($json_params)){
/* json_decode(..., true) returns an 'array', not an 'object'
* Working combination: json_decode($json_params) WITH $inp->password
*/
$inp = json_decode($json_params);
} else {
echo "could not decode POST body";
return;
}
$password = $inp->password;
// echo $password;
if ($password == "****") {
$gigs = $inp['gigs'];
// WAS $res = file_put_contents('gigs.json', json_encode($gigs), TEXT_FILE);
$res = file_put_contents('gigs.json', json_encode($gigs));
if ($res > 0) {
echo "Success";
return;
} else {
if (!$res) {
http_response_code(500);
echo "file_put_contents error:".$res;
return;
} else {
http_response_code(500);
echo "Error: saved zero data!";
return;
}
}
}
else {
// http_response_code(403); // (2)
echo "Password invalid";
return;
}
What I find is that
if I comment out the if statement and uncomment echo $password; then the right password is there
if I uncomment line 2, which I want to do, then I get back a 500 and the error logs refer an Illegal string offset 'password' in line (1) above. Without that I get back a "Success" (all for the same password).
I don't understand what is happening, nor how to get 200, 403 and 500 error messages safely.
Note
$json_params = file_get_contents("php://input");
If your scripts are running upon regular HTTP requests, passing data like it comes from HTML form, them you should consider using $_POST for your content, not php://input. If you expect JSON in request body, then I'd be fine, yet I'd also check content type for application/json.
Next:
$inp = "I never got set";
if (strlen($json_params) > 0 && isValidJSON($json_params)){
$inp = json_decode($json_params, true);
}
$password = $inp->password;
$password = $inp['password'];
This is pretty broken. First, see json_decode() arguments (2nd) -> you are decoding to array (true), not object (false), so only $password = $inp['password']; will work in your case. Also the whole code will fail when your input data is invalid as in that case $np is rubbish string, not the array you try to read later on. Use null as default value and check for that prior further use.
Next:
$res = file_put_contents('gigs.json', json_encode($gigs), FILE_TEXT);
there's no FILE_TEXT option for file_put_contents(). Nor you'd need one.
Once you correct these you'd be fine. Also print_r() and var_dump() may be the functions you wish to get familiar with for your further debugging.
In general http://php.net/ -> lookup for functions you are about to use.

PHP - str_replace returns original string

I'm building a simple JS terminal shell emulator which posts its commands via AJAX to PHP.
Please leave security aside, this is only for learning and demo purposes.
Now my problem is, str_replace() won't work as expected, in fact, it returns the unchanged input string. It should work like this:
The name of this host is $hostname --> Yes, this string contains a variable --> Replace $hostname with testserver --> return The name of this host is testserver
What am I doing wrong?
This is my respond script for echo and export:
<?
// get environment variables from JSON
$vars = json_decode(file_get_contents('environment.json'), true);
// get request params
$method = $_SERVER['REQUEST_METHOD'];
$action = $_POST['action'];
$data = $_POST['data'];
switch ($action) {
case 'echo':
$cmd = $data;
// if the string in question contains a variable, eg. "the time is $time"
if (strpos($cmd,'$')) {
$output = '';
// for each environment variable as variable => value
foreach ($vars as $var => $val) {
// replace every variable in the string with its value in the command
$output = str_replace($var,$val,$cmd);
}
echo $output;
} else {
// if it does not contain a variable, answer back the query string
// ("echo " gets stripped off in JS)
echo $cmd;
}
break;
case 'export':
// separate a variable declaration by delimiter "="
$cmd = explode('=',$data);
// add a $-sign to the first word which will be our new variable
$var = '$' . array_shift($cmd);
// grab our variable value from the array
$val = array_shift($cmd);
// now append everything to the $vars-array and save it to the JSON-file
$vars[$var] = $val;
file_put_contents("environment.json",json_encode($vars));
break;
}
Better using :
if (strpos($cmd,'$') !== false) {
Then, every single replace will take the "first" data as its input data. You should proceed like this :
$output = $cmd;
// for each environment variable as variable => value
foreach ($vars as $var => $val) {
// replace every variable in the string with its value in the command
$output = str_replace($var, $val, $output);
}

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