CakePHP 2 requestAction breaks my JSON encoding to Swift... invisibly - php

I've got CakePHP 2 outputting JSON, and I've got Swift 2 code in the Xcode iPhone emulator loading that JSON data.
In my Controller, here's the code that generates the JSON:
public function iosDemoIndex() {
$studentDataIn = $this->Student->getStudentsByUserId(298, 'rASC');
$studentDataOut = [];
foreach ($studentDataIn as $student) {
//$currentIep = $this->Iep->requestAction('/ieps/getCurrentIep/' . $student['Student']['id']);
$goals = $this->Goal->find('all', array('conditions' => array('Goal.student_id =' => $student['Student']['id'])));
$goalHolder = array();
foreach ($goals as $goal) {
array_push($goalHolder, $goal['Goal']['goal_title']);
}
array_push($studentDataOut, array('studentName' => $student['Student']['l_name']. ", " . $student['Student']['f_name'], 'studentGoals' => $goalHolder));
}
$this->set(array(
'students' => $studentDataOut,
'_serialize' => array('students')
));
}
Which works fine. My Swift code succesfully loads the students array via the JSON into an array of structs. But if I simply un-comment line 5 (which grabs data that I ultimately hope to use to restrict the find in line 6), Xcode gives me:
Error with Json: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 2." UserInfo={NSDebugDescription=Invalid value around character 2.}
Line 5 shouldn't alter the JSON document in any way. And when I look at the JSON itself, it looks the same regardless of whether the line's commented out.
So, any ideas what an unrelated, ought-to-be invisible requestAction could be doing that's breaking my JSON... in a way that I can't see when I look at it? Thanks.

