I'm learning to work with Backbone.js and set up the following environment:
/* define the model */
var Login = Backbone.Model.extend({
url:"api/index.php/login/"
});
/* the following code is contained in a view method */
var login = new Login({
email: $("#email").val(),
pass: $("#pass").val()
});
var result = Backbone.sync('create',login);
alert(JSON.stringify(result));
In the "index.php" on the server the correct method is called and the data is correctly available.
The alert just outputs: {"readyState":1}
Now my question: What should the server (index.php) return/output to answer the client?
I'd like to transfer data back to the client to e.g. display it.
Backbone.sync() is an asynchronuous operation. You cannot do
var result = Backbone.sync('create', login);
because sync() does not return anything useful. It sends the request to the server and returns immediately, long before the server's response has arrived.
Use the options parameter and place success and error callback functions there.
Backbone.sync('create', login, {
success: function () {
// whatever you want to do when login succeeds
},
error: function () {
// display an error message
}
});
The error callback would be executed if the server returned an 401 Unauthorized response, for example; the success callback when the server returns 200 OK.
For documentation on how to use these callbacks and what other options you can use, read the jQuery.ajax() docs.
Related
I know similar question has been answered in this forum. I have tried many of the solutions provided in stackoverflow for the problem, yet could not solve it. So I am expecting some suggestions from your expertise.
I am trying to make a call to AjaxController function on form submit via ajax call using Cakephp 3. The issue here is i am getting 403 error. I have not yet found out the fix for this. I can see that form is passing the value but Ajax call can not reach the controller function . I get following error
POST http://localhost/shoppingCart/ajax/ajaxTest 403 (Forbidden)
AjaxController:
public function ajaxTest(){
$result = "hello";
return $result;
}
script:(view.ctp of AjaxController)
$(document).ready(function(){
$('button').click(function(event){
var form_data = $(this).serialize();
var hidden_value = $('[name="id"]').val();
// alert("your form data "+hidden_value);//works fine here
event.preventDefault();
$.ajax({
url:'../ajaxTest',
type:'POST',
data : hidden_value,
success:function(result){
alert('success');
$("#result").text(result);
},
error:function(error){
alert('error ='+(error.Message));
}
});
});
});
// });
</script>
According to Cakephp:
If authenticator returns null, AuthComponent redirects user to the
login action. If it’s an AJAX request and config ajaxLogin is
specified that element is rendered else a 403 HTTP status code is
returned.
I think you didn't specify any authorization scheme. That why according to cakephp you are getting 403 error.
If you don’t use an authorization scheme, make sure to check
authorization yourself in your controller’s beforeFilter or with
another component.
You can make actions public (in beforeFilter or initialize) using:
// Allow all actions
$this->Auth->allow();
// Allow only the index action.
$this->Auth->allow('ajaxTest');
// Allow only the view and index actions.
$this->Auth->allow(['ajaxTest', 'index']);
CakePhp > Authentication > Handling Unauthenticated Requests
CakePhp > Authentication > Using No Authorization
Even though the below PHP code exits with an error, the success callback in the AJAX code is still being triggered. Why is that?
JavaScript code :
$.ajax({
type: "POST",
url: xxxx,
data: {info:data},
success: function(result){
//code here
},
error:function(msg)
{
alert('add data error,please add again');
}
});
php code:
if(is_wrong) //data is error
{
exit("the data is not right,please add again");
}
There are various ways to handle error or success, when communicating between the client and server.
1. with HTTP status code
One of the $.ajax() callbacks (success and error) will be called, depending on the HTTP status code returned by the server. The "normal" success code is 200 OK. When you send output with a PHP script, if everything goes well, your generated content will be sent with code 200.
This is the case when you call exit() here. From the point of view of your client-side JavaScript code, since it received status code 200 OK, it will call the success callback. If you want the error callback to execute, you have to send custom headers in your PHP code, before sending any other output.
You can achieve this with the header function. For example, the following code can be used to generate a "404 Not Found" status:
header("HTTP/1.0 404 Not Found");
Here you would need to find another HTTP code that corresponds to your code better. I don't think this approach is the best solution, because HTTP status codes are meant to be server status codes, i.e. not meant for reflecting application error codes.
2. with your own conventions
The other way would be to handle the application error codes would be to handle everything from the success() handler. You don't set error codes from your PHP, but establish a convention to tell when you have an application error or a normal case. You would still keep the error() callback, so that you can handle various HTTP errors (i.e. if your connection to the server is broken).
For example, if you send your data from the server to the client as JSON, you might send from your php:
if(is_right) //data is ok
{
$response = array(
'data' => $someData, // any data you might want to send back to the client
);
}
if(is_wrong) //data is error
{
$response = array(
'error' => "the data is not right,please add again"
);
}
// Called in both cases
exit(json_encode($response));
In your client-side code, you would have:
...,
success: function(result) {
if(data.error !== undefined) {
// do something if your server sent an error
console.log(data.error);
}
else {
var data = result.data;
// do something with the data
}
},
...
I'm relatively new to mailchimp and have been using this post to implement a very simple email capture form that will redirect to a new landing page on submit. I have been using this post:
using an existing form to send data to mailchimp, then redirect
I understand everything in the post except I need an example for this statement:
"However, if you want to redirect, you'd simply alter your jQuery ajax function to do so."
Can someone provide an example of how to alter the jQuery ajax function? Also I don't need it to return a success or failure message, I just need it to capture the name / email and then immediately redirect to the next page.
Thanks
Sparky is saying that you can modify the success function of the AJAX that is part of the submit function tied to form $('#signup').
i.e., Currently the success function is:
...
success: function(msg) {
$('#message').html(msg);
}
...
And you could just update to redirect doing something like:
...
success: function(msg) {
document.location = '/target/path/file.html';
}
...
EDIT - Doing the above will redirect the browser - so long as the AJAX call is successful (not necessarily that the API call was successful.) So even if the PHP is returning an error in the message - the success function is called because it is referring to the success of the AJAX call itself.
If you want to redirect only on a successful message returned by the PHP file then you'll have to check the incoming msg and handle accordingly.
...
success: function(msg) {
if (msg.indexOf('Success') != -1) {
document.location = '/target/path/file.html';
} else {
$('#message').html(msg);
}
}
...
This will redirect the browser on a successful message return from the PHP file, otherwise it will display the message in $('#message') .
I'm trying to send an AJAX request to a page to interpret some data, and if it complies with what i'm looking for, send another AJAX request back. Right now I can see the first request is being made, but I'm not getting one back
//message.php
<head>
<script>
function org_name(str){
alert(str); //this alert appears, so I know the data is being received by this function
$.get("common_functions.php", { group_name: str} );
}
</script>
</head>
Then, on common_functions.php I have a similar request back, however, I'm not sure exactly what the issue is. The alert box doesn't even appear so I'm confused as to why the console would say the request was sent
//common_functions.php
if(isset($_GET['group_name'])){
?>
<script src="http://code.jquery.com/jquery-1.8.2.js"></script>
<script type="text/javascript">
alert('common_functions'); //this does not appear
$.get("message.php", { name: "test"} );
</script>
<?
}
When I open up the javascript console in chrome I see the request sent form message to common_functions, but apparently the request on common_functions isn't sending one back
//text from javascript console
Request URL:http://localhost/message/common_functions.php?group_name=test
Request Method:GET
Status Code:200 OK
Does anyone see something obvious that I'm doing wrong or missing? If it makes a difference, common_functions is included in message.php because I do use some other functions from that page for my php.
You have to do something with your data. Right now, you're making an AJAX call, and doing nothing with your data.
So something like the following would work:
$.ajax({
url: "common_functions.php",
data: { group_name: str },
type: "GET",
success: function (data) {
$(data).appendTo("head");
}
});
Use $.ajax if you want control over execution states:
$.ajax({
type: "POST",
url: "common_functions.php",
data: { name: "test"},
success: function(r)
{
// user r as output
},
error: function(xhr, ajaxOptions, thrownError)
{
// error report
alert(xhr.responseText);
}
});
In this case you can see if execution was successful or if error occurred.
Also you can use firebug add-on for firefox or chrome to detect if response was sent. There is also an excellent tool called Fidler, which can give you much better overview over request/response states.
Here is an excellent tutorial for ajax debugging.
$.get will strip out <script> tags. You can use another jQuery AJAX method load() that won't, or use $.getScript. If you need content and script you can do both by making an ajax request for the content, and in the success callback of that ajax, call for the script with $.getScript
load() replaces all the content in the specified selector
$('#myDiv').load('common_functions.php', { name: "test"})
Will take all the content of the php output and replace all the contents of #myDiv but will also run the scripts
you may use a library that does that for you automatically, using http://phery-php-ajax.net
in your case, it would be
function messages($data){
$r = new PheryResponse;
// return your messages
return $r->json($messages);
}
function common($data){
$r = new PheryResponse;
switch ($data['group_name']){
case 'messages':
$r
->include_script(array(
'jquery' => 'http://code.jquery.com/jquery-1.8.2.js'
))
->phery_remote('messages'); // load your messages
break;
}
return $r;
}
Phery::instance()->set(array(
'common' => 'common',
'messages' => 'messages'
))->process();
on your page load
$(function(){
phery.remote('common', {'group_name': 'messages'});
});
you don't have to do anything else. btw, if you are including jQuery AFTER you are using $.get(), it won't work, obviously
I'm trying to get an understanding of how Backbone.js, Slim PHP and Paris/Idiorm might work together and I'm having trouble completing the flow, starting with model attribute data, all the way to the database. PROBLEM: What exactly gets sent to my server when I do model.save() ?
Client-side: Backbone.js
var Donut = Backbone.Model.extend({
defaults: {
name: null,
sparkles: false,
creamFilled: false
},
url: function() {
return '/donut';
}
});
var bostonCream = new Donut({
name: 'Bawston Cream',
sparkles: true,
creamFilled: true
});
bostonCreme.save(); // <-- Problem: Not sure what & format this is sending
I think the above is my main problem. My understanding is that backbone will by default, know to send POST data since it's new. It sends it to /donut which is routed, but the question I have is WHAT does it send? And in what format? The outcome I want is to save those donut attributes to my DB. I can pass this server-side code a json like this using jQuery $.post()...
var myDonut = {"name":"Jelly Filled", "sparkles":false, "creamFilled":true};
$.post('http://localhost/donut', myDonut);
...and it happily takes it, saves it to my database. But with the current setup trying to send my backbone donut data, I get POST 500 Internal Server Error. Below I have some server-side code.
Server-side: Slim PHP w/ Paris
class Donut extends Model {}
$app->post('/donut', function() use ($app) { // Slim framework routes my POST...
$donuts = Model::factory('Donut')->create(); // Paris stuff...
$donuts->name = $app->request()->post('name'); // Slim request parameters...
$donuts->sparkles = $app->request()->post('sparkles');
$donuts->creamFilled = $app->request()->post('creamFilled');
$donuts->save(); // Paris... Save name, sparkles, and creamFilled to my DB
});
I have a feeling the answer is out there, but every example I've looked at seems to be missing one piece of the puzzle or another and I can't get that "A-hA!" moment. I thank you in advance and apologize if this is a really ignorant question. :-P
FOLLOWUP/EDIT: 1
Can you paste the error messages?
I get a POST http://localhost:8888/donut 500 (Internal Server Error) in the current state. I can get more information with the following code.
bostonCream.save({}, { // REPLACE bostonCream.save();
success: function(model, response) {
console.log('SUCCESS:');
console.log(response);
},
error: function(model, response) {
console.log('FAIL:');
console.log(response);
}
});
Now when I run backbone's save(), I still get the 500 Error but also XMLHttpRequest as my FAIL response. The only remarkable clue from the XMLHttpRequest is responseText = SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'name' cannot be null.
So my guess is that either 1) I'm messing something up with the save() in that it isn't capturing my attributes correctly, 2) It is currently sending my attributes in a format that my server isn't recognizing with the standard $app->request()->post() Slim methods (Doesn't seem to do much when I try accessing directly with $_POST either), 3) My server isn't setup correctly to take the kind of data that is being sent.
Another thing I noticed although I don't know what to make of it is that when I add
echo $_POST;
It returns to me an empty array. Still gives me the FAIL. If I do THIS however...
echo json_encode($_POST);
It gives me a SUCCESS and the response is a [ ]. Nothing in there. Clearly my POST data is still wonky.
I came up with a solution to completing the problem: how to get data from client to server using the default backbone save() and .sync - passed over to the Slim php framework and going through Paris/Idiorm to my DB.
I am including my working updated code below:
Client-side: Backbone.js
var Donut = Backbone.Model.extend({
defaults: {
name: null,
sparkles: false,
creamFilled: false
},
url: function() {
return '/donut';
}
});
var bostonCream = new Donut({
name: 'Bawston Cream',
sparkles: true,
creamFilled: true
});
bostonCream.save();
/***** If you want to check out the response to save() ? ***
bostonCream.save({}, {
success: function(model, response) {
console.log('SUCCESS:');
console.log(response);
},
error: function(model, response) {
console.log('FAIL:');
console.log(response);
}
});
************************************************************/
Sever-side: Slim PHP w/ Paris/Idorm
class Donut extends Model {}
$app->post('/donut', function() use ($app) {
$donuts = Model::factory('Donut')->create();
/* EDIT: Works... but not the Slim way
$parameters = json_decode(file_get_contents('php://input'), true);
$donuts->name = $parameters['name'];
$donuts->sparkles = $parameters['sparkles'];
$donuts->creamFilled = $parameters['creamFilled']; */
/* SLIM: Using Slim Request Object */
$requestBody = $app->request()->getBody(); // <- getBody() of http request
$json_a = json_decode($requestBody, true);
$donuts->name = $json_a['name'];
$donuts->sparkles = $json_a['sparkles'];
$donuts->creamFilled = $json_a['creamFilled'];
$donuts->save();
// echo json_encode($parameters); // Prove you've captured POST data, send it back
}
Now my code is happily using the default settings of Backbone.js (no changes to sync) and sending proper model attribute information to my server which seems to be successfully accepting the data and saving it to my DB.
The key here seems to be this line...
/* $parameters = json_decode(file_get_contents('php://input'), true); */
// EDITED: getBody() method not documented in Develop Doc, only Stable # time of post
$requestBody = $app->request()->getBody();
If you want to know "what exactly is sent to the server", you should have a look at the Backbone.sync function in Backbone's code. It is very well documented, step-by-step. Then, the cleanest way to achieve what you need is to write you own sync function, inspired by Backbone's sync.
Also, a quick way to see what is sent to the server is to use your browser debug console (Network tab). You can compare here what is sent by Backbone vs. what is sent when you use $.post directly. Please post this information if you need more help !
backbone sends json data to your php backend server, which you should expose your RESTful api to respond to http verb like get, post, put, delete and etc.
your backend api is responsible for communicating with database.
I am not sure about SLIM PHP. it seems to handle the request. Can you paste the error messages?