How to access a custom field in Exception in jQuery's jqXHR object?

I created a subclass of PHP's Exception class (which I'll call MyException) because I needed to add an additional property that contains a more user-friendly message for the user. So aside from the usual properties of the Exception class (i.e., $message, $code, ...), I added a property called $userMessage. I ran into no problems with this, and it works very well within PHP.

But when I get to the final moment when I throw a MyException within PHP for .ajax()'s .fail() handler to receive, how do I access this custom property (i.e., $userMessage) from the jqXHR object? It wasn't the 'statusText', not the 'responseText' property either.

Thanks.
elepilAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

RobOwner (Aidellio)Commented:
You need to catch the exception and return the data from PHP to the browser (jquery and just like you would any other data success or failure).

try {
...
}
catch ($e) {
header('application/json');
echo json_encode($e);
}
0
RobOwner (Aidellio)Commented:
In addition, jQuery's .fail() will only be called when there is an HTML error code e.g. 404, 500 so the fact that your PHP fails but the communication between the browser (jQuery) and your server (PHP) is working then jQuery will call .success() when the data is returned.
0
RobOwner (Aidellio)Commented:
The way I get around this is by setting an error flag in the json object I'm returning (let's assume json for the time being as it's a great way to communicate)

so taking my example above:

try {
...
// everything is ok
header('application/json');
$a = ('error'=>false, 'data'=>$other_stuff);
echo json_encode(
}
catch ($e) {
$a = array('error'=>true, 'message'=>$e->getMessage());
header('application/json');
echo json_encode($a);
}

Open in new window

==========

then in your jQuery

$.ajax({
    ....
    success: function(d) {
        if (d.error) {
            // this is where you show an error message
        }
        else {
            // everything is ok, continue what needs to be done
        }
});

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Exploring ASP.NET Core: Fundamentals

Learn to build web apps and services, IoT apps, and mobile backends by covering the fundamentals of ASP.NET Core and  exploring the core foundations for app libraries.

Ray PaseurCommented:
I'm guessing that this question is a follow-on from:
http://www.experts-exchange.com/Programming/Languages/Scripting/PHP/Q_28658286.html#a40731619

There is a timeline of events and interaction here, and I think Rob's last post will be the best one for you.  If you want to see a little more about the timeline, this article can give you the background information you need.
http://www.experts-exchange.com/articles/11271/Understanding-Client-Server-Protocols-and-Web-Applications.html

If you want to create a RESTful interface, you will need to know about HTTP response codes.  Here is my executive summary:
2xx - everything is OK
3xx - everything is somewhere else
4xx - client screwed up
5xx - server screwed up
Details here:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

The timeline for an example login request, as I see it, would look like this:
1. Client visits a page with a GET request
2. This request triggers a PHP script that responds with an HTML form
3. Client fills in the form and fires the submit button
4. JavaScript "submit handler" intervenes, maybe does some client-side pre-validation, etc
5. JavaScript makes an AJAX POST-method request to a PHP validation script on the server
6. The PHP validation script examines the credentials in the AJAX request
7. If the credentials are acceptable,
7.a the PHP validation script puts OK signal into the PHP session
7.b the PHP validation script creates a JSON object representing a successful login
7.c the PHP validation script sets a response code of 200-OK or 201-CREATED
7.d the PHP validation script responds to the request in step 5, with a JSON string
7.e PHP shutdown functions
8. If the credentials are not acceptable,
8.a PHP throws a UserInvalidCredentialsException
8.b PHP UserInvalidCredentialsException handler creates a JSON object representing a failed login
8.c PHP UserInvalidCredentialsException handler sets a response code of 401 or 403
8.d (see 7.d)
8.e PHP shutdown functions
9. JavaScript receives the JSON string and the response code from the PHP validation script
10. JavaScript prepares a client view showing what happened

If you deconstruct the problem into these steps that keep client and server actions isolated, with only formal communications across the client/server request/response protocol, you'll be successful.  JavaScript does not need to know anything about how PHP got to the conclusion that the user credentials are valid or invalid; it just needs to see the response.  With this separation of concerns, you have greater freedom to program each side of the problem independently and JavaScript does not need to know anything about PHP Exception processing.  Likewise, PHP does not need to know anything about what JavaScript will do with the response code and response JSON.  Much easier that way!
0
RobOwner (Aidellio)Commented:
Thanks Ray, I almost posted your article but thought you'd be asking before too long!
0
Ray PaseurCommented:
:-)
0
elepilAuthor Commented:
To Rob Jurd.

What you have succinctly and clearly conveyed to me is the same as what I got from the forum at jQuery.com as well -- that I had to use the .success/.done handler to handle both success and failures from the PHP script. I guess the "slight purist" in me thinks that the .success/.done handlers should handle only successful operations, and the .fail() handler should handle only the unsuccessful operations. But I now realize that there is no mechanism in place for PHP to pass a message through the jqXHR object. So yes, I now realize I have to pass my message through the .success handler.

I also got the chance to see and learn how more experienced PHP developers do things, and I greatly appreciate seeing your method. I was using a much simpler method of returning a string "true" for a successful operation, and any other string is an automatic failure where the message should be displayed right away in a <div id="message"></div> at the bottom of the UI. Mine is crude and simple, but your method is better because a JSON object can provide a lot more detail than a simple string. I have also repetitively seen people use json_encode() that I really think I should look into that in greater depth. So I'm happy because I received confirmation that I cannot use the .fail() handler for this, and I got more insight in seeing how you did it. Thank you very much, Rob!


To Ray Paseur,

Ray, you are one of the most helpful people in this forum, 99% of the time, it's a pleasure to interact with you. Even when you don't have a direct solution to an inquiry, you manage to somehow provide supplemental information that provides a little more richness on top of what others have already given, such as what you have done in this case. Much appreciated.
0
RobOwner (Aidellio)Commented:
elepil,

I'm glad you've got so much out of this conversation.  

As I was working on another project, I thought of you and this question as it occurred to me that you can control the http status codes that are returned to the browser.  I'm hesitant to suggest this but wanted to give you the option.  The status codes reflect the communication between the client and the server as we've all mentioned above.

In this project I'm working on, I'm using a URL routing system called Slim (http://docs.slimframework.com/response/status/).  It's great to use for a lot of different reasons but the main ones are for SEO (Search Engine Optimization) as the URLs can be prettified e.g. /search/product-id/product-name etc but it also adds a sense of logical organisation to the requests made from your page.  The long and short of it is that when you send a response to the client (using Slim), you can set the http status code along with any relevant information.

So definitely worth a look.
0
elepilAuthor Commented:
Rob,

Thank you for that suggestion. Reading briefly about it, so I'd have to install SLIM, then use their API to put the user-friendly message I want in the header which I can then extract on the JavaScript side. I'll definitely think about it.

Your response to my post did more than just provide me another way of sending data from server to client. You also confirmed to me what I was told in the jQuery forums that it is not possible to send custom data through jQuery's jqXHR object. I got the impression that developers who use jQuery course their data through the .done()/.success() handlers rather than the .fail().

By the way, I noticed you would use header('application/json') prior to echoing your json string to the client. I understand what it's for, i.e., to be very specific to PHP and the receiving end what kind of data you're sending. But when I tried it, it didn't seem to matter if it was there or not. So now I'm curious, did you experience a problem in the past which led you to adhere to this practice?
0
RobOwner (Aidellio)Commented:
You don't want to blur the line too much between an error on your application and an error in the browsers communication with the server. One reason is that the browsers (and jQuery) may one day change how those errors are handled and you do not want your application reliant on that. I.e.using the .fail() you're saying to someone else that reads your code, that there was a communication error with the server. So even though it's possible, It's just confusing for anyone else interpreting your code.
I always use the header that that's to the days I'm sending because of the reason I mentioned above where the client (this could be a browser [of which there are quite a few], an app, native software etc) may ignore different types of headers at this point but should they choose to actually do something, you don't want to be caught out.
I know the chrome browser will parse the response as an object automatically if you set the json header.
Just a thought :)
0
elepilAuthor Commented:
Thanks for the sage advice, Rob. :)
0
elepilAuthor Commented:
Rob,