For posterity (future-me):
It was a login issue. The reason the JSON looked identical in my browser was that I had an active user session in the browser at the time. Without that session, (for instance when the iOS emulator tried to load the JSON page) the CakePHP was returning a redirect to login. Viable solutions include replicating the requestAction code in the JSON-generating controller (though that's not very DRY), or establishing proper login handling on the Swift side of things.

Related

json string passed in url which is encoded by urlencode

I am using CodeIgniter 3.x.
User have this data : %7B%5C%22uid%5C%22%3A%5C%221234%5C%22%2C%5C%22uname%5C%22%3A%5C%22kishor%5C%22%7D
User send me the request and pass the data as parameter in url. The last parameter in url is nothing but the users data.
http://localhost/codeigniter/myproject/myfunction/%7B%5C%22uid%5C%22%3A%5C%221234%5C%22%2C%5C%22uname%5C%22%3A%5C%22kishor%5C%22%7D
The encoded data nothing but a json string which he want to encode and then send me the request. If I parse it using php then it yields this : '{"uid":"1234","uname":"kishor"}'
But it is not accepted in url, it gives me Object not found! error in browser.
Object not found!
The requested URL was not found on this server. If you entered the URL manually please check your spelling and try again.
If you think this is a server error, please contact the webmaster.
Error 404
I tried changing $config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-';, but it doesn't work for me.
Assuming that your CodeIgniter is set up properly and routing things correctly then I recommend sending the JSON as a $_GET parameter:
http://localhost/codeigniter/myproject/myfunction/?json=%7B%5C%22uid%5C%22%3A%5C%221234%5C%22%2C%5C%22uname%5C%22%3A%5C%22kishor%5C%22%7D
So in CodeIgniter, you should be able to simply:
json_decode( $this->input->get( 'json' ) );
If you pass the below way than you have to pass argument in function.
http://localhost/codeigniter/myproject/myfunction/%7B%5C%22uid%5C%22%3A%5C%221234%5C%22%2C%5C%22uname%5C%22%3A%5C%22kishor%5C%22%7D
like this
function myfunction($param = ''){ echo $params; }
The way you are passing is not a proper way. If you need to get and decode that value, use following way in your controller function
i dont know which one is controller & function in your code, I guess myproject is a controller. So, i'm passing 3rd parameter Number 3 in segment
// it will return %7B%5C%22uid%5C%22%3A%5C%221234%5C%22%2C%5C%22uname%5C%22%3A%5C%22kishor%5C%22%7D
$json_value = $this->uri->segment(3);
$json_value = (array) json_decode(stripslashes(urldecode($json_value)));
var_export($json_value);
output
array (
'uid' => '1234',
'uname' => 'kishor',
)

PHP Receive JSON POST Data

I am trying to receive JSON data from an external system, and then process and save to my local DB. When an event triggers, the external system sends the data below to my system.
The external system logs show:
Log 1: Date/Time: 16 August 2017 11:54:44 AM
Status: Failure
Server: Apache https://blahblah.com/abc/data.php
Status Code: OK
Event Content: [{"field":"_USERNAME","value":""},
{"field":"_PASSWORD","value":""},
{"field":"_TOKEN","value":""},
{"field":"_CODE","value":"L77H4XD6ZA"},
{"field":"_SUBMITTEDDATE","value":"2017.08.16.01.54"},
{"field":"_SUBMITTEDDATEEXT","value":"2017.08.16.01.54.39.610"},
{"field":"_EDITEDDATE","value":"2017.08.16.01.55"},
{"field":"_SEQUENTIALID","value":"39a1cad9-2582-e711-9477-06c7814985cc"},
{"field":"_COMPLETETYPE","value":"Complete"},
{"field":"_LANGUAGE","value":"en"},
{"field":"_TOTALTIME","value":"12.59"},{"field":"_LINKURL","value":"http%3a%2f%2fsurv.blah.com%2ftest3%3fusr%3dL77H4XD6ZA"},
{"field":"GENDER","value":"TEXT%3aFemale%3bVALUE%3a2"},
{"field":"AGE","value":"TEXT%3a40%2b-%2b44%3bVALUE%3a6"},
{"field":"STATE","value":"TEXT%3aVIC%3bVALUE%3a2"},
{"field":"END_CHC","value":"TEXT%3aComplete%3bVALUE%3a2"},
{"field":"D2H","value":""},
{"field":"D2V","value":""},
{"field":"PCODE","value":""},
{"field":"PSTATE","value":""},
{"field":"PREGION","value":""},
{"field":"STATEREGION","value":""},
{"field":"TEST1","value":""}]
So, in my php file (https://blahblah.com/abc/data.php) I have
$json = file_get_contents('php://input');
$obj = json_decode($json);
and I have been trying a foreach() loop to try and get each field and value, to then put into a database, like
foreach($obj as $key => $value)
{
$qry = $conn->prepare('INSERT INTO `key_value`(`db_id`, `rkey`, `rvalue`) VALUES (NULL,$key,$value)');
$qry->execute();
}
But it isn't working, and I either get errors about the foreach loop, or if I play around with just echoing or var_dumping, I get NULL in the response, when I use the Postman or ARC Chrome API testing Apps.
So, I suspect I am on the completely wrong track of how to do this.
Can anyone help guide me back?
EDIT: I have had a look at Receive JSON POST with PHP and a few others, but the working answers aren't clear.
You've got a couple of problems here. First, you need to pass true as the second parameter to json_decode in order to get an associative array instead of a stdClass. Then, when you're iterating the results, you don't need the $key, and the $value is each entry in the results array (each "row"). Try running this to see what's going on:
<?php
$json = <<<JSON
[{"field":"_USERNAME","value":""},
{"field":"_PASSWORD","value":""},
{"field":"_TOKEN","value":""},
{"field":"_CODE","value":"L77H4XD6ZA"},
{"field":"_SUBMITTEDDATE","value":"2017.08.16.01.54"},
{"field":"_SUBMITTEDDATEEXT","value":"2017.08.16.01.54.39.610"},
{"field":"_EDITEDDATE","value":"2017.08.16.01.55"},
{"field":"_SEQUENTIALID","value":"39a1cad9-2582-e711-9477-06c7814985cc"},
{"field":"_COMPLETETYPE","value":"Complete"},
{"field":"_LANGUAGE","value":"en"},
{"field":"_TOTALTIME","value":"12.59"},{"field":"_LINKURL","value":"http%3a%2f%2fsurv.blah.com%2ftest3%3fusr%3dL77H4XD6ZA"},
{"field":"GENDER","value":"TEXT%3aFemale%3bVALUE%3a2"},
{"field":"AGE","value":"TEXT%3a40%2b-%2b44%3bVALUE%3a6"},
{"field":"STATE","value":"TEXT%3aVIC%3bVALUE%3a2"},
{"field":"END_CHC","value":"TEXT%3aComplete%3bVALUE%3a2"},
{"field":"D2H","value":""},
{"field":"D2V","value":""},
{"field":"PCODE","value":""},
{"field":"PSTATE","value":""},
{"field":"PREGION","value":""},
{"field":"STATEREGION","value":""},
{"field":"TEST1","value":""}]
JSON;
$obj = json_decode($json, true);
foreach($obj as $currTuple)
{
echo $currTuple['field'].':'.urldecode($currTuple['value'])."\n";
}
Also some of the results are url encoded, so you'll probably want to decode that before persisting.

Curl and codeigniter passing in POST data from an from into the url

Tying myself in knots a little bit with cURL. Using codeigniter for my framework and downloaded the CURL lib from getsparks.org/packages/curl .
I have this URL http://localhost:8984/rest?run=loc.xq&$a=York so this is a Rest for BaseX that I pass in a city (like York) and it shows me a carpark, This works in my browser. So what i wanted to do is have a user type the name into a form and pass that to basex and display the results. I have me view, controller set up, and this is currently the code I have in the controller
$this->load->library('curl');
$url = "http://localhost:8984/rest?run=loc.xq&$a=";
$datai = array($this->input->POST('carpark_location'));
$results = $this->curl->simple_get($url,$datai);
so this to me looks right, but its not, comes back with an error,
Message: Undefined variable: a
which I am guessing its picking $a out of the text as a variable, how would I make it ignore that?
not sure if just that will solve my issue but printing out the $url and $datai looks like below?
http://localhost:8984/rest?run=loc.xq&=Array ( [0] => York )
what am I missing?
Try this instead:
$url = 'http://localhost:8984/rest?run=loc.xq&$a='
Because it is inside single quotes instead of double quotes, PHP should treat $a as if it is part of the string instead of as a variable.

How can I bulk update a basic one-to-one key structure located in a.html file with script or text editor like this?

I have a one-to-one key structure of zip codes to user located in a .html that looks like...
...
'80135': 'user1',
'80136': 'user1',
'80137': '',
'80138': '',
'80202': 'user2',
'80203': 'user2',
'80204': '',
'80205': '',
'80206': '',
'80207': '',
...
I would like to take a bulk list zip codes for user3 and fill in or over-write old user. So for example if I have for user3, zip codes (80202,80203,80204) then my previous block of code would change to...
...
'80135': 'user1',
'80136': 'user1',
'80137': '',
'80138': '',
'80202': 'user3',
'80203': 'user3',
'80204': 'user3',
'80205': '',
'80206': '',
'80207': '',
...
The reason for text editor is to complete my set now, but ideally it would be nice to have a client application that our non-programmer team can update and make changes as they please, so a script for this would be nice for future plans.
I am passing the content into my site via...
var list_load = {<?php include_once('list.html'); ?>};
Because I believe some might have an alternate idea on storage of this information, this list is very long, 35,000 lines of code, so any ideas on completely changing my code consider a process to migrate data.
Based on the information you provided I'm going to assume your example code is a subset of a JSON object. I'm also going to assume that you only have a one-to-one relationship of zip-codes to users in your object given that you did not explicitly state otherwise and given that the existing object structure would not allow for one-to-many relationship. Given all these assumptions the solution to your immediate problem is to load the JSON into PHP, make your changes there, and then overwrite the entire file with the updated JSON object.
$json = file_get_contents('list.html');
$array = json_decode($json, true);
$oldUser = 'user2';
$newUser = 'user3';
$listZipCodes = array("80204"); // list of zip codes to update
// Update the JSON based on user ...
foreach ($array as $zipCode => $user) {
if ($user === $oldUser) {
$array[$zipCode] = $newUser;
}
}
// Update the JSON based on zip code ...
foreach (array_keys($array) as $zipCode) {
if (in_array($zipCode, $listZipCodes)) {
$array[$zipCode] = $newUser;
}
}
$json = json_encode($array);
file_put_contents('list.html', $json);
Again, this is all assuming that list.html looks like this...
{
"80135": "user1",
"80136": "user1",
"80137": "",
"80138": "",
"80202": "user2",
"80203": "user2",
"80204": "",
"80205": "",
"80206": "",
"80207": ""
}
Remember it has to be valid a valid JSON object notation in your list.html in order for PHP to be able to parse it correctly. Your existing example is not going to work in PHP because you're using single quotes instead of double quotes, which is a requirement of the JSON spec. So you have to make sure that part is valid in your list.html file.
Beyond that I highly discourage you to take this approach, because it causes a number of serious problems that can't easily be solved. For example, you can not ensure your data won't be corrupted using this approach as anyone two PHP scripts may attempt to overwrite the file at the same time (no data integrity). Also, you can't easily make this scale without it costing you a lot of unnecessary CPU and memory problems if the list gets large enough. Additionally, you have no way to control who may edit the file directly and thus no way to control data flow to the underlying application code that tries to use that data.
A better solution is to use a database and that way you can both control the data and its user privileges, plus you can provide a front-end for non-programmers to edit/modify/read the data through your front-end, via PHP.

PHP-generarted JSON File Errors

I am currently using a PHP script to create a cache of JSON files. We have a PHP file on our server that queries a very large database, and returns result sets in JSON format (so we can use it on the site in jQuery and other frameworks).
The script for presenting the raw JSON from our database works great, and I made a simple cache building script that also works to a degree. However, we have noticed some odd things happening with the resulting cache file.
PHP seems to be adding slashes to the quote marks, as well as adding superfluous " to the beginning and end of the JSON.
Here is a sample of the JSON we're passing in (note that it's not complete):
[
{
"id":1580,
"name":"Fydell House",
"address1":"South Square",
"address2":null,
"towncity":"Boston",
"county":"Lincolnshire",
"postcode":"PE21 6HU",
"addressVerbose":"South Square
Boston
Lincolnshire
PE21 6HU
",
"addressVerboseLinked":"",
"longitude":-0.022778,
"latitude":52.975806,
"londonBorough":null,
"telno":"01205 351 520",
"faxno":null,
"email":null,
"webaddress":null,
"mainimg":null,
"venueType":"Historic Building",
"description":null,
"excerpt":" ",
"images":null,
"creationDate":943920000,
"londonfeatured":false,
"unusual":false,
"featured":false,
"active":true,
"trial":false,
"modifiedDate":1234709308,
"hits":"1579",
"allowReviews":false,
"amenities":null,
"imagealt":"Lincolnshire wedding reception venue in Boston, Fydell House",
"imagetitle":"Lincolnshire wedding venues in Boston",
"car_directions":null,
"pub_directions":null,
"additional_info":null,
"listedBy":0,
"listedByName":null,
"region":null
}
]
And the PHP code that outputs the JSON file and stores it on our server:
// Function to output the contents from the live data, and create a cache file:
function create_cache_file($url, $filename)
{
$url = str_replace(' ', '%20', $url);
$json_string = file_get_contents($url);
$file = fopen($filename, 'w');
// If there is a problem creating the file:
if(!$file)
{
die('error creating the file!');
}
else
{
fwrite($file, json_encode($json_string));
fclose($file);
echo $json_string;
}
}
And this is what the file looks like after it's been processed with PHP and stored on our server:
"[{\"id\":437,\"name\":\"Lanteglos Country House Hotel\",\"address1\":\"Lanteglos-by-Camelford\",\"address2\":null,\"towncity\":\"Camelford\",\"county\":\"Cornwall\",\"postcode\":\"PL32 9RF\",\"addressVerbose\":\"Lanteglos-by-Camelford<br \\\/>Camelford<br \\\/>Cornwall<br \\\/>PL32 9RF<br \\\/>\",\"addressVerboseLinked\":\"\",\"longitude\":-4.695491,\"latitude\":50.612462,\"londonBorough\":null,\"telno\":\"01840 213 551\",\"faxno\":null,\"email\":null,\"webaddress\":null,\"mainimg\":null,\"venueType\":\"Hotel\",\"description\":null,\"excerpt\":\" \",\"images\":null,\"creationDate\":943920000,\"londonfeatured\":false,\"unusual\":false,\"featured\":false,\"active\":true,\"trial\":false,\"modifiedDate\":1234662248,\"hits\":\"1145\",\"allowReviews\":false,\"amenities\":null,\"imagealt\":\"Cornwall wedding reception venue in Camelford, Lanteglos Country House Hotel\",\"imagetitle\":\"Cornwall wedding venues in Camelford\",\"car_directions\":null,\"pub_directions\":null,\"additional_info\":null,\"listedBy\":0,\"listedByName\":null,\"region\":null},{\"id\":438,\"name\":\"Rosehill Public House\",\"address1\":\"Little Petherick\",\"address2\":null,\"towncity\":\"Wadebridge\",\"county\":\"Cornwall\",\"postcode\":\"PL27 7QT\",\"addressVerbose\":\"Little Petherick<br \\\/>Wadebridge<br \\\/>Cornwall<br \\\/>PL27 7QT<br \\\/>\",\"addressVerboseLinked\":\"\",\"longitude\":-4.94093,\"latitude\":50.51259,\"londonBorough\":null,\"telno\":\"01841 540 777\",\"faxno\":null,\"email\":null,\"webaddress\":null,\"mainimg\":null,\"venueType\":\"Inn \\\/ Pub\",\"description\":null,\"excerpt\":\" \",\"images\":null,\"creationDate\":943920000,\"londonfeatured\":false,\"unusual\":false,\"featured\":false,\"active\":true,\"trial\":false,\"modifiedDate\":1234752874,\"hits\":\"818\",\"allowReviews\":false,\"amenities\":null,\"imagealt\":\"Cornwall wedding reception venue in Wadebridge, Rosehill Public House\",\"imagetitle\":\"Cornwall wedding venues in Wadebridge\",\"car_directions\":null,\"pub_directions\":null,\"additional_info\":null,\"listedBy\":0,\"listedByName\":null,\"region\":null}]"
This is causing some serious problems elsewhere on the site when we try to decode the JSON. While we can use stripslashes to remove the slashes, some of the other areas are also causing parse errors (that weren't present using the raw data served up by the first PHP file).
Can anyone suggest why PHP is adding slashes and erroneous quote marks around the string? Ideally, we would like a work-around at the point of creating the JSON file on the server, not reading it from it...
I take it that file_get_contents($url) returns you a JSON encoded file? Then your problem is that you're JSON encoding it again. "[{\"id\":437,\"nam... is the proper JSON encoded representation of the string [{"id":1580,"nam....
If you json_decoded it when reading from the cache file, you'd get the original JSON string back. Or just don't json_encode it.

Categories