My personal preference, which is in no way "THE" correct way to do it, is to use JSON for everything.
So I have a JavaScript function that, when a form is submitted, will convert the form data to a JSON string and POST it to the server.
The server then processes it, and returns another JSON object. In your login example, therefore, the server would receive:
{"username":"Foo","password":"bar"}
And it would return one of these:
{"ok":false,"error":"No user with that name was found."}
{"ok":false,"error":"The password you entered was incorrect."}
{"ok":false,"error":"Failed to log you in (error code: ###)"}
{"ok":true,"redirect":"/home"}
Every AJAX request response has this "ok" property. If it is false, there will be an "error" property saying what happened (and there may be additional data depending on the situation). On success, the "ok" property is true. A lot of requests just get {"ok":true}
all by itself, but sometimes there is additional data here too.
As I said, this is not "THE" way to do it, but I like it and it's consistent.
EDIT: Forgot to mention the bit about PHP errors.
The JavaScript that receives the server's response attempts to parse it as JSON using a try...catch
block. If parsing fails, then there was a server error. In such a case, an error message is popped up with the raw response from the server, with a note advising the user to contact me about the error message.