I am using jQuerydatables and server side scripting with php and mysql. I have modified the script found here:
https://legacy.datatables.net/examples/data_sources/server_side.html
and I have included an if-else which is wrapped around the entire script.
The goal is to only allow results to be returned if the user posted a valid token from my db.
So I have that bit set up. But I am unsure how to handle the error message to the user.
Right now, when a user passes in an invalid token, my website (using datatables) throws up the error invalid JSON response.
I assume this because it is expecting iTotalRecords etc in the JSON returned.
I am wondering if anyone knows how to achieve this. I haven't been able to find any examples.
Algorithm:
if (postedToken exists in db){
return datatables JSON
}
else{
return json in such a way that I can provide an alert to the user that their session has expired
}
and datatable initialisation:
"sAjaxSource": "mydatatablescript.php?token=<?php echo $token;?>
EDIT:
I was returning a valid JSON but I was missing a few parameters which must be required i.e. 'iTotalRecords' => 0, 'iTotalDisplayRecords' => 0, 'aaData' => [], 'sEcho' => 0.
Now I am not getting the error message described in the question. I see there is a "fnDrawCallback" parameter I can include in the datatable initialisation. I suspect here I can check my message param and alert if necessary but I just don't know how to access the JSON from within that function?
As you have seen already, you need to return valid json in any case if your client-side is expecting that.
You could do that using for example something like:
if (postedToken exists in db){
return datatables JSON
}
else{
return json_encode(array('success': false, 'message': 'session has expired'));
}
You should probably add these same keys / parameters when the call is successful as well so that you can easily check in your javascript function what the result of the operation is.
Related
I am making an API for mobile APP based on PHP backend. I have cases where i return an array list and if there is no results i return a message
where results are found:
{"status":"success",
"data":[{"users_details":[{"user_id":1,"parent_id":2}]}],
"token":"success"}
where are no results found:
{"status":"error","data":"no user found","token":"success"}
Is this a good approach, If no what should it be?
i prefer to utilise the http response code so for data not found you can return 204 and when you find matches return 200 and the list of the users
It's a good idea to return a message, that no user data is found, but it would be perfect, if along with the response, a correct response code would be returned. In this case it would be 404 - not found. See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes for more info
It depends on how you process it, I would simply do this.
{"status":"error","msg":"no user found","token":"success"}
Because you don't need to get confused with user data and error message.
consider like if the status is an error then it should have detailed error message in msg key
so you can eliminate the response before the going into actual user data parsing functions. like
if($response['status'] === 'error')
return "Error Message: " . $status['msg'];
I personally stand with empty array. It's normal situation, when API search return no results (and empty array is naturally no results answer). It's okay status for me.
The request may me malformed or there may be problems with database, this is really the case to return status: error.
More to say, when we return in first case array with data and in second string, it is bad approach anyway, cause we have to handle different types of data, it's anti-pattern as I might say. The type should always be the same.
We first check that status is okay or error (no connection, bad connection, bad request etc), then we either check data (empty array = no results) or check error message
{"status": "error", "message": "connection error"}
{"status": "success", "data": []}
{"status": "error", "data": ["First result", "Second result"]}
It doesn't mean that we cannot redirect user to 404 page f.e. if we get such API result, of course. But as for API request, when empty result is normal outcome it shouldn't be treated as error, or we will be mixing real errors with logic, which is obviously bad.
I’ve got an ajax based script that is designed purely to run a php script to authenticate a user. As there is with user authentication, there could be one of two outcomes: either they get authenticated or they don’t.
To signify success or failure back to the page that called it is extremely easy, you just echo ‘success’; or ‘echo ‘failure’` accordingly and have the JS/jQuery script handle it by the response string. (Or at least I think that’s good practise..)
But apart from essentially returning true or false, if it returned false I would also like to give a message back as to why it failed. Did the user exist? Was the password incorrect? Or did the database access go wrong and need to spit out a technical error code. Since we are responding with true or false already, we can’t send back a message alongside with the false statement otherwise it technically isn’t false as there is more data.
Now I have had these ideas, but I feel like there is a better way to do it:
Return an array [true/false, “String to display”] though this seems clunky within the PHP file and also parsing it on the page
Return success when we want to return true, and label anything else as a failure and assume it’s a message for failure
But in all honesty I feel like this whole text response method is bad especially for something like user authentication as it could possibly be spoofed easily(?) so what would the recommended way to achieve something like this?
Thanks in advance!
This is purely opinion based but I think your missing two important concepts when handling communication between two systems such as PHP (server) and Javascript (client).
One, evaluating response codes. If the HTTP response code is 200, it indicates OK, 201 indicates a resource was created (possibly a session), 401 indicates the user is unauthorized. Given this, just by the HTTP response, you should be able to tell if the action succeeded or not.
Two, using JSON or a markup language. You can pass a JSON string to include both the status and the message and parse the JSON string in Javascript.
Example in PHP being:
http_response_code(401);
$response = [
'success' => false,
'message' => 'Password incorrect'
];
echo json_encode($response);
I've been looking around at similar topics on REST APIs but I am still having some confusion in my project, mostly with the PHP side of things.
USPS provides a REST API with functions that can be called via URL like this: https://epfws.usps.gov/ws/resources/epf/login
To make any call successfully, I have been told that a JSON object must be created and passed as a "POST parameter" with the expected values.
This is the JSON object that needs to be passed in this case:
obj=
{
"login":"loginExample",
"pword":"passwordExample"
}
I have also been given a PHP class that is supposed to manage these calls. This is the login function:
public function login ()
{
// Set up the parameters for a login attempt
$jsonData = array(
'login' => $this->loginUser,
'pword' => $this->loginPass,
);
// Make a login request
$jsonResponse = $this->pullResource
('/epf/login', 'POST', $jsonData);
return $jsonResponse;
}
So I have a few questions regarding this:
The document they sent says
"To make the request calls, a JSON object will need to be created and passed as a POST form parameter obj={jsonObject} for security reasons using content-type “application/x-www-form-urlencoded”."
I know that the login function contains the correct input values that USPS' REST API is wanting, but I'm not sure how to pass them as "obj", or how to apply the "content-type".
I have a "constant" defined at the top of my PHP script that looks like this:
const EPF_BASE_URL = 'https://epfws.usps.gov/ws/resources';
And I noticed in the actual functions that this part of the link is left out and they simply reference '/epf/login' as you can see above. Since "$this" contains lots of different values I'm wondering how it supposedly finds EPF_BASE_URL as needed. Is it similar to how 'using' directives work in C#?
What is the easiest way to call this function and display the result? This is my biggest question. Would I use a separate PHP class with an HTML form? I understand the concept of what it should do but I'm completely lost setting up a development environment for it.
I've been trying all of this with MAMP but would love to know if I'm on the right track or not.
That really depends on their API. Hopefully you get a string back that can be decoded to a JSON object (http://au.php.net/manual/en/function.json-decode.php). Some API might give a simple string that says 'SUCCESS' or 'FAIL'. You've got the code, so take a look at what $this->pullResponse() gives you.
If you've been given a PHP class that is supposed to support the API (hopefully from USPS), then it should already take care of putting the data in the form content, and ensuring is it submitted with the appropriate content-type.
A PHP const is more like a C# static string. It is very likely that the library will use the constant to create the end URL (i.e. EPF_BASE_URL . $resource). If you needed to run against a sand box environment, you could change that constant without having to change all the other code.
That's a very big question, because it depends on how you are programming your application. Procedural, MVC, existing frameworks, etc.
At the very least, you would set the loginUser and loginPass on the instantiated object, and call the login method`. You could then inspect the results, assuming the result is a JSON object, or use your favourite debugging method to see the contents.
I'm having a guess as the USPS API class name.
$uspsApi = new UspsApi();
$uspsApi->loginUser = 'username';
$uspsApi->loginPass = 'password';
$result = $uspsApi->login();
echo print_r($result, true);
I have a Windows Desktop Gadget that, for a small number of my users, suddenly stopped working a few months back. Seemed to be that they suddenly didn't like cross-domain requests (even though all servers are on our intranet here). So, I'm rewriting the thing so that it goes to a single backend server that I have a lot of control over... and its Ajax queries to the backend are set to use data Type: jsonp. Meanwhile, the php script that the gadget queries a la Ajax calls a SOAP service, gets the data back, turns it into an array, and then uses json_encode to turn it into a string and add a reference to a callback function on the Gadget / javascript side.
My problem seems to be with json_encode. If the SOAP response includes a single data record, it sends it as an object. If the SOAP response contains multiple records, it's slapping brackets around it, like an array.
Examples:
Single record:
`{
"SmeDetail": {
"SipAddress": "jane.smith#whatever.com",
"SubjectExpert": "Smith,Jane",
"SubjectMatter": "Unix"
}
}`
Multiple records:
`{
"SmeDetail": [
{
"SipAddress": "fred.flintstone#whatever.com",
"SubjectExpert": "Flintstone,Fred",
"SubjectMatter": "Bedrock"
},
{
"SipAddress": "barney.rubble#whatever.com",
"SubjectExpert": "Rubble,Barney",
"SubjectMatter": "Bedrock"
},
{
"SipAddress": "wilma.flintstone#whatever.com",
"SubjectExpert": "Flintsone,Wilma",
"SubjectMatter": "Bedrock"
}
]
}`
In the php script, a typical SOAP call goes like this:
$Service_URL = 'http://server/PROD/OurWcfService/WcfService.svc?wsdl';
$client = new SoapClient($Service_URL);
$res= $client->GetSMEDetails($params)->GetSMEDetailsResult;
and then $res is fed to this routine:
$json_data = json_encode((array)$res);
echo $_GET['callback_name'].'('.$json_data.');';
And that echo is what's fed back as the Ajax response.
I'm not sure where I even read about using this json_encode((array)$res) to do the conversion from the Soap response into an array, then the json encoded string. But I'm wondering if I'm doing something wrong here? I guess I need to make sure that single records are pushed through as an array. And I'd rather fix that the "right way" rather than do some sort of hack on the string.
Any thoughts?
I think the problem occurs cause GetSMEDetailsResult returns not array(singlerecord) but singlerecord itself.
What about checking "is SmeDetail associative"?
hint: How to check if PHP array is associative or sequential?
function isAssoc($arr)
{
return array_keys($arr) !== range(0, count($arr) - 1);
}
if(isAssoc($res['SmeDetail'])) $res['SmeDetail'] = array($res['SmeDetail']);
This solution is ugly but it should work.
Another way is to check "is SipAddress set":
if(isset($res['SmeDetail']['SipAddress'])) $res['SmeDetail'] = array($res['SmeDetail']);
I have been searching the internet and the jqGrid documentation, but I can't find anything about the format of a JSON response to a create, update, delete (CRUD) operation. Surely there should be a JSON message that is returned from PHP to jqGrid to tell it whether the CRUD operation was successfull? What is the format of this message and how would you code the javascript for the jqGrid to respond to that message? I'm not a very good programmer, so complete code answers would be greatly appreciated.
Thanks
You don't need to use a response for create, delete and update.
E.g. if you do an create operation you are calling an "ajax operation" which adds your data into a database.
There are now two possibilites:
Create Operation succeeds
just return nothing, means empty string
(as long as a 200 response is received by jqgrid, everything is fine)
Create Operation failed
just throw an Exception with a modified response header
If jqGrid receives an non 200 response code it shows you an error itself!
try {
// insert something in your db
// ok = true means everything fine
// ok = false means something unpredictable happened
if (!$ok) {
throw new Exception('error');
}
} catch (Exception $e) {
header("Status: 500 Server Error caused by dbinsert jqgrid");
var_dump($e->getMessage());
}
Sorry for the code, but it was the fastest I get out of my brain now :)
I use jqGrid in combination with the Zend Framework and ZF uses 500 Response codes for Exceptions by default (at least my template)
After a successful update/delete/create you have to refetch the whole jqGrid data.
jQuery("#your_jqgrid_id").jqGrid().trigger('reloadGrid');
There is afaik no other mechanism. (Used it last about 6 months ago, maybe that changed)
If you want to implement your own error/success handling, just define your own message in whatever format you want and handle it in the ajax success function callback.
If you need more code and it is not urgent, just drop me a comment.
One additional advice: Don't expect to understand jqGrid immediatly. Take your time, try some things, play with it. It will take some time before you feeling comfortable with it.