I am working on a project where I use a lot of http requests. Most of the time the server will respond as a json with either:
{"error": "Request invalid"}
or
{"success": "Request successful"}
The server side page that returns the response looks like this:
<?php
header('Content-type: application/json');
$data = [];
if (isset($_POST['action']) {
if ($_POST['action'] == 'function_one') {
/* Arbitary Function... */
$data['success'] = 'This works...';
} elseif ($_POST['action'] == 'function_two') {
/* Arbitary Function... */
$data['error'] = 'Example error';
} elseif ($_POST['action'] == 'function_that_is_not_working') {
$data['success'] = 'This unexpectedly does not interpret correctly...';
}
}
$post_data = json_encode($data);
print_r($post_data);
?>
The javascript file does the http request and handles the data similar to:
if (xml_http.readyState == 4 && xml_http.status == 200) {
try {
console.log(JSON.parse(xml_http.responseText));
return JSON.parse(xml_http.responseText);
} catch (e) {
console.log(xml_http.responseText);
return xml_http.responseText;
}
}
So this all works absolutely fine, I have multiple functions all using the same code without an issue. The problem I have is that I have one specific action that does a request, if I set $data['success'] it does not interperet as a JSON object, but a string. If I set the key as anything else, it works fine.
I have tried commenting out the function in case there is some unexpected echo's etc.
The JSON string is a valid JSON string, it's just this one action when using the success key that the JSON.parse doesn't see it as valid JSON so just outputs the string.
Am I missing something obvious? Are there other ways that I could test this?
Edit After a little more playing around I found out there was nothing wrong with the response, nor the JSON.parse.
I had an issue with some of the script after causing an error.
Solution: Always look at the bigger picture, and the subsequent processes.
Related
I have been looking for multiple ways to redirect users to a html page when a certain access code if submitted in a form. I have the form up and is working properly, but I can't get it to redirect to the right page, I have seen 1 other post like this, but with specific user login.
<?php
$_GET["code"] = $accessCode;
if ($accessCode === "code123") {
header("Location: http://www.example.com/code_123.html");
} else if ($_GET["code"] === "test") {
header("Location: http://www.example.com/code_test.html");
} else {
header("Location: http://www.example.com/unknown_code.html");
}
?>
I even tried using the redirect option (cPanel)
Whenever I use the code code123 or test, they redirect me to unknown_code.html
I tried using both if ($accessCode === "code123") and ($_GET["code"] === "test")
You have it backwards.
When you are making an HTTP "GET" Request, PHP will store the "query string parameters" in the global $_GET array.
For example, http://www.yoururl.com?code=code123&mobile=1
In this context, the query string starts with "?" and is delimited by "&", leaving you with key value pairs of:
code = code123
mobile = 1
PHP converts that and stores it in the global $_GET array as such:
$_GET['code'] = "code123"
$_GET['mobile'] = 1
The same thing would happen if you were to do an HTTP POST request, where instead of the query string, the HTTP POST Request "Body" contains the query string, or in some cases, JSON, or XML, etc.
PHP would parse that and you would get as so:
$_POST['code'] = "code123"
$_POST['mobile'] = 1
So for your context, you actually have it backwards.
You want to "assign" $accessCode with the value stored in the $_GET array at index "code"
<?php
$accessCode = $_GET['code'];
if ($accessCode == 'code123') {
header('Location: http://yaddayadda', 301); /* you can change 301 to whatever redirect code that is most appropriate. this is good for information search engines on the appropriate behavior. do a google search for http redirect codes to understand. 301 is permanent redirect. 302 is temporary. etc.*/
exit;
} elseif ($accessCode == 'code234') {
header('Location: http://');
exit;
}
else {
echo 'No valid access code.';
exit;
}
You need to assign the value of $_GET['code'] to $accessCode.
<?php
$accessCode = $_GET['code'];
switch ($accessCode) {
case 'code123':
header("Location: http://www.example.com/code_123.html");
exit;
case 'test':
header("Location: http://www.example.com/code_test.html");
exit;
default:
header("Location: http://www.example.com/unknown_code.html");
exit;
}
?>
Also, when you are comparing a single variable to several values, use a switch statement.
It's a good idea to follow a redirect header with exit - you're done at that point.
I have my client app sending a json object to server which is in php.
Client side code:
var jacc = JSON.stringify(acc);console.log(acc);
$http.post($rootScope.url+'signup.php',jacc)
.then(function(response){console.log(response.data);});
which works perfectly fine.
But at server side
$acc = $_POST["jacc"];
$code = $_POST["code"];//received later
if($acc){
echo 1;//this thing never echoed.
}
elseif ($code && matchCode($code)){
if(addAcc($acc))
echo 1;
}
else echo 0 ." failed";
die();
The output at the console will be always "0 failed". Tried changing the post request to httpbin.org/post which works well. so the problem is with my php script. Also tried a var_dump($_POST) which also returns null value.
Your JavaScript code should be something like :
var params = { jacc : JSON.stringify(acc) };
// or var params = acc; if acc is already an object with the "jacc" property
$http.post($rootScope.url+'signup.php', params)
.then(function(response){
console.log(response.data);
});
Your error is that you try to post a "string" when you need to post an object with key:value.
tiltem saved my day.. thanks to dievardump for help.. Finally i got the issue and able to fix it. When using JSON content-type the $_POST array will not populate. All i had to do to fix it was
$rest_json = file_get_contents("php://input");
$_POST = json_decode($rest_json, true);
I am sending a simple array from my PHP file,
//example.php
if(0){
return json_encode(['status'=>false, 'message'=>'Please enter a username']);
}
and in my ajax.js I have everything working, including the XHR object, and event handlers. All is find, except this line.
// ...
var x = JSON.parse(xmlhttp.responseText);
console.log(x);
// ...
But, I am getting the following error.
SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data
I don't understand this. All the code is correct. Before using JSON, I used to pass from values from PHP using echo 'ok' and just do if(xmlhttp.responseText) == 'ok and it worked fine, but not with json
Two problems:
you use return which does not print anything to the output wheras echo actually prints text. Try using:
if(0) will always fail, so you will never print anything. You should use if(1) as trivial test. It is possible that you're PHP code can fail, but in that case you better also return an JSON formatted error message.
Something like:
if(test) { //test means you can do the action
//do action
echo json_encode(['return' => 'ok','result' => 'foobar']);
} else {
echo json_encode(['return' => 'error']);
}
I'm trying to learn OOP in PHP but I'm having some troubles at the moment. Whenever method is executed i don't know what value should i return to be able to handle it with jQuery in both cases - true and false. For example, in Pick_data() if false i want to get value like: "Fill in all fields" and most important, to be able to display it for user using jQuery or Ajax. I will leave code down below. Places commented ,,//I NEED HELP HERE" is my problem. I'm not asking you to write whole code and just need reference to information how can i deal with it. I would appreciate that because i'm completely lost. I will leave code down below(it's working fine expect my problem). Thanks!
<?php
require ('db_connect.php');
Class Registration {
public $username, $password;
public function Pick_data() {
if (isset ($_POST['username']) && isset ($_POST['password'])) {
$this->username = trim($_POST['username']);
$this->password = trim($_POST['password']);
} //end of if isset
if (!empty($this->username) && !empty($this->password) ) {
return true;//NEED HELP HERE
} //end of is empty
else //NEED HELP HERE
} //end of Pick_data
public function Username_equivalent_check() {
$find_username_equivalent = mysql_query("SELECT * FROM websiteusers WHERE Username='".$this->username."'");
if (mysql_num_rows($find_username_equivalent) == 0) {
return true;//NEED HELP HERE
} //end of (mysql_num_rows)
else //NEED HELP HERE
} //end of Username_equivalent_check
public function Input_data() {
$input_user = mysql_query("INSERT INTO websiteusers (Username, Password)
VALUES ('$this->username','$this->password')");
if ($input_user) {
return true; //NEED HELP HERE
}//end of inputing new user data
else //NEED HELP HERE
} //end of input_data
} //end of class
$var = new Registration;
$var->Pick_data();
$var->Username_equivalent_check();
$var->Input_data(); ?>
There are several ways to do this. Here are a few suggestions:
When an error occurs, you do not just want to return a true/false result, but you want to return a text message. That text message can then be displayed (or can be passed to jQuery or whatever). Since you are a beginner, I would say just change your functions to return a string value (the actual error message text) instead of returning just false in case of an error. Something like this:
public function Pick_data() {
if (isset($_POST['username'])) $this->username = trim($_POST['username']);
if (empty($this->username)) return 'User name must be specified.';
if (isset($_POST['password'])) $this->password = trim($_POST['password']);
if (empty($this->password)) return 'Password must be specified.';
return true;
}
As you can see above, your Pick_data function will return with an error message (a string value) if either one of the required fields were empty. It will only return true if there were no errors.
Then when you call this function, you must check its return value:
$var = new Registration;
$result = $var->Pick_data();
if ($result !== true) {
echo 'Error: ' . $result; // This gets executed when Pick_data returned an error message
} else {
// This gets executed when Pick_data returned true, so only here you should continue:
$result = $var->Username_equivalent_check();
// you must check here the $result variable again as it now contains the return value of your Username_equivalent_check function
// ...and so on
}
If you must do a lot of checks one after the other, you'll end up with a lot of nested if / else statements. Which is not so great. But as a beginner programmer you need to learn that you should almost always need to check the return value of each(!) function you call!
A more advanced solution is to use a try / catch block, something like this:
try {
$var = new Registration;
$var->Pick_data();
$var->Username_equivalent_check();
$var->Input_data();
} catch(Exception $e) {
// Get the error message:
$error_msg = $e->getMessage();
// and print it out
echo 'Error: ' . $error_msg;
}
To make the above try / catch block work, you must(!) also change your functions to throw an exception (error) when something goes wrong, something like this:
public function Pick_data() {
if (isset($_POST['username'])) $this->username = trim($_POST['username']);
if (empty($this->username)) throw new Exception('User name must be specified.');
if (isset($_POST['password'])) $this->password = trim($_POST['password']);
if (empty($this->password)) throw new Exception('Password must be specified.');
}
Using try / catch blocks are much more elegant because you do not end up with a lot of nested if / else statements. Note: when an exception is thrown while the program is running within a try / catch block the program execution stops there immediately and the catch block gets executed.
I think now you have a better idea on how to handle error events in PHP.
If you want to display the error message in the user's web browser with jQuery then you must pass the error message from the server which runs your PHP code to the browser which can only run javascript (jQuery is written in javascript). Nowadays forms are being submitted from the browser to the server via an Ajax call. It looks something like this: First the form gets being displayed in the browser (PHP sends the page containing the form to the browser when the user visits your page). The user fills the form and when hitting the Submit button javascript takes over and sends the form data to the server. This way the user is still on the same page, in other words the page does not get reloaded. When your server receives the Ajax request from the javascript code running in the browser, it does the actual processing, in your example checks the values of the form fields, etc. Finally the server sends the results back usually as a JSON object to the browser, to the calling javascript program. Then the results can be displayed by the javascript code running in the user's browser. So for what you want to do you need to learn both PHP and javascript programming and you need to learn using jQuery and the JSON format as well.
I'm using AJAX to make a call to a PHP script. The only thing I need to parse from the response is a random ID generated by the script. The problem is that the PHP script throws a number of errors. The errors are actually fine and don't get in the way of the program functionality. The only issue is that when I run
$.parseJSON(response)
I get:
Uncaught SyntaxError: Unexpected token <
Since the PHP response starts with an error:
<br />
<b>Warning</b>:
I'm wondering how to change the PHP or JS such that it can parse out the ID despite the errors.
PHP:
$returnData = array();
$returnData['id'] = $pdfID;
echo json_encode($returnData);
...
JS:
function returnReport(response) {
var parsedResponse = $.parseJSON(response);
console.log(parsedResponse);
pdfID = parsedResponse['id'];
I know that the warnings should be resolved, but the warnings are not functionality critical for now and more importantly
1) Even if these warnings are resolved new ones may come up down the line and the JSON should still be properly parsed and
2) In addition to the warnings there are 'notices' that cause the same issue.
Why not deal with and eliminate the warning so that the result from the server is actually JSON?
There are several ways this could be solved (any one of which would work):
1. Fix your warnings. : PHP is saying something for a reason.
2. Turn off error reporting & error display:
At the top of your file place the following
error_reporting(false);
ini_set('display_errors', false);<br/>
3. Use the output buffer:
At the top of your file place
ob_start();
When you have your data array and your ready to echo to browser clear the buffer of all notices warnings etc.
ob_clean();
echo json_encode($returnData);
ob_flush();
4. Set a custom error handler:
set_error_handler("myCustomErrorHandler");
function myCustomErrorHandler($errno, $errstr, $errfile, $errline){
//handle error via log-to-file etc.
return true; //Don't execute PHP internal error handler
}
5. Optionally in JavaScript:
Sanitse your response to be a JSON array:
function returnReport(response) {
response = response.substring(response.indexOf("{") - 1); //pull out all data before the start of the json array
response = response.substring(0, response.lastIndexOf("}") + 1); //pull out all data after the end of the json array
var parsedResponse = $.parseJSON(response);
console.log(parsedResponse);
pdfID = parsedResponse['id'];
}
Like everybody else has said, you SHOULD really fix your errors and handle them accordingly.
This is something more to have under circumstances that you will not control and yet want to handle errors accordingly:
<?php
//Change it to 'production' or something like that
//so that you don't send debug data on production
define('ENVIRONMENT', 'testing');
//Set your error handler globally
set_error_handler('handle_error');
function handle_error($errno, $errstr, $errfile, $errline, array $errcontext )
{
//Set your headers to send a different than 200 so you can
//catch it on error on jQuery
header($_SERVER["SERVER_PROTOCOL"].' 500 Internal Server Error');
//Set output as json
header('Content-Type: application/json');
//Create some sort of response object
$response = new stdClass;
$response->message = "Application error details";
//You dont want to give debug details unless you are not on prod
if(ENVIRONMENT == 'testing') {
$severity = get_err_severity($errno);
$response->error_detail = "({$severity}) [{$errfile}#L{$errline}]: {$errstr}";
$response->context_vars = $errcontext;
}
//Return the json encoded error detail and exit script
$json = json_encode($response);
exit($json);
}
function get_err_severity($severity)
{
switch($severity) {
case E_ERROR:
return 'E_ERROR';
case E_WARNING:
return 'E_WARNING';
case E_PARSE:
return 'E_PARSE';
case E_NOTICE:
return 'E_NOTICE';
case E_CORE_ERROR:
return 'E_CORE_ERROR';
case E_CORE_WARNING:
return 'E_CORE_WARNING';
case E_COMPILE_ERROR:
return 'E_COMPILE_ERROR';
case E_COMPILE_WARNING:
return 'E_COMPILE_WARNING';
case E_USER_ERROR:
return 'E_USER_ERROR';
case E_USER_WARNING:
return 'E_USER_WARNING';
case E_USER_NOTICE:
return 'E_USER_NOTICE';
case E_STRICT:
return 'E_STRICT';
case E_RECOVERABLE_ERROR:
return 'E_RECOVERABLE_ERROR';
case E_DEPRECATED:
return 'E_DEPRECATED';
case E_USER_DEPRECATED:
return 'E_USER_DEPRECATED';
}
}
function test_error()
{
$test = array('foo'=>'bar');
$baz = $test['baz'];
echo $baz;
}
test_error();
While this doesn't solve the broader issue of warnings, I used this hack to parse the response:
function returnReport(response) {
var pdfID = parseID(response);
...
}
function parseID(response) {
var responseIndex = response.indexOf('{"id');
var start = responseIndex + 7;
var pdfID = response.slice(start, start + 6);
return pdfID;
}
I know everybody has recommended you fix the errors, I would agree, but if you do not want to then there is another a solution.
If you are getting a number of warnings and expect new warnings could appear, simply disable reporting of warnings and notices:
error_reporting(E_ALL ^ (E_NOTICE | E_WARNING));
If ob is enabled
ob_end_clean();
ob_start();
echo json_encode($returnData);
Or, in top of your file
error_reporting(0);
I am sure that there would be some mistakes in your PHP code due to that error is coming please check few things:
Make sure that there should not be more than one echo or print in your php code for printing response.
jQuery must be included properly.
And check the other php code in your function/page that should not produce any run time errors/warnings because it will also create same problem.
I am saying this because I have tried your code and it working fine for me you can check that also:
PHP File: myContentPage.php
<?php
$returnData = array();
$returnData['id'] = 123;
echo json_encode($returnData);
?>
HTML File:
<!DOCTYPE html>
<html>
<head>
<script type='text/javascript' src='js/jquery.js'></script>
</head>
<body>
<h1>Demo Example</h1>
<script>
function loadResponse() {
var dataString={};
$.ajax({
url:"myContentPage.php",
type: 'POST',
cache:false,
data: dataString,
beforeSend: function() {},
timeout:10000000,
error: function() { },
success: function(response) {
var parsedResponse = $.parseJSON(response);
pdfID = parsedResponse['id'];
console.log(pdfID);
alert(pdfID);
}
});
}
loadResponse();
</script>
</body>
</html>
And for handling the warnings you can do these this:
To skip warning messages, you could use something like:
error_reporting(E_ERROR | E_PARSE);
or simply add the # sign before the each line of php code on that you think warning can come
Happy Coding!!
Script used in Ajax call just must have perfect constrution, shall not thrown any warnings just by convenience, for production you should have erros disabled, so fix it into development, edit the question with the warning that's phps givin to we help you with directly on the point.
1st alternative:
Solve the problem causing the warning. A good PHP system should never show a PHP Notice, Warning or Error. This may expose some critical information.
2nd alternative:
Just disable error reporting by setting
error_reporting(0);
This will work, but will hide even to you any errors.
3rd alternative:
Set a error handler function that treat the error and show a JSON friendly error message that does not cause any trouble.
Also I recommend you to log this exceptions. It will allow you to debug any system trouble.
My recomendation?
Use 1st and 3rd alternatives together, and be HAPPY!
You can use Try..Catch construct in the javascript function code as shown below.
function returnReport(response) {
try
{
var parsedResponse = $.parseJSON(response);
console.log(parsedResponse);
pdfID = parsedResponse['id'];
}
catch(err)
{
//Do something with the err
}
}
This will work even if your php code generates debug info in response.
If you want to see the error in JavaScript, you should handle the error on PHP with a "try catch" and the "catch" to do something like "echo json_enconde ($ error);" on this way you can parse from JavaScript.
Example:
try{
$returnData = array();
$returnData['id'] = $pdfID;
echo json_encode($returnData);
}catch (Exception $e) {
echo json_encode($e);
}
I hope this helps :)!