POST data not appearing in CakePHP controller - php

I'm using AJAX on a knockout.js form to post some information that CakePHP should receive, however, Cake doesn't seem to find anything. Also, the alert isn't appearing despite a 200 status (OK) from the POST.
Here's the AJAX
$.ajax({
url: "/orders/finalize_payment",
type: "POST",
dataType: "json",
contentType: "json",
data: JSON.stringify({"customer": customer_id}),
success: function(){
alert("success");
}
});
Here's the corresponding action in the orders controller. Right now, I completely stripped it to just the bare minimum.
function finalize_payment($id = null){
$this->layout = false;
$this->autoRender = false;
if($this->request->is('post')){ //the user has submitted which status to view
print_r($this->request->data);
echo "test"; //just to make sure it's reaching this point
}
}
When I open up the network tab in chrome, it shows the request payload as
customer: 1
The POST shows as success, status 200. I checked the response headers and it just shows
array
(
)
test
Despite chrome showing a payload being sent, CakePHP isn't finding it apparently.
Update
I changed the request from AJAX to $.post and it worked. I still have no clue why
$.post("/orders/finalize_payment",{"customer_id":customer_id},function(data){
alert('success');
});

Don't encode post data as json
The code in the question won't appear in any php script, the reason is this:
contentType: "json"
It's not a form-url-encoded request, so e.g. the following code:
print_r($_POST);
print_r(file_get_contents('php://input'));
will output:
Array()
'{"customer":123}'
If you want to submit data as json, you'll need to read the raw request body:
$data = json_decode(file_get_contents('php://input'));
There might be times when that's desirable (api usage), but that isn't the normal way to use $.post.
The normal way
The normal way to submit data, is to let jQuery take care of encoding things for you:
$.ajax({
url: "/orders/finalize_payment",
type: "POST",
dataType: "json", // this is optional - indicates the expected response format
data: {"customer": customer_id},
success: function(){
alert("success");
}
});
This will submit the post data as application/x-www-form-urlencoded and be available as $this->request->data in the controller.
Why $.post works
I changed the request from AJAX to $.post and it worked. I still have no clue why
Implicitly with the updated code in the question you have:
removed the JSON.stringify call
changed from submitting json to submitting application/x-www-form-urlencoded
As such, it's not that $.post works and $.ajax didn't ($.post infact just calls $.ajax) - it's that the parameters for the resultant $.ajax call are correct with the syntax in the question.

As you're using CakePHP you may find adding RequestHandler to your components fixes the problem.
public $components = array([snip], 'RequestHandler');
Doing this allowed me to transparently access JSON posted data using $this->request->data. The other answer's advice to not encode POST data as JSON becomes a bit awkward, given that certain JS frameworks, such as Angular, post JSON as default.

Using raw data and json you can use:
$data = $this->request->input('json_decode');
**Data is an object now, not an array.
Then you can use:
$this->MyModel->save($data).

Nicely formatted question :)
I'm pretty sure I have the answer, though I could be wrong... Basically, $this->request is an object in Cake, and $this->request->data is a variable/array that's a property of the object.
The data you're sending to Cake is going straight into the object (if this is even possible), not into the data array. This is why when Cake generates forms using the HtmlHelper, the names are, for example data[User][username].
I think, if you put JSON.stringify({"customer": customer_id}) into a 'data' array and send that, it should work.

Have a look at this post. You're data string probably isn't correct. Therefore CakePHP might not be able to put it in $this->request->data.

Use print_r($this->request->params);
function finalize_payment($id = null){
$this->layout = false;
$this->autoRender = false;
if($this->request->is('post')){ view
print_r($this->request->params);
} }

Related

Sending information with AJAX and CodIgniter

Hey guys I am building an application in which I send input value from a text box via AJAX to a controller function and then return what I send back to the user (I am developing an instant search, this is a first step).
The AJAX links to the method fine however I am having problems returning the information. I receive no error messages, the problem is that the return string is BLANK.
I receive [you wrote ] rather than [you wrote WHATEVER I IN PUTTED ]
Any help greatly appreciated.
view_index.php
function search(){
var term = document.getElementById("mainsearch").value;
$.ajax({
type: "POST",
url: "<?php echo base_url('index.php/site/search/')?>",
data: term,
cache: false,
success: function(html){
alert("you wrote " + html);
}
});
controller_site.php
function search(){
$gotcha = $this->input->post('term');
return $gotcha;
}
The data: parameter accept a key : value json to pass to the POST, as the json array key will be your $_POST key
Try with this:
$.ajax({
type: "POST",
url: "<?php echo base_url('index.php/site/search/')?>",
data: {'term': term }
cache: false,
success: function(html){
alert("you wrote " + html);
}
});
You didn't send your data correctly, so PHP has nothing to process, and you end up sending back nothing:
data: term,
POST/GET requests MUST be in key=value format, and you're sending only the value portion. Try
data: {foo: term},
and then
$gotcha = $this->input->post('foo');
You need to change return to echo as AJAX response works on whatever echo from called function.
So, you can code like :
function search(){
$gotcha = $this->input->post('term');
echo $gotcha;
}
or
function search(){
echo = $this->input->post('term');
}
The responseText property returns the response as a string, and you can use it accordingly
It is generally a bad idea to return HTML from your controllers. Instead try to just manage data server-side wise and do all the frontend on the client side.
Now, for the error:
The success callback takes 3 parameters
You need to pass key-value pair in the data argument of the .ajax call
Make sure you handle errors on your controller appropriately because if something goes wrong you'll get an html document as a response from CodeIgniter and you'll spend a lot of time debugging javascript to find out that the error was actually server-side
1 the callback:
Your success callback function should look like this:
function (data, status, response) {
}
Where:
data is whatever you are echoing from your controller's method. You'll probably want JSON.
status Will tell you if the HTTP response message (e.g. "Not Found" is the status for a 404 code, "success" for a 200 code)
response is the jquery wrapped XmlHttpRequest object that gives you a handful information of the transaction, for example response.responseText would give you whatever you outputed from PHP, response.responseJSON would give you a JSON object if you echoed a json encoded object, etc.
Why should you care? Because those extra parameters will let you decide if something went wrong on your backend so you can handle the situation client-side not leaving the user wondering if you app just don't work. Worse, giving the infamous red cross on the status bar of the browser.
If you set the dataType parameter of the jQuery.ajax function then you can explicitly tell jQuery what kind of data you are expecting to be retrieved from the server on data parameter from your callback.
2 the sent data
As said, you need to either pass value-pairs or a URL encoded string. If you intend to use GET then you can pass the URL encoded string, but that means you have to have arguments on your CI function like:
function search($term)
And then CI automatically routes the incoming parameters. But since you want to do POST then you'll want to effectively get the values with $this->input->post("name")
If you have your input inside a form, or several fields that you need to send, then its easier to just serialize the form:
$.ajax("url", {
type : 'POST',
data : $('#form').serialize(),
dataType : 'json',
success : function(data, status, response) {} error : function(response, status error) {}});
3 handle errors
If you are relying on AJAX then make sure that you return some sort of error or warning so you can catch it client side:
function search() {
$term = $this->input->post("term")
if($term == FALSE) {
//return a 404 so that you can catch .error on jquery
} else {
echo $term;
}
}
Do a research on RESTFul apps. It'll help you a lot understanding that. this is a good starting point and although your question was not exactly related to this, it is a good practice to have separate layers on your application so that you just consume data from your backend, handle situations and then just react accordingly on the frontend, that is, you just use javascript to either send, receive and list data. If you are using CI or any other MVC framework then you should not really be generating HTML on your controllers, thats what the views are for.

understanding jquery getjson approach

In an earlier post today the answer has led me down the route of using a JSON feed to populate elements in my page.
Something new to learn!!
the JSON data is created from a PHP script which retrieves the data from a Mysql database. The php script retrieves a specific record which I need to pass to the php script with the getJson call.
I've had success with creating the url with the parameters added as a GET method but I can't find an example of a POST method - the parameters should go as an optional parameter. here's what I have so far...
function loadData(index) {
alert(index);//debug
$.getJSON('loadJSONholeData.php' ,
{hole: index} ,
function(data) {
I've found examples for a twitter feed which shows a parameter like option: "cat", but can't find an option where the value is in a variable.
I don't understand how to use the parameters - where am I going wrong. Appreciate this is probably a fundamental issue but I'm learning.
Thanks
Update:
I've revised the code per the responses below and used both suggestions to pass the POST parameter, but the receiving PHP code is not reading the POST parameter and just returns the default query values.
I even used as static value of 1 both as a value and as a string but no joy.
Here's my receiving PHP code which accesses the POST values:
$hole = 3;
if (isset($_POST['hole'])) {
$hole = $_POST['hole'];
}
I'm missing something basic here. The value in 'index' definitely exists as it shows in the debug and JSON data is being returned )(but the default). I can go back to my GET method but want to see this work!!
Thanks
Update: Success!!
I played around further with the revised code. I removed the content type parameter from the code and it all works now, the PHP is returning the correct query.
I assume then that by specifying the JSON type in contentType it passes the POST parameter in a different way to PHP which expects it in anpther way?
Onwards and upwards - thanks
The $.getJSON() method does an HTTP GET and not POST. Try something like this -
$.ajax({
url: 'loadJSONholeData.php',
data: JSON.stringify({hole: index }),
type: 'POST',
contentType: 'application/json;',
dataType: 'json',
success: function (result) {
//(result.d) has your data.
}
});
Each key/value pair in the arguments object will represent a parameter in the HTTP POST. You can use variables as values, but I believe they will be converted to strings, so it's better to do the conversion yourself (so you can make sure they have the correct format). A simple example:
var dynamicValue = foo();
$.post('my/url', { var1:"static value", var2:dynamicValue }, function(data) {
// Your callback; the format of "data" will depend on the 4th parameter to post...
}, "json"); // ...in this case, json
Now, in case your server is expecting a json encoded object/list, you can pass it by using JSON.stringify:
function foo() {
return JSON.stringify({ my:"object" });
}
JSON should be available in most modern browsers, in case it's not, you can get it here (json2.js, under "JavaScript").

AJAX, JSON, jQuery, and PHP

I know there are alot of different questions about this but none of them seem to pertain to me. I have an ajax request as follows:
var responsePacket;
$.ajax({
dataType: 'json',
type:'POST',
data:{
"updatePacket":{
"job":"name-update",
"firstName":firstName,
"lastName":lastName
}
},
processData: false,
url:'modify.php',
success: function(json){
console.log(json);
responsePacket = json;
if(responsePacket.updateStatus==true){
genAlertAlignAndShow('Name Successfully Updated', false, 4000);
}
else{
genErrorAlignAndShow('Name Update Failed!', false, 4000);
}
}
})
And my PHP on the other end are as follows:
$updatePacket = json_decode($_POST['updatePacket'], true);
//and I access variables from the JSON Object like this:
$job = $updatePacket['job'];
In response to the AJAX, the PHP file will punch out a simple JSON object, and yes my headers are set to application/json. This is how I a output a JSON response, I have tested it and it appears to get back to the AJAX Request when I rig it to return a static response:
$responsePacket = array("updateStatus"=>true);
echo json_encode($responsePacket);
But Here Is The Problem
As you can see I output the data to the console, but all it says is null which I have deduced is indicative of the JSON not getting to the PHP correctly. So, is there a proper way to create JSON Objects and prepare an AJAX request that will get the data to the PHP script intact.
I have been grappling with this problem for about 3 hours now, ANY suggestions are welcome.
I believe $_POST['updatePacket'] is not actually a json string. Try to access it like this instead:
$updatePacket = $_POST['updatePacket'];
$job = $updatePacket['job'];
No need to json_decode() it. From the json_decode() manual (return value):
NULL is returned if the json cannot be decoded...
Give it a try. As mentioned in the comments, var_dump($_POST); should be the first thing you try, to ensure you're getting what you think you are.
I figured it out. Here is my AJAX Requst:
$.post('modify.php', { job: "name-update", lastName: lastName }, function(data){
console.log(data);
})
The Problem:
When declaring data for an AJAX Post request putting quotes on the variable names will make the variables inaccessible to the receiving script.
You can easily make the time consuming issue of getting form data in a clean way with jquery, or javascript alone.
All you need to do is .serialize() the data. An example is here.
$( "form" ).on( "submit", function( event ) {
event.preventDefault();
console.log( $( this ).serialize() );
});
Once it is done you can transform a string that looks like this.
"param1=someVal&param2=someOtherVal"
with this
$params = array();
parse_str($_GET, $params);
with this usage you also want to filter the data and you should do this prior to the above.
http://php.net/manual/en/function.filter-input.php
Do this is less time consuming then listing each one individually in your ajax. You can also create a function to do this so you aren't continually writing ajax boilerplate code.
You are doing it wrong. You don't send a JSON object to the server, you send key/value pairs. And it's what jQuery expects. Do it like this instead:
data: {
"job": "name-update",
"firstName": firstName,
"lastName": lastName
},
and access the values like this:
$job = $_POST['job'];

Is this a jQuery bug, or am I missing something?

I am using jquery-1.3.2 in an AJAX web application. I use the jQuery ajax $.post() method to submit requests to the server.
On the server I am using php to build an array and then json_encode the answer. Then on the client I use the callback function of the AJAX post method to process the response.
All works well until I use the $.post() method to send variables to the server. If I send variables to the server, the response I get back is [object Object] and therefore I am unable to parse it. I have a work around at the moment that when posting variables I request a HTML response and then I parse that.
So the code involved taken from my site is:
The Jax call:
$.post("inc/sendfeedback.php", {NAME: name,TYPE: type,EMAIL: email,COMMENT: comment}, function(data) {PostData(data);}, "json");
So the PostData code looks like this:
function ProcessData(data)
{
//alert(data);
var jo = eval("(" + data + ")");
if(jo.result == "true")
{
if(jo.data != "" && jo.element != "")
{
$(jo.element).html(jo.data);
}
}
SMessage(jo.error);
}
If I uncomment the above code the alert with have in it [object Object].
if I remove the Post variables from the call it works fine.
The server code look like this:
$arr = array ("result" => $result,"data" => $data,"error" => $error,"element" => $element);
echo(json_encode($arr));
Is this a bug with the jQuery library, I tried it with the 1.2 version however its was still present there? I also search the jQuery site and can not find anyone having this issue.
So I assume I am missing something. But what?
$.ajax({
url: "script.php",
global: false,
type: "POST",
data: {NAME: name,TYPE: type,EMAIL: email,COMMENT: comment},
dataType: "json",
contentType: "application/json",
success: function(data){
alert(data.result);
}
}
No need to eval, jQuery evals/parses it before calling the success callback.
eval = pure evil
http://docs.jquery.com/Ajax/jQuery.ajax#options
Because you are using an associative PHP array, json_encode will return a string representation of a Javascript Object and not a Javascript Array. However, you should still be able to process it in a similar fashion to an array:
for (var key in data)
{
var item = data[key];
}
I would strongly recommend you download Firefox+Firebug addon and use the console API for debugging/dumping what is being returned by the server.
I have since registered and now can't post comments into this thread without reputation and can not see any easy method to claim this question as mine.
Deviant, your suggestion of using the $.ajax() method worked. Reason it didnt work for me the first time was I submitted the post data as a JSON object when the server code was expecting POST data.
So I fixed my javascript to call the server script correctly and everything works exactly as it should.
So the conclusion is, the $.post() method has a bug in it. I have not tracked it down but line 3633 is were the post method makes the call. I started digging however have not yet found the issue.
I qualify this by the fact the $.ajax() to the same server script and the same javascript processes the response and it all works, use the $.post method and my script fails with the return even through the return object appears to be a valid JSON object.
Thanks for the help guys. Now to go and remove all my $.post calls for $.ajax calls.
The result of all this can be seen at www.pygames.net
Cheers
Shane
a.k.a FrogSkin

cakephp, jquery, .ajax(), dataType: json

is it possible to be able to do without a view for a cakephp controller function? i am trying to have my server return a datatype that is not a string - but an array
my controller function :
function test() {
$this->layout = 'plain';
$task['Numbers']['uno'] = 'mooo';
$task['Numbers']['dos'] = 'says the cow';
$result = json_encode($task);
$this->set('result', $result);
}
my view file test.ctp
echo $result;
my jquery:
$('#test').live('click', test);
function test() {
var data = $('#form').serialize();
$.ajax({
type: "post",
url: "/controller/test",
data: data,
dataType: 'json',
success: function(response){
alert(response.Numbers.uno);
}
});
}
clicking on the html element marked test doesn't give me anything. however if i take out
dataType: 'json',
and change alert(response.Numbers.uno); to
alert(response);
in my jquery - i get an alert: the json encoded data but as a string (alert(typeof response);)
does anyone have any idea what might be happening?
First, to answer your question, yes you can do without a view (and this is a good case for doing so). In your controller action (test, in this case), just set $this->autoRender = false;. That's what I usually do and just echo out the encoded JSON string in the controller itself. Less clutter that way.
The next thing that I'd look at are your debug settings in config.php. If not set to 0, there's a very good chance that this is your problem. Your echo statement may be echoing the JSON-formatted string, but appending debug output to it. In the method, just include Configure::write ( 'debug', 0 ). This will disable debug only for the current request. I usually do this in my AppController actually:
if ( $this->RequestHandler->isAjax() ) {
Configure::write ( 'debug', 0 );
}
I'd engage a tool like Firebug and see what's happening to your ajax request. It will monitor those requests and provide the request and response headers for you to inspect. That may help. If the latter is the problem, then Firebug would have shown you that in the response headers.
I agree with Rob, except with setting your debug in the app controller. It gets a little annoying to me because you have to set the debug level in the app controller every time you want to debug something for a specific function. I write my handler out like this in the controller i am working in.
Configure::write('debug', 0);
$this->autoRender = false;
Also I agree with the use of firebug. With firebug all you have to do is open firebug, click on console, and then run your test. This will tell you what you are doing with your jquery and give you the results.
Check out the cakePHP book on Request Handling:
http://book.cakephp.org/view/174/Request-Handling
CakePHP has some built in functionality to handle controller methods that return json.
You have to transform the data before use it.
See this answer:
jQuery ajax request with json response, how to?
you have to use the
var json = $.parseJSON(response);
alert(json.Numbers.uno);
I just use
die(json_encode(array('success' => true, 'result' => $result)));
at the end of the called controller method and it works for me.

Categories