Sorry to bother you again, but I wanted to ask you about your usage of :

header('application/json');

Open in new window


I actually asked you about this in one of my previous posts, but I'm not sure I got an answer from you. For some odd reason, it didn't seem to have an effect on my local server, but when I deployed my application to the remote host, the weirdest thing happened. My PHP side would execute perfectly fine, and it would even successfully execute this final statement:

echo json_encode("<whateverResultStringHere>";

Open in new window


And here's the odd thing -- instead of reaching .ajax()'s .done()/.success() handler, it keeps hitting the .fail() handler! This phenomenon confused the heck out of me at first, and for the lack of anything better, I decided to remove the header() function, then it went through fine.

I asked you before what in your experience could have encouraged you to use header(). I'm curious because although I got past my issue by removing header(), did you ever encounter an issue because you didn't use it? I'm asking this just for my own learning.

Thanks.
0
RobOwner (Aidellio)Commented:
Please see my last comment as I mentioned why I use the header: http:#a40732743

So this confirms what I thought to be true.  Check your jQuery.ajax() dataType flag as it should be set to 'json'.
0
elepilAuthor Commented:
Rob,

I did read that comment you made but wasn't sure I understood you.

You said:
the client (this could be a browser [of which there are quite a few], an app, native software etc) may ignore different types of headers at this point but should they choose to actually do something, you don't want to be caught out.

Correct me if I misunderstood, but I interpreted what you said as your wanting to be proactive in the event various clients eventually start doing something with the different header types. But in my mind, what if they change the syntax of "application/json" to "app/json", or something like that. Wouldn't the possibility of header format change possibly work against you as well?

You were also saying that using the header() with Chrome browser would cause it to parse it automatically. But by specifying dataType: "json" in .ajax(), that's what parses it for me. I actually didn't have to do a JSON.parse() on the result that came in.

Did I understand your post correctly before?
0
RobOwner (Aidellio)Commented:
be proactive in the event various clients eventually start doing something with the different header types
That's right but it would seem that they are already.

Here's an example to show you what's going on with the header: http://jsbin.com/bunefu/1/edit?js,console

In both ajax examples, the dataType is 'json'.  The difference between the two requests is the first one returns the header 'application/html' and second 'application/javascript' (akin to application/json for all intents and purposes).  The first call fails, the second works.

So in your case, I would set the header to 'application/json' in your PHP, dataType: 'json' in your jQuery and use console.dir(textStatus) to see what the error message is.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.