I have an application where information from the database is sent back as a JSON response.
Tailoring the jQuery side to handle each and every response seems like a lot of effort for little adaptability.
In what ways could the JSON format could be standardized ? Additionaly, is there a way to "slot in" a handler in jQuery ?
I've been thinking along the lines of something like this:
{
"replyCode": "OK"/"Error",
"replyMessage": "Operation successful"/"Could not connect",
"returnData": ... // Entities go here
}
Standardizing the JSON response is something that needs to be customized for each application; only you have the necessary data to decide exactly what actions should be supported and how they would be communicated over JSON.
As an example, in the past I have used both a "response sniffer" logic (where the handler checks for specific properties in the response and processes each one that exists in a specific manner) and a "command list" logic (where the response always contains an array of objects that describe specific actions that must be taken and the handler executes them) in this situation.
I don't believe that a reply code and message is necessary in most situations as the HTTP response header can communicate this information effectively.
Whatever you decide to do, .ajaxComplete (and its siblings .ajaxSuccess and .ajaxError) can be used to install global response handlers on the client side that run on completion of every request.
First, you should really take a look at the video RESTful API Design from the apigee guys. It contains a ton of good advice for RESTful APIs. Brian Mulloy gives also feedback on how responses should look like.
Next, you should take a look at some libs in php for developing RESTful APIs. Some of these gives you a solid way of how to return responses.
https://github.com/Respect/Rest
https://github.com/MArcJ/PHPRestService
https://github.com/kla/php-activerecord
or more https://github.com/search?q=php%20rest
With this you should good to go to build well RESTful APIs.
Why not have a central function that does the final echoing of the JSON as the response.
function returnJSON($code,$data=array()){
echo json_encode(
array(
'replyCode'=>$code,
'replyMessage'=>getReturnMessageByCode($code),
'returnData'=>$data
)
);
}
Now at the end of every AJAX call you make to retrieve this data, your PHP code would do something like this -
$data = fetchData();
if ($data){
returnJSON('OK',$data);
}else{
returnJSON('FAIL');
}
exit();
Standardizing your responses is a great idea and is also your responsibility. Unless your framework has other options its up to you to make your code as robust as possible.
Related
I'm a bit confused about how errors are handled in Wordpress's REST API. In their examples, they suggest using WP_Error to return errors, but WP_REST_Response has the HTTP status code as a second parameter, which makes it shorter and somewhat cleaner to my taste.
So I'm comparing this way of returning an error:
return new WP_REST_Response(array('error' => 'Error message.'), 400);
With this one:
return new WP_Error('rest_custom_error', 'Error message.', array('status' => 400));
With the first option, I can have just the error text in my response and it's enough for me. So the response would look like so:
{"error":"Error message."}
With the second one it's more detailed:
{"code":"rest_custom_error","message":"Error message.","data":{"status":403}}
But I also need to specify the error code (first parameter), which doesn't give any advantage to my front-end implementation. Other than the syntax, I'm curious about differences in performance, security and future-proof factors.
So is there any reason to prefer one over the other than personal preferences?
I do as follows:
WP_REST_Response // Used when endpoint code runs just fine but needs to
// tell the client about some other downstream error (e.g. 4xx)
WP_Error // Used when endpoint code has an issue and needs to tell you
// it didn't compute or couldn't find resources etc (e.g. 5xx)
As far as I can tell, WordPress changes the status codes of the responses in unpredictable ways. This is dumb. For instance, if you create a WP_REST_RESPONSE with status 400, it actually sends it as status 200 with "status:400" as data in the body.
What I do:
Just use PHP response functions:
http_response_code(400);
exit;
If you tell me I'm wrong, please explain the benefit of using these two function wrappers. I see the benefit if you work for Automattic and are creating regressions in core itself. If you're a plugin or theme dev, [and you're assuming core works] these functions should be avoided as having no use.
I have recently been asked to create an API that can process data using PHP. I am not that accustomed to PHP so I am not quite sure how to proceed.
Basically what I would like to achieve is create an API that processes a form post that the user can call like this:
<form METHOD="POST" ACTION="https://MyURL/index.php" id=aForm name=aForm>
<input type="hidden" id="Lite_Merchant_ApplicationID" name="Lite_Merchant_ApplicationID" value="Your Application Id">
(various other fields to be processed)
</form>
I might be wrong in calling this an API, because it's supposed to handle a form post. But I need to compile documentation for users to be able to integrate with our system and post the form to our URL which will then process the info in the form.
Are there any good tutorials that I can have a look at? I am not sure if the ones I am looking at are applicable as they mention nothing about using a form to call the API? e.g.
https://docs.phalconphp.com/en/latest/reference/tutorial-rest.html
and
http://coreymaynard.com/blog/creating-a-restful-api-with-php/
Or do I just process the form as normal in PHP and accesss the values using:
$_POST["name"];
If that is the case will users be able to call the API using the language of their choice?
An additional question I have would be if there is anything I would need to look at or consider due to the fact that it will be "https"?
Thanks in advance and my apologies if this is not very specific, any advise/pointers will be appreciated.
Additional info:
The system needs to be able to perform redirects and login credentials will be sent within the hidden form inputs
Your question is a little wide ranging, and you may be using words in a way that isn't consistent my understanding.
An API typically is more than a single method, whereas handling a form POST event is just - well, a form handler. The difference is more than semantic - for an API, you probably need to consider versioning (how do you upgrade your API without breaking client applications), abstraction (how can you make your API easy to use), documentation, and security (how can you ensure that only authorised users/applications consume your API?). An API often has more than one user, and often needs to support the scalability requirements of the client applications.
REST is a great way to design an API - it's easy to understand for clients, and lots of smart people have solved problems like authentication/authorisation, versioning and abstraction.
It's important to note that REST uses existing HTTP concepts, so a RESTful API would expose POST requests to create new entities. That POST request can be called from a web page with a <form> element, or from a REST client.
If you write a RESTful API, clients can be written in any language that supports HTTP.
There are a bunch of frameworks which make building RESTful web APIs easier in PHP. I haven't used any, so can't make a recommendation.
If, however, all you have to do is handle a POST request, from a web page that won't change - well, I'd not build a RESTful API, I'd just write a PHP "POST" handler. In this case, the client can be anything that understands your POST parameters (in practice, pretty much any application that can make an HTTP request).
However, the difference between "POST Handler" and "API" in my view is that when you create an API, you make certain promises that your clients depend on. "I won't change the field names without telling you". "I won't change the location without telling you". "You can depend on what my documentation says". When you create a POST handler, you only promise the maker of the HTML form that it works, and that you will tell that team of any changes.
The only challenge with HTTPS is that you must make sure that the calling application can handle it, and that the keys work.
Just process the form as normal in PHP and accesss the values using:
$_POST["name"];
The API user just has to send a POST request, by html form, AJAX, or whatever.
You should add a field for the response format html, xml, json, then use that to format the response.
Check below links (restful services)... Its very simple and meets your requirement.
http://rest.elkstein.org/2008/02/what-is-rest.html
http://www.9lessons.info/2012/05/create-restful-services-api-in-php.html
Going along with Neville K's answer here is an example of how my company handles RESTful api calls.
First we have a php file that handles the calls with a switch statement. Routing the different actions to said functions and classes.
/* Class file that is called on this page */
include_once "$_SERVER[DOCUMENT_ROOT]/classes/class.myclass.php";
/**
* This function makes it simpler to stop it from working for debugging purposes.
* All we have to do is comment out the one line of code apiCall($_REQUEST);
* You could have this outside of the function and it would work just as well.
* #param type $REQUEST
*/
function apiCall($REQUEST) {
$con = new MyClass();
switch ($REQUEST['action']) {
case 'getList':
/* Setting the content type to json means that the developer can
* expect a response in the form of parseable json.
*/
header('Content-Type: application/json');
echo json_encode($con->getList($REQUEST));
case 'setValue':
header('Content-Type: application/json');
echo json_encode($con->setValue($REQUEST));
case 'login':
if ($con->login($REQUEST)) {
header('Location: /index.php');
} else {
header('Content-Type: /login.php?status=Failed+Login');
}
default:
header('Content-Type: application/json');
/* If an invalid action was sent in, then this error message will be sent
* back to the user
*/
echo json_encode(['status' => 'Invalid API Call']);
}
}
/* Using $_REQUEST allows developers to access the api via GET or POST */
apiCall($_REQUEST);
Then we handle all the logic in the different classes we called.
class MyClass {
public function getList($REQUEST) {
$id = $REQUEST['id'];
/* code */
return ['status' => 'ok', 'results' => $array];
}
public function setList($REQUEST) {
/* code */
return ['status' => 'ok'];
}
public function login($REQUEST) {
/* code */
$_SESSION['user_id'] = $user_id;
return $login_successful;
}
}
Using JSON is good for applications that send information via AJAX calls. Using the header('Location:') are good for form submissions without ajax.
You can then use JavaScript ajax calls or for submissions based on how you handle the submission of data.
Example of using jQuery.getJSON
$.getJSON('/switch.php', $.param({id: id, action: 'getList'}), function (json) {
if (json) {
/*code*/
}
});
Then you would pass a hidden input with action in it to the switch page for regular form submissions.
<form action="/switch.php" method="post">
<!--hidden input named action to direct which switch to use-->
<input name="action" value="login" type="hidden"/>
<input name="username"/>
<input name="password" type="password"/>
<input type="submit"/>
</form>
These examples are for html/JavaScript web applications. If you are using JAVA, Python, .NET, or some other language, it would be as simple as using the REST API and parsing out the JSON to figure out how to handle your application logic.
You can even run a php to php api call using file_get_contents or curl.
$data = [
'action' => 'setValue',
'information' => 'More'
];
$json = json_decode(file_get_contents('/switch.php?' . http_build_query($data)),true);
if(!empty($json)){
/*code*/
}
You could create a seperate page for each call and not have to worry about passing in an action to every request. But then your filetree starts to look like this.
/api/loginSubmit.php
/api/login.php
/api/getListFromId.php
/api/getList.php
/api/setValues.php
/api/getValues.php
It gets really tedious to traverse all these files to figure out where the problem is.
I created API Framework, its very light weight, simple, fast.
Github
Clickme
OR
Link : https://github.com/mackraja/mackApi
I used the code from http://angularjs.org/ (Wire up a Backend)
Here in project.js
angular.module('project', ['firebase']).
value('fbURL', 'https://angularjs-projects.firebaseio.com/').
factory('Projects', function(angularFireCollection, fbURL) {
return angularFireCollection(fbURL);
}).
config(function($routeProvider) {
I used this code in my web page. Instead of https://angularjs-projects.firebaseio.com/ url i want to use my url i.e http://test.com/test.php. But it didn't work.
Also i want to know in my php file in which format the out put should be?
Do you need to echo the content in php file or use the return command? Please give suggestion. I have searched a lot. I couldn't find the solution.
I think in firebase url https://angularjs-projects.firebaseio.com/ they are returning the response from their back-end service. That is why it didn't worked for you even if you changed the URL.
And answer to your second question;
If you make a call to your back-end service its better to have a json response style from your PHP and you don't have to use any return command for that. Instead you should echo your contents.
For example in your PHP file if you are getting the results as an array you can give back the response to the angular application as;
echo json_encode($result_array);
Hope it helps.
I think you should separate backend and frontend and treat them as two separated application. Both apps should communicate with each other by sending ajax request (front) and respone data in json format (backend). In my opinion it's the best way to handle this.
I'm writing my first web service, and I have a problem related to JSON data passing. I have my web service divided in two files: controller.php, which contains the service handler, and service.php, which contains the classes and methods to be served on request.
This is the acquisition fragment from controller.php:
public function atender() {
// pre-procesamos la peticiĆ³n
if (!empty($_POST)) {
if (!empty($_POST["class"]) && !empty($_POST["action"]) && !empty($_POST["function"])) {
$clase = ucwords($_POST["class"]);
$metodo = "{$_POST["action"]}{$this->obtenerMetodo($_POST["function"])}";
$id = (!empty($_POST["datos"]) ? stripslashes($_POST["datos"]) : null);
I can attend requests on both GET and POST mode (I use GET for methods not requiring authentication, like getCategories, getCategoryById, getProducts and getProductById. These are methods to get the dish categories and dishes in a sushi restaurant.)
For any of the GET requests, everything works like expected. My problem comes when I handle POST requests. I need to get all URL parameters in JSON, as this is to serve an iOS app, and JSON is the way we handle data to/from.
This is the processing fragment from service.php:
public function putUser($datos) {
if (!empty($datos)) {
$usuario = json_decode($datos);
$this->log .= implode("/", $usuario) . "\r\n";
In this case, $datos is the JSON-encoded data from the request. It's received as $id in controller.php (the code above). As it's my first web service, it's very probable I'm doing something really bad here, but I'm a bit blinded.
I've tried different variations of the service handling code. Using json_decode($datos, true) doesn't work either. I get
'Unexpected token <' as a response and, in raw form (using the advanced REST client from Google Chrome) it says: ''Warning: implode() [<a href='function.implode'>function.implode</a>]: Invalid arguments passed in /home/refine/public_html/sushigo/palma/service.php on line 344'.
I know SOAP is, usually, a better alternative to writing custom code like this but, for now, I need to stick with this code and implement a better alternative for my next project. Could you tell me what am I doing wrong?
The error message says, basically, that it is NOT a valid JSON - and such error messages are usually right.
Your error is somewhere in the sending / receiving code. Probably you send the JSON in one form and try to access it in some other way. Since I have no way of looking at the requests sent from the phone, I would guess that:
you send the data as application/json and try to receive it as an url encoded form. If you don't understand the difference, here's your problem.
you use stripslashes on the JSON data, which is wrong. UNLESS you have magic_quotes turned on, which would also be wrong (that is: both magic_quotes and stripslashes have to go).
I'm looking for a PHP library that allows me to scrap webpages and takes care about all the cookies and prefilling the forms with the default values, that's what annoys me the most.
I'm tired of having to match every single input element with xpath and I would love if something better existed. I've come across phpQuery but the manual isn't much clear and I can't find out how to make POST requests.
Can someone help me? Thanks.
#Jonathan Fingland:
In the example provided by the manual for browserGet() we have:
require_once('phpQuery/phpQuery.php');
phpQuery::browserGet('http://google.com/', 'success1');
function success1($browser)
{
$browser->WebBrowser('success2')
->find('input[name=q]')->val('search phrase')
->parents('form')
->submit();
}
function success2($browser)
{
echo $browser;
}
I suppose all the other fields are scrapped and send back in the GET request, I want to do the same with the phpQuery::browserPost() method but I don't know how to do it. The form I'm trying to scrape has a input token and I would love if phpQuery could be smart enough to scrape the token and just let me change the other fields (in this case username and password), submiting via POST everything.
PS: Rest assured, this is not going to be used for spamming.
See http://code.google.com/p/phpquery/wiki/Ajax and in particular:
phpQuery::post($url, $data, $callback, $type)
and
# data Object, String which defines the data parameter as being either an Object or a String. POST requests should be possible using query string format, e.g.:
$data = "username=Jon&password=123456";
$url = "http://www.mysite.com/login.php";
phpQuery::post($url, $data, $callback, $type)
as phpQuery is a jQuery port the method signature is the same (the docs link directly to the jquery site -- http://docs.jquery.com/Ajax/jQuery.post)
Edit
Two things:
There is also a phpQuery::browserPost function which might meet your needs better.
However, also note that the success2 callback is only called on the submit() or click() methods so you can fill in all of the form fields prior to that.
e.g.
require_once('phpQuery/phpQuery.php');
phpQuery::browserGet('http://www.mysite.com/login.php', 'success1');
function success1($browser) {
$handle = $browser
->WebBrowser('success2');
$handle
->find('input[name=username]')
->val('Jon');
$handle
->find('input[name=password]')
->val('123456');
->parents('form')
->submit();
}
function success2($browser) {
print $browser;
}
(Note that this has not been tested, but should work)
I've used SimpleTest's ScriptableBrowser for such stuff in the past. It's part of the SimpleTest testing framework, but you can use it stand-alone.
I would use a dedicated library for parsing HTML files and a dedicated library for processing HTTP requests. Using the same library for both seems like a bad idea, IMO.
For processing HTTP requests, check out eg. Httpful, Unirest, Requests or Guzzle. Guzzle is especially popular these days, but in the end, whichever library works best for you is still a matter of personal taste.
For parsing HTML files I would recommend a library that I wrote myself : DOM-Query. It allows you to (1) load an HTML file and then (2) select or change parts of your HTML pretty much the same way you'd do it if you'd be using jQuery in a frontend app.