I'm trying to delete an item from json file using id property match.
What is actually the unset i need?
Json data:
{"memory":[{"id":1,"pinned":false,"title":"my title","author":"me"},
{"id":2,"pinned":false,"title":"my title","author":"me"}]}
$projectsArr = json_decode(file_get_contents("../db/memory.json"), true);
if(isset($_POST['subDelete'])) {
$selectedIitemId = $_POST["subDelete"];
foreach($projectsArr['memory'] as &$mydata) {
if($mydata['id'] == $selectedIitemId) {
// unset ?
$save = json_encode($projectsArr,JSON_UNESCAPED_UNICODE);
file_put_contents('../db/memory.json', $save);
header('LOCATION:approve.php');
}
}
}
This code uses the index of the entry that matches and uses unset() from the array itself ($projectsArr['memory']). Also as this then leaves an array with missing entries (which will cause it to save as an object) it uses array_values() to reset the keys before saving the data.
foreach($projectsArr['memory'] as $key => $mydata) {
if($mydata['id'] == $selectedIitemId) {
unset($projectsArr['memory'][$key]);
$projectsArr['memory'] = array_values($projectsArr['memory']);
$save = json_encode($projectsArr,JSON_UNESCAPED_UNICODE);
file_put_contents('../db/memory.json', $save);
header('LOCATION:approve.php');
exit;
}
}
Related
I need to know how to update a decoded JSON array with new values (I don't mean a simple array_push though).
I'm going to post my code, here's my Users.json file:
[
{
"objID":"Y0FVVFZYCV",
"createdOn":{"type":"__date","date":"2018-09-21T16:48:09"},
"string":"lorem ipsum"
},
{
"objID":"YShAUqIcMg",
"username":"johndoe", // new key->value here!
"createdOn":{"type":"__date","date":"2018-09-21T16:48:14"},
"string":"lorem ipsum"
}
]
Here's my create.php file where I used to add JSON objects from a URL string:
// Prepare data to be saved:
if(!empty($_GET)){
foreach($_GET as $key => $value) {
// Random objID
$objects->objID = generateRandomID();
// Number
if( is_numeric($value) ){
$objects->$key = (float) $value;
// Boolean
} else if($value === 'true'){
$objects->$key = true;
} else if($value === 'false'){
$objects->$key = false;
// ClassName
} else if ($key === 'className'){
// String
} else { $objects->$key = $value; }
// createdOn & updatedOn Dates
$objects->createdOn = array('type'=>'__date','date'=>$formattedDate);
$objects->updatedOn = array('type'=>'__date','date'=>$formattedDate);
}// ./ foreach
// Save data into the JSON file
$jsonStr = file_get_contents($className.'.json');
// Decode the JSON string into a PHP array.
$jsonObjs = json_decode($jsonStr, true);
// Check if there's some new key and values -> update the $jsonObjs array
$result = array_diff($jsonObjs, $objects);
print_r('<br><br>DIFFERENCE: <br>'.$result[0].'<br>');
// Push array
array_push($jsonObjs, $objects);
// Encode the array back into a JSON string and save it.
$jsonData = json_encode($jsonObjs);
file_put_contents($className.'.json', $jsonData);
// echo JSON data
echo $jsonData;
I'm trying to get the difference between $jsonObjs and $objects with array_diff():
$result = array_diff($jsonObjs, $objects);
print_r(.$result[0].'<br>');
but it dones't work, it shows an empty row and also the error_log file shows this:
PHP Warning: array_diff(): Argument #2 is not an array on line 63
I launch 2 URL strings, the first one starts with
create.php?className=Users&string=lorem%20ipsum
In the 2nd one, I add an additional string object, like this:
create.php?className=Users&string=lorem%20ipsum&username=johndoe
So, what I need to achieve is to add the "username" key into the 1st object too, as it does on the 2nd object. In other words, my Users.json file should look like this after launching the 2nd URL string:
[
{
"objID":"Y0FVVFZYCV",
"username":"", //<-- upodated key with no value
"createdOn":{"type":"__date","date":"2018-09-21T16:48:09"},
"string":"lorem ipsum"
},
{
"objID":"YShAUqIcMg",
"username":"johndoe", // new key->value here!
"createdOn":{"type":"__date","date":"2018-09-21T16:48:14"},
"string":"lorem ipsum"
}
]
As was already pointed out in the comments, you can't pass "$objects" to the array_diff function because it expects an array and "$objects" is, well, an Object.
You could cast your object to an array by calling it like this:
$result = array_diff($jsonObjs, (array)$objects);
As pointed out my #miken32, my $objects object wasn't an array, but an StdClass Object, so I simply had to replace:
$objects->
with:
$objects[$key]
In this way, $objects becomes a valid array and I can use array_diff() like this:
$result = array_diff_assoc($jsonObjs, $objects);
print_r('DIFF: '.json_encode($result).'<hr>');
It prints out a valid JSON array.
So this is my very simple and basic account system (Just a school project), I would like the users to be able to change their password. But I am unsure on how to just replace the Password value within a row keeping all the other values the same.
CSV File:
ID,Username,Email,DateJoined,Password,UserScore,profilePics
1,Test,Test#Test.com,03/12/2014,Test,10,uploads/profilePics/Test.jpg
2,Alfie,Alfie#test.com,05/12/2014,1234,136,uploads/profilePics/Alfie.png
PHP:
("cNewPassword" = confirm new password)
<?php
session_start();
if(empty($_POST['oldPassword']) || empty($_POST['newPassword']) || empty($_POST['cNewPassword'])) {
die("ERROR|Please fill out all of the fields.");
} else {
if($_POST['newPassword'] == $_POST['cNewPassword']) {
if ($_POST['oldPassword'] == $_SESSION['password']) {
$file = "Database/Users.csv";
$fh = fopen($file, "w");
while(! feof($file)) {
$rows = fgetcsv($file);
if ($rows[4] == $_POST['oldPassword'] && $rows[1] == $_SESSION['username']) {
//Replace line here
echo("SUCCESS|Password changed!");
}
}
fclose($file);
}
die("ERROR|Your current password is not correct!");
}
die("ERROR|New passwords do not match!");
}
?>
You'll have to open file in read mode, open a temporary one in write mode, write there modified data, and then delete/rename files. I'd suggest trying to set up a real DB and work using it but if you're going for the csv, the code should look like more or less like this:
$input = fopen('Database/Users.csv', 'r'); //open for reading
$output = fopen('Database/temporary.csv', 'w'); //open for writing
while( false !== ( $data = fgetcsv($input) ) ){ //read each line as an array
//modify data here
if ($data[4] == $_POST['oldPassword'] && $data[1] == $_SESSION['username']) {
//Replace line here
$data[4] = $_POST['newPassword'];
echo("SUCCESS|Password changed!");
}
//write modified data to new file
fputcsv( $output, $data);
}
//close both files
fclose( $input );
fclose( $output );
//clean up
unlink('Database/Users.csv');// Delete obsolete BD
rename('Database/temporary.csv', 'Database/Users.csv'); //Rename temporary to new
Hope it helps.
My suggestion is a little function of mine which will turn your database data into an array which you can modify and then return to original state:
With this set of function, you simply have to precise how each row/row data are separated.
function dbToArray($db, $row_separator = "\n", $data_separator = ",") {
// Let's seperator each row of data.
$separate = explode($row_separator, $db);
// First line is always the table column name:
$table_columns =
$table_rows = array();
foreach ($separate as $key => $row) {
// Now let's get each column data out.
$data = explode($data_separator, $row);
// I always assume the first $row of data contains the column names.
if ($key == 0)
$table_columns = $data;
else if ($key > 0 && count($table_columns) == count($data)) // Let's just make sure column amount matches.
$table_rows[] = array_combine($table_columns, $data);
}
// Return an array with columns, and rows; each row data is bound with it's equivalent column name.
return array(
'columns' => $table_columns,
'rows' => $table_rows,
);
}
function arrayToDb(array $db, $row_separator = "\n", $data_separator = ",") {
// A valid db array must contain a columns and rows keys.
if (isset($db['columns']) && isset($db['rows'])) {
// Let's now make sure it contains an array. (This might too exagerated of me to check that)
$db['columns'] = (array) $db['columns'];
$db['rows'] = (array) $db['rows'];
// Now let's rewrite the db string imploding columns:
$returnDB = implode($data_separator, $db['columns']).$row_separator;
foreach ($db['rows'] as $row) {
// And imploding each row data.
$returnDB .= implode($data_separator, $row).$row_separator;
}
// Retunr the data.
return $returnDB;
}
// Faaaaaaaaaaaail !
return FALSE;
}
Let's just point out I tried these with your db example, and it works even when tested on it's own results such as : dbToArray(arrayToDb(dbToArray())) multiple times.
Hope that help. If I can be clearer don't hesitate. :)
Cheers,
You need a 3 step process to do this (create 3 loops, could be optimized to 1 or 2 loops):
Load the relevant data to memory
Update the desired data
Save the data to the file
Good luck! :)
PS. Also your passwords should never been stored in clear text, wether in memory(session) or on disk(csv), use a hasing function!
I'm trying to implement the following feature. When someone reads an article, I want to add a cookie that stores the article id so I can use this in another page. My issue is that if the user sees another article, then the cookie is rewritten so the old id is deleted. I want to keep in the cookie all the ids of the seen articles.
Setting the cookie
<?php
// Check if cookie exists
if( isset($_COOKIE["read"]) ) {
$array = unserialize($_COOKIE['read']);
// Iterate array
found = False;
foreach ($array as $i) {
// Check if doc id already in cookie
if ($array[$i] == $id) {
found = True;
}
}
if (!found) {
array_push($array, $id);
setcookie("read", serialize($array), time()+3600);
}
}
// If cookie does NOT exists
else {
$array = array();
array_push($array, $id);
setcookie("read", serialize($array), time()+3600);
}
?>
Reading the cookie to show that the article is read
<?php
while($row = mysqli_fetch_array($result)){
$id = $row['id'];
if( isset($_COOKIE["read"]) ) {
$array = unserialize($_COOKIE['read']);
// Iterate array
for ($i = 0; $i < count($array); ++$i) {
if ($array[$i] == $id) {
$read = True;
}
else {
$read = False;
}
}
}
else {
$read = False;
}
print "<p>Document ".$row['id']." Title: <b>".$row['title']."</b>";
if ($read == True) {
print("*");
}
print " More Info</p>";
}
?>
This code works but as said overwrites the previous article id. I think I got to use an array. But I don't know how to keep adding values.
UPDATE: I tried to serialize but still no results. I'm trying to see if the id is inside the unserialized array.
Do you want Arrays in cookies PHP
Serialize data:
setcookie('cookie', serialize($idS));
Then unserialize data:
$idS= unserialize($_COOKIE['cookie']);
Try adding a datetime() string to the start of the cookie's name. That way old ones won't get overwritten. Something like:
$date_snippet = date('Y-m-d H:i:s');
setcookie("{$date_snippet}read", serialize($array), time()+3600);
I am trying to validate whether or not an array is listed in an array.
I am trying to add a product name and url to an session, the session will contain all the products visited by a visitor, but I don't want it to add the same product twice, hence the validation. So if the product is already in the array, I want it to do nothing, but if it doesn't already belong to the array, it needs to be added. This is as far as I got so far. The only issue seems to be the validation.
$viewed_product_url = $viewed_base.$_SERVER['REQUEST_URI'];
if(!isset($_SESSION['products'])) {
$_SESSION['products'] = array('product'=>$products_name,'url'=>$viewed_product_url);
} else {
$found = false;
foreach($_SESSION['products'] as $each_item) {
while(list($key,$value)=each($each_item)) {
if($key == 'product' && $value == $products_name) {
$found = true;
}
}
}
if($found==false){
echo 'found';
$_SESSION['products'][] = array('product'=>$products_name,'url'=>$viewed_product_url);
}
}
these are the errors I am getting
Warning: Variable passed to each() is not an array or object in C:\xampp\htdocs\customers\msl\product.php on line 10
Warning: Variable passed to each() is not an array or object in C:\xampp\htdocs\customers\msl\product.php on line 10
found
So I just want to know how you can check if an array is already in an multivariate array. Or if there are any other alternatives to achieving what I want here.
Change:
$_SESSION['products'] = array('product'=>$products_name,'url'=>$viewed_product_url);
to:
$_SESSION['products'] = array(array('product'=>$products_name,'url'=>$viewed_product_url));
so that you get a 2-dimensional array.
However, I think this is a poor data structure. You should make $_SESSION['products'] an associative array, whose key is the product name. So you add elements to it with:
$_SESSION['products'][$products_name] = $viewed_product_url;
and you find products with:
$found = isset($_SESSION['products'][$products_name]);
check with is_array like
if(is_array($_SESSION['products']))
and then you can go with foreach
is_array() function will help you..
http://php.net/manual/en/function.is-array.php
$each_item is not an array. That is the reason for the error.
Try this
$viewed_product_url = $viewed_base.$_SERVER['REQUEST_URI'];
if(!isset($_SESSION['products'])) {
$_SESSION['products'] = array('product'=>$products_name,'url'=>$viewed_product_url);
} else {
$found = false;
if (in_array($viewed_product_url, $_SESSION['products'])) { {
$found = true;
}
}
}
if($found==false){
echo 'found';
$_SESSION['products'][] = array('product'=>$products_name,'url'=>$viewed_product_url);
}
}
my Current json code :
{"Results":[{"username":"test","password":"test"},{"username":"test","password":"test"},{"username":"google","password":"test"},{"username":"yahoo","password":"test"},{"username":"hotmail","password":"test"}]}
i want to remove this :
{"username":"google","password":"test"}
from the code using php.
i tried deleting by decoding json to array but cant get it done.
any solution ?
$json_obj = json_decode($json_string);
$unset_queue = array();
foreach ( $json_obj->Results as $i => $item )
{
if ($item->username == "google")
{
$unset_queue[] = $i;
}
}
foreach ( $unset_queue as $index )
{
unset($json_obj->Results[$index]);
}
// rebase the array
$json_obj->Results = array_values($json_obj->Results);
$new_json_string = json_encode($json_obj);
<?php
$JSON = '{"Results":['
. '{"username":"test","password":"test"},'
. '{"username":"test","password":"test"},'
. '{"username":"google","password":"test"},'
. '{"username":"yahoo","password":"test"},'
. '{"username":"hotmail","password":"test"}'
. ']}';
// use json_decode to parse the JSON data in to a PHP object
$jsonInPHP = json_decode($JSON);
// now iterate over the results and remove the one that's google
$results = count($jsonInPHP->Results);
for ($r = 0; $r < $results; $r++){
// look for the entry we are trying to find
if ($jsonInPHP->Results[$r]->username == 'google'
&& $jsonInPHP->Results[$r]->password == 'test'){
// remove the match
unset($jsonInPHP->Results[$r]);
// now we can either break out of the loop (only remove first match)
// or you can use subtract one from $r ($r--;) and keep going and
// find all possible matches--your decision.
break;
}
}
// now that we removed items the keys will be off. let's re-order the keys
// so they're back in-line
$jsonInPHP->Results = array_values($jsonInPHP->Results);
// dump the new JSON data, less google's entry
echo json_encode($jsonInPHP);
Would be how I approach it. I like to avoid foreach(...){} statements when I need to modify the array itself. The above code, by the way, leaves you with:
{
"Results":[
{"username":"test","password":"test"},
{"username":"test","password":"test"},
{"username":"yahoo","password":"test"},
{"username":"hotmail","password":"test"}
]
}
$json = '
{
"Results":[
{"username":"test","password":"test"},
{"username":"test","password":"test"},
{"username":"google","password":"test"},
{"username":"yahoo","password":"test"},
{"username":"hotmail","password":"test"}
]
}';
$arr = json_decode($json, true);
array_filter($arr, function($v) {
return !($v['username'] == 'google' && $v['password'] == 'test');
});
$json = json_encode($arr);
$input='{"Results":[{"username":"test","password":"test"},{"username":"test","password":"test"},{"username":"google","password":"test"},{"username":"yahoo","password":"test"},{"username":"hotmail","password":"test"}]}';
$json = json_decode($input,true);
$match = array('username'=>'google', 'password'=>'test');
unset($json['Results'][array_search($match,$json['Results'])]);
To do it without a foreach but assuming you know the exact values you want to remove
Old question, formatting your JSON differently would help a lot.
Each result entry should have a unique key to identify it.
This makes it easy when needing to remove or update that result.
No reason to iterate over entire JSON this way.
Code would look like this
<?php
$jsonString = '{"Results":{'
.'{"username1":{"username":"google","password":"test1"}}'
.'{"username2":{"username":"yahoo","password":"test2"}}'
.'{"username3":{"username":"msonline","password":"test3"}}'
. '}}';
$jsonInPHP = json_decode($jsonString);
$password = $jsonInPHP["username1"]["pasword"];//Returns test1
$username = $jsonInPHP["username1"]["username"];//Returns google
?>
$myArray=json_decode($theJSONstring);
unset($myArray['Results'][2]);