Build a json in php from POST data - php

I need to update a json list of object via url post data. For example, with url:
http://myweb.com/index.php?name=Peter&surname=Brown
in php, using get method:
$name = $_GET["name"];
$surname = $_GET["surname"];
$json = array();
$json["nombre"] = $name;
$json["lat"] = $lat;
$data[] = $json;
$json_end= json_encode($data);
and json_end efectively is done like I want:
[{"name":"Peter","surname":"Brown"}]
My question is about how I can do it incrementing the json, in order to build an array like:
[{"name":"Peter","surname":"Brown"}]
[{"name":"newname","surname":"newsurname"}]
// and so on
each time user use the url with new parameters.
Do I need to write to a file, or to database? Any tips will be apreciated.
The idea is to be able that any user can add some dat using url. I tried to store the json to a fiel but the storing is durable only along the current session.

<?
/* This needs to be at the top of your file, without ANYTHING above it */
session_start();
/* ... */
if(!array_key_exists('entries', $_SESSION))
{
$_SESSION['entries'] = array();
}
$_SESSION['entries'][] = array("name" => $_GET["name"], "surname" => $_GET["surname"]);
$json_string = json_encode($_SESSION['entries']);
This would produce a single JSON. However I don't know whether you meant to or not, but your output is a series of separate JSONs. You could do this by replacing the last line above with:
$json_string = '';
foreach($_SESSION['entries'] as $entry){
$json_string.= json_encode($entry) . "\n";
}
You would also probably want a way to reset/empty the array. In which case I'd change the if test from:
if(!array_key_exists('entries', $_SESSION))
to:
if(!array_key_exists('entries', $_SESSION) || array_key_exists('reset', $_GET))
Which you could use by visiting
http://myweb.com/index.php?reset
Edit: If somewhere you add the following code:
foreach($_SESSION['entries'] as $id=>$entry){
printf("%2d: %s\n", $id, json_encode($entry));
}
You'll get a list of the json elements enumerated by their respective keys. For example, it might look like:
0: "[{\"name\":\"Peter\",\"surname\":\"Brown\"}]"
1: "[{\"name\":\"newname\",\"surname\":\"newsurname\"}]"
2: "[{\"name\":\"George\",\"surname\":\"Washington\"}]"
3: "[{\"name\":\"John\",\"surname\":\"Adams\"}]"
If you then add the following code:
if(array_key_exists('del', $_GET) && is_numeric($_GET['del']))
{
$key = (int)$_GET['del'];
if(array_key_exists($key, $_SESSION['entries']))
{
unset($_SESSION['entries'][$key]);
}
else
{
printf('<strong>ERROR: $_GET['del'] = %d but $_SESSION['entries'][%d] doesn't exist.</strong>', $key, $key);
}
}
you'll be able to delete individual json entries by specifying id as the del GET parameter.
For example,
http://myweb.com/index.php?del=2
would delete the entry corresponding to '[{"name":"George","surname":"Washington"}]';
And the remaining entries would be:
0: "[{\"name\":\"Peter\",\"surname\":\"Brown\"}]"
1: "[{\"name\":\"newname\",\"surname\":\"newsurname\"}]"
3: "[{\"name\":\"John\",\"surname\":\"Adams\"}]"
4: "[{\"name\":\"Thomas\",\"surname\":\"Jefferson\"}]"

Just make a nested array of users:
$data = array (
0 => array("name"=>"Peter","surname"=>"Brown"),
1 => array("name"=>"newname","surname"=>"newsurname")
);
echo json_encode($data);
// [{"name":"Peter","surname":"Brown"},{"name":"newname","surname":"newsurname"}]

I think it would be easiest to store the data in a session, something like this:
<?php
session_start();
if (isset($_GET['name'])) {
$_SESSION['json'][] = $_GET;
}
echo json_encode($_SESSION['json']);
?>
Edit: You may want to filter the $_GET array before storing it in the session so that you don't store values that aren't meant to be stored.
Edit: Of course, if you want to save this data for more than one session you would need to use files or a database (or perhaps a cookie). It all depends on what you want to do with the information.

Related

Unpacking an array_value()'d $_POST array

I'm having some issues that I suspect are from misunderstanding how to handle $_POST data from a web form. It's racking my brains, because my method works in one scenario, but breaks in its successor.
In a nutshell: I can call key=>value pairs of $_POST in a method, but I can't manipulate the $_POST array itself, which always returns as 1.
Initial Scenario. Refer to comments for context & gripes. This method works:
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$post = $_POST; // I'm aware $_POST is a superglobal and can be called within the method
$cms->addPage($table, $post);
}
addPage() Method from CMS class:
public function addPage($table, $post) {
global $db; // SQL object declared in config
$url = preg_replace('/\s+/', '-', $post['pageTitle']);
$vals = array($post['pageTitle'], $post['isRoot'], $post['metaTitle'], $post['metaDesc'], $post['pageCont'], $url, $post['dateCreated'], $post['pageBanner']);
$cols = array("pageTitle", "isRoot", "metaTitle", "metaDesc", "pageCont", "pageURL", "dateCreated", "pageBanner");
$types = "sissssss";
$db->prep_Insert($table, $cols);
$db->bind_Prep($types, $vals); // This method unpacks the $vals array with ...
$db->execute_Prep();
$db->close_Prep();
$_SESSION['success'] = 'Page Updated';
header('Location: ' . DIRADMIN . 'manage/pages');
exit();
}
This works fine. Pops right up in the database, and bob's your uncle. But, this CMS should be able to handle multiple form objects, and I don't want to write an add / update method for every custom feature a client might want. So I came up with this:
public function addContent($table, $post, $types) {
global $db;
$cols = self::getColumns($table); // Helper method I wrote to get column names from the table being added to
array_shift($cols); // AUTO_INCREMENT is set in database, so knock off the ID row
/* This is where it falls apart. All I want is to take the $_POST array
I got from the form and reduce it from associative to indexed.
The array_values() should do this, right? */
$post = array_values($post);
// $post = array_values($_POST);
/* Also doesn't work. It doesn't matter if I pass forward the
$_POST array as a parameter, or if I call it directly here. */
/* Second attempt at getting $_POST into an indexed array. I don't need the keys. */
/*$i = 0;
$vals = array();
foreach ($_POST as $key => $value) {
$vals[$i] = $value;
$i++;
}*/
$db->prep_Insert($table, $cols);
$db->bind_Prep($types, $post); // This is where I got the initial unpacking error; can't unpack associative arrays. Okay, I'll use array_value($_POST). Except, that always just outputs 1, and breaks the prep statement anyway.
$db->execute_Prep();
$db->close_Prep();
$_SESSION['success'] = 'Page Updated';
header('Location: ' . DIRADMIN . 'manage/' . $table);
exit();
}
So to reiterate, for some reason I can get $_POST data by its individual key=>value pairs in the initial method, but if I try to manipulate the $_POST array in any way (array_keys(), reset(), foreach loop, etc), it will output as 1. print_r() outputs 1, var_dump() outputs blank, and in the exception message it returns as 1.
Is there some limitation or rule to handling $_POST data that I'm not getting? I can't figure out why I can get key value pairs, but otherwise can't manipulate it at all.

How to get multiple values of same param for url

I'm building a PHP querying a mongodo database. I need to retreive the value of a param from the url, and there is potentially more than one.
An example url would look like this
http://localhost/api/v1/report-01?type=EE&type=ER
How would I retrieve the two values from type.
At the moment I'm only get one, and it's the last one.
if (isset($params["TYPE"]) && in_array($params["TYPE"], ["EE", "ER"])) {
$matchPipeline["TYPE"] = $params["TYPE"];
echo "Printing Variables";
echo $params["TYPE"];
}
The code is only printing ER
This SO answer provides a good suggestion on how to do this. Add [] to the parameter name, so in your case the url might look like:
http://localhost/api/v1/report-01?type[]=EE&type[]=ER
Then PHP will automatically create an array of all the type[] values.
Just add to your link after every param(type) this []
example
http://localhost/api/v1/report-01?type[]=EE&type[]=ER
or follow this
<?php
$params = $_GET;
/*
echo $params['type'][0];
-> ANSWER = EE;
echo $params['type'][1];
-> ANSWER = ER;
*/
if(isset($params['type']) && is_array($params)){
echo "Printing Variables<br>";
foreach ($params as $get){
echo $get[0]."<br>";
echo $get[1]."<br>";
}
}
?>

Why does this json_encoded string NOT return the fourth element?

I'm trying to echo a simple json_encoded file.
<?php
$allMessages = file_get_contents("chatmessages.txt");
$allMessagesArr = explode(PHP_EOL, $allMessages);
$newObj = [];
var_dump($allMessagesArr);
foreach ($allMessagesArr as $thisLine) {
// echo($thisLine . "\n");
if (empty($thisLine) ) {
} else {
$thisLineArr = explode("|", $thisLine);
$newObj[trim($thisLineArr[0])] = trim($thisLineArr[1]);
// echo("here comes another one ".$thisLineArr[0] . " : ". $thisLineArr[1]."\n");
}
}
$newObjForFront = json_encode($newObj);
echo($newObjForFront);
chatmessages.txt looks like this
bob|hello
jimmy|second try incoming again
sam|third try
bob|oh damn
I've echoed each individual line within the loop and the fourth element appears. However, when I echo $newObjForFront, it's missing the last element. Any ideas why?
When you create your final array $newObj in
$newObj[trim($thisLineArr[0])] = trim($thisLineArr[1]);
Your using the name as the index to the array. As array indexes have to be unique, this means in fact the last entry overwrites the first one, so your actual output is...
{"bob":"oh damn","jimmy":"second try incoming again","sam":"third try"}
So it is in fact the first message that is missing.
Edit:
If you wanted to just have all of the messages, then you could store them using
$newObj[] = [ "user"=> trim($thisLineArr[0]), "msg" =>trim($thisLineArr[1])];
Which would give you the output as...
[{"user":"bob","msg":"hello"},{"user":"jimmy","msg":"second try incoming again"},{"user":"sam","msg":"third try"},{"user":"bob","msg":"oh damn"}]
$newObj[trim($thisLineArr[0])] = trim($thisLineArr[1]); this line will replace value with the last message of any username. if any username have multiple messages then only last message will be stored in the array.
By creating multidimensional you can store multiple messages with the same username. Check below code that may help you
$newObj[][trim($thisLineArr[0])] = trim($thisLineArr[1]);

Updating a PHP array of POST datas, before processing them

I need to apply some functions to a key items inside an array before moving on with the whole array, but I probably miss something.
Here is my code:
// Get generated datas
$data_post = $this->input->post('form_data'); // Need to update this array
foreach( $data_post as $data ){
$data['password'] = password_encrypt($data['password']);
var_dump($data); // Password encryption succeed
}
var_dump($data_post); // But here, the password is still the same, no encryption applied
So as commented in the CODE section, how should I update the main $data_post array with the modifications made in foreach() ?
Inside a foreach, data isn't passed by reference. This means that modifying the variable $data doesn't modify $data_post. You can modify the original array in more than one way, but here is how I would do it:
foreach( $data_post as $key => $data ){
$data_post[$key]['password'] = password_encrypt($data['password']);
}
Note that this presumes that $data_post contains multiple sub arrays, each with the password key (or else notices will be thrown).
Try this:
$data_post = $this->input->post('form_data'); // Need to update this array
foreach( $data_post as $k=>$v ){
if($k == "password"){
$data_post[$k] = password_encrypt($v);
}
}
var_dump($data_post);

PHP split and mongodb

ok, this might sound strange, but i have a form and our business wants to track what is getting changed, when a user adds a new lead etc.
So i set up a function that does the following
function savedata($data){
$collection = $this->db->retail_logs;
$this->data = explode('|', $data['data']);
print_r($this->data);
try {
$collection->update(
array($this->data['0']=>$this->data['1'],$this->data[2]=>$this->data[3]),
array("date"=> date("d.m.Y"), "time"=>date("H:i:s"),"whochanged"=>$_COOKIE['CRMUIDkey']), // new lead document to insert
array("upsert" => true, "safe" => true)
);
} catch (Exception $e) {
// Something went wrong ..
}
}
it is basiclly a log file.
but as you may be able to see the $data sends data though like tradingname|ABC|owner|ownerID
But if I want to add to that i would need to run a loop or a foreach I am wondering what is the best way to make sure all teh data gets saved and not just data[0] to 3 so say they send 16 fields and values in it I need a foreach or something to split it.
It appears that you want to map the $data['data'] into key=>value pairs (an associative array). You want to be very careful about what fields you allow in this format especially since it looks like user-provided data (or data they can modify in a post request?). For example, a malicious user could update or add to another user's account if you aren't checking the allowed keys before doing the upsert.
To convert the $data string you want to do something like:
<?php
// Keys that can be updated
$allowed = array('tradingname','owner');
// Sample data
$data = 'tradingname|ABC|owner|ownerID|badkey|foo';
// Split into arrays based on '|' delimiter
preg_match_all("/([^\|]+)\|([^\|]+)/", $data, $keypairs);
// Combine matches into key => value array
$keypairs = array_combine($keypairs[1], $keypairs[2]);
// Sanity check to create $criteria
foreach ($keypairs as $key => $value) {
if (in_array($key, $allowed)) {
// Perhaps do some extra sanity checking that $value is expected format
$criteria[$key] = $value;
} else {
// Log and/or bailout as appropriate
echo "Ignoring: [$key] => [$value]\n";
}
}
// Criteria should now be reasonable to use in $collection->update(..) upsert
print_r($criteria);
?>
Send your data as json. And then use json_decode to convert it to the array you want.

Categories