How to handle application errors for json api calls using CakePHP? - ajax

I am using CakePHP 2.4.
I want my frontend make api calls to my CakePHP backend using ajax.
Suppose this is to change passwords.
Change password action can throw the following application errors:
old password wrong
new password and confirm new passwords do not match
In my frontend, I have a success callback handler and a error callback handler.
The error callback handler handles all the non 200 request calls such as when I throw NotFoundException or UnAuthorizedAccessException in my action.
The success callback handler handles all the 200 request calls including of course, the above 2 scenarios.
My questions are:
Should I continue to do it this way? Meaning to say, inside all success callback handler, I need to watch out for application success and application error scenarios.
Should I send application errors back with actual HTTP error codes?
if I should do 2, how do I implement this in CakePHP?
Thank you.

Don't use http error codes for system errors like:
old password wrong
new password and confirm new passwords do not match
etc etc...
Now using success handler you can show messages and code flow as:
Create Ajax post or get to submit the form, I am showing you post example
var passwordValue = $('#password').val();
$.post( "/updatePassword", { passwordText: passwordValue })
.done(function(response) {
if(response.status === 'Success'){
// Success msg
// whatever
}else{
// Error msg
// whatever
}
});
json response would like:
{
"status": "Failed/Success",
"message": "old password wrong."
}
Create one function in controller
public function updatePassword() {
$myModel = $this->MyModel->find('first' // YOUR CODE LOGIC);
if($this->request->is('ajax') {
$this->layout=null;
// What else?
echo json_encode($myModel);
exit;
// What else?
}
}
Do something like this, hope it will solve your query!

Related

Vue API Calls and Laravel Middleware

Is it possible to globally set a listener on API calls made with Axios in Vue? The Laravel back-end has middleware set up on each endpoint that will either give the requested data or return a message saying that they need to check their messages. My goal is to capture that message and redirect the user to the page to view their message. I can't think of a way to do this other than setting something on each function that checks for the message and responds accordingly. There are hundreds of functions and that it wouldn't be a clean solution.
Any and all recommendations are welcome!
Using Axios Interceptors you can do something along these lines:
this.$http.interceptors.response.use(response => () {
// Redirect to a new page when you send
// custom header from the server
if (response.headers.hasOwnProperty('my-custom-header')) {
window.location.href = '/another-page';
}
// Or when you get a specific response status code
if (response.status === 402) {
window.location.href = '/another-page';
}
// Or when the response contains some specific data
if (response.data.someKey === 'redirect') {
window.location.href = '/another-page';
}
// ...or whatever you want
});

Datatables 1.10.5 ajax error handler - Getting access to the http status code

I'm using Datatables 1.10.5 and I have the ajax error handler defined. I need to gain access to the actual http status code when the error fires so I can see if my user's session time has expired (HTTP 401) vs if there's something wrong on the backend such as an HTTP 500 error. Right now the techNote is always 7.
How can I get that elusive HTTP status code from the ajax transaction? I tried below, but it does not fire.
$("#example").ajaxError(function(event, jqxhr, request, settings){
alert("Failure HTTP Code:"+jqxhr.status);
});
and
$.fn.dataTable.ext.errMode = 'throw';
$('#example').on('error.dt', function(e, settings, techNote, message) {
console.log( 'An error has been reported by DataTables: ', message);
});
Does not have the information I need, or at least that I cannot find it in any of the passed variables.
I've been able to get access to the status code without overriding global jQuery ajaxError by overriding the more specific to DataTables $.fn.dataTable.ext.errMode with a function:
$.fn.dataTable.ext.errMode = function (settings, tn, msg) {
if (settings && settings.jqXHR && settings.jqXHR.status == 401) {
window.location = window.location.origin + '/login';
return
}
alert(msg) // Alert for all other error types; default DataTables behavior
};
This example shows a redirect to login on 401 status code, however, you could do the same with any other status code.
Last note is you might want to leverage the DataTables statusCode option for status code specific handling but you'll still need to override $.fn.dataTable.ext.errMode if you want to bypass default error handling since it executes before anything you define in statusCode
Handle xhr event. When Ajax error occurs third argument json would be null and fourth argument xhr would contain jQuery XHR object. You can get the status by accessing xhr.status property.
Also see $.fn.dataTable.ext.errMode which could be used to instruct DataTables not to show the alert.

How to prevent server call for empty string in Select2 with remote data?

I noticed that the Select2 widget serving options with remote data was making a call even when I enter just empty spaces. This usually returns me an empty array, but I would like to eliminate this call altogether.
So here is what I did.
The Select2 plugin allows us to define our own AJAX call handler via the transport option.
From the docs :
Select2 uses the transport method defined in ajax.transport to send requests to your API. By default, this transport method is jQuery.ajax but this can be changed
So here is how you can eliminate the unnecessary call altogether.
$('select').select2({
...
ajax: {
transport: function (params, success, failure) {
if (!params.data.q.trim().length) {
return false;
}
var $request = $.ajax(params);
$request.then(success);
$request.fail(failure);
return $request;
}
}
...
})
A more detailed snippet at my blog.
Select2 has a minimumInputLength option which will handle this for you. It will display a notice when the user needs to enter more characters, and then send the request out when enough have been entered.

Send response from action method liferay

I have an actionURL in my jsp from which I am calling a method called "updateDB" in my java file.
whenever I submit the form through an AJAX request using A.io.request , this udpateDB function in my java code is being called, where I am doing some database CRUD operations.
I want to know how can I send some values(either success/failure status of database insertion) back to my jsp from java code to the success callback of my A.io.request ajax call.
You can find below my Ajax request :
Liferay.provide(window,‘submitForm’,
function() {
var A = AUI();
A.io.request(‘${”formsubmissionURL”}’,{
method: ‘POST’,
form: { id: ‘<portlet:namespace />fm’ },
on: {
success: function(){
alert(form submitted”);
// I WANT DATABASE SUCCESS OR FAILURE STATUS HERE FROM JAVA CODE
}
}
});
});
Thanks
You can pass data values by writing it to resourceResponse.
response.getWriter().write(String/int/char[])
Here, response can be servletResponse or portletResponse(resourceResponse)
You can get data in javascript like
this.get('responseData') inside success method.
EDIT:
As you are calling action method via ajax call, below code may be helpful.
PortalUtil.getHttpServletResponse(actionResponse)
Get httpServletResponse from code above and then you can use response.getWriter().write method.

Debugging Ajax requests in a Symfony environment

Not sure if SFDebug is any help in this situation. I am making an ajax post using jQuery. Which retrieves JSON data in my action URL and then makes a call to the Model method that executes the action. The part until my action URL, and the jQuery call to it work fine. With the data transmitted from the client to the server well received and no errors being made.
It is the part where it calls the method on the Model that is failing. My jQuery method looks like this:
$.post(url, jsonData, function(servermsg) { console.log(servermsg); }) ;
My server action is like this
public function executeMyAjaxRequest(sfWebRequest $request)
{
if($request->isXmlHttpRequest())
{
// process whatever
$servermsg = Doctrine_Core::getTable('table')->addDataToTable($dataArray);
return $this->renderText($servermsg);
}
return false;
}
The method of concern in the Table.class.php file looks like this:
public function addDataToTable($dataArray)
{
// process $dataArray and retrieve the necessary data
$data = new Data();
$data->field = $dataArray['field'];
.
.
.
$data->save();
return $data->id ;
}
The method fails up here in the model, when renderText in the action is returned and logged into the console, it returns the HTMl for SFDEBUG. Which indicates that it failed.
If this was not an Ajax call, I could debug it by seeing what the model method spat out, but this is a little tedious with Ajax in the mix.
Not looking for exact answers here, but more on how I can approach debugging ajax requests in a symfony environment, so if there are suggestions on how I can debug this, that would be great.
You must send cookie with session ide key via ajax
(Assuming you have XDEBUG configured on the server)
In order to trigger a debug session by an AJAX request you have to somehow make that request to send additional URL parameter XDEBUG_SESSION_START=1. For your example:
$.post(url + '?XDEBUG_SESSION_START=1', jsonData, function(servermsg) { console.log(servermsg); }) ;
You can also trigger it via cookie, but appending URL parameter usually easier.

Resources