I want to post data to a controller in CakePHP, but posting with JQuery always results in"POST http//localhost/SA/myController/editUserData/1 400 (Bad Request)" error and I can't figure out why.
In my view I have the following method, that posts the data to the controller page
$scope.saveUser = function() {
$.ajax({
type: 'POST',
url: '<?php echo Router::url(array(
'controller' => 'myController',
'action' => 'editUserData',
0 => $userInfo['user']['id'],));?>',
data: { email: 'cabraham#delhi.k12'},//"my edited data for example"
success: function (data) {
alert(data);
}
});
My controller method looks like this:
public function editUserData($id) {
if($this->request->is('post') || $this->request->is('put')) {
$this->AcsaUser->save($this->request->data('email'));//edit and save the new data
echo 'ok';
}
}
Any ideas??
Two things that may be throwing it.
(1) Cake's built-in security - so exempt the method from it:
In AppController.php
public function beforeFilter() {
$this->Security->unlockedActions = array('editUserData')
}
(2) Decide how you want your editUserData method to render the view, if you're echo'ing out an 'ok' it will still pull in the default layout and look for an editUserData.ctp in the view (and cause an error if it doesn't find the file), so
To not render anything, ie a .ctp view file and the default layout.. in the editUserData($id), add
$this->autoRender = false;
To only render the view file and not the layout:
$this->autoLayout = false;
......Then lastly I wound just add this parameter in the ajax call :
dataType : 'html' // (or JSON?)
Related
I'm trying to read $_POST array posted through AJAX in a controller action using Yii::$app->request->post(), but something strange happens.
jQuery:
`
function renderGridView() {
var formId = $('#input-field :input[value!=""]');
// extract values. Make sure to send _csrf token
$.ajax({
url: "?r=value-search%2Fsearch", //this one works
method: 'POST',
data: {
searchData: formId.serializeArray(),
},
success: function(response) { //JSON array is returned.
/*$('#resultGrid').DataTable( {
data: [
response['provider']
],
columns: [
response['columns']
]
}); */
console.log(response);
}
})
}
`
PHP Controller action:
public function actionSearch() {
$data = \Yii::$app->request->post('searchData');
$tt; $svalue;
if(count($data) === 0) {throw new UserException('data is emptry');}
echo var_dump($data);
}
And here's the issue, the code above works just fine. But when I'm trying to echo $data my custom UserException 'data is empty' is thrown, instead of PHP's 'trying to pass array as a string', which I'd normally expect. What is causing this? Why does post() behave like this? Is there a technical reason to it?
just change
data: {
searchData: formId.serializeArray(),
},
to
data:formId.serialize(),
you should use ActiveForm to create your form using your model and the names will be automatically assigned to inputs which include the convention ModelName[field_name] apart from this you haven't shown your form but in your action you are getting the searchData in the post() array so I assume you have the data being posted as
[
searchData=>[
field_1=>value,
field_1=>value,
field_1=>value,
field_1=>value,
]
]
This is my controller action.
public function getData(){
if($this->request->is('ajax')) {
$session = $this->request->session();
$data=$session->read('User.access_token');
$this->set('data', $data);
$this->set('_serialize', 'data');
}
}
It is my controller action in cakephp 3.3. I want to getting my session data but it is showing error code 500 .I have already write session data and that is working on normal call of action. I also referred to https://stackoverflow.com/a/19861698/3110742
Below is my session write part.
public function oauthcallback(){
$session = $this->request->session();
$session->write('User.access_token', $google_sess);
}
Need to see the ajax call to confirm but usually error 500 occurs when the wrong url is called.
I advise to use always the Url helper to avoid any issue (will also work with Routes)
Ex:
$("#my-ajax-btn").click(
function()
{
jQuery.ajax({
type:'POST',
async: true,
cache: false,
url: '<?= $this->Url->build(['plugin' => null, 'controller' => 'Controllers', 'action' => 'action']) ?>'
});
return false;
}
);
CakeBook url conventions:
https://book.cakephp.org/3.0/en/intro/conventions.html
CakeBook Url Helper:
https://book.cakephp.org/3.0/en/views/helpers/url.html
I'm using Laravel 5.2. On my index page, I've got a button to add a new entry, which brings up the form in a lightbox. This form then submits via the create method.
I also have each entry listed on this page, with the ability to edit them inline, which submits via the update method.
I've setup validation via a Request. This means when someone misses something on the add, it redirects to the index method with errors. The errors only show though, when the lightbox is triggered by the user.
I know I can use $errors to see any errors, but I don't see how I can differentiate between the create and update forms for the sake of forcing the lightbox to appear on reload with create errors. Is there a way to do that?
Update:
Suggestion was made to use AJAX to bypass the reload issue, but now I'm getting a 422 return:
AJAX call:
(function(){
var submitAjaxRequest = function(e){
var form = $(this);
var method = form.find('input[name="_method"]').val() || 'POST';
$.ajax({
type: method,
url: form.prop('action'),
data: form.serialize(),
success: function(data){
console.log(data)
}
});
e.preventDefault();
}
$('form[data-remote]').on('submit', submitAjaxRequest);
})();
Request:
public function response(array $errors)
{
$response = parent::response($errors);
if ($this->ajax() || $this->wantsJson()) {
return $response;
}
return $response->with('requestMethod', $this->method());
}
I've also tested the ajax call and it works fine when the validation rules are met. It only fails if the validation comes back with something incorrect in the input.
You could override the response method so that you can flash the type of request.
In you Request class you could add
public function response(array $errors)
{
$response = parent::response($errors);
if ($this->ajax() || $this->wantsJson()) {
return $response;
}
return $response->with('requestMethod', $this->method());
}
(With ajax you wouldn't need to worry about the page reload so we can just return the original response.)
In the above I'm assuming you're using POST for your create methods and PUT or PATH for your update methods. If this is not the case you could use a way that make sense to you to differentiate between the requests.
Then in your view you could do something like:
#if(session('requestMethod') == 'POST')
https://laravel.com/docs/5.2/responses#redirecting-with-flashed-session-data
If you are going to use ajax, as I mentioned in the comment above, you will need to make sure you use the error method within the ajax call:
$.ajax({
type: method,
url: form.prop('action'),
data: form.serialize(),
success: function (data) {
console.log('success', data)
},
error: function (data) {
console.log('error', data)
}
});
Hope this helps!
I'm using Laravel 4,
I want to reload a view and change the content (Basically change the langage)
When I arrive on the index :
On my controller :
public function getIndex()
{
$lang = $this->retrieveLang("FR");
$this->layout->content = View::make('cv.cv', array('lang' => $lang));
}
The content extend the layout
#extends('layout.cvlayout')
#section('content')
My ajax function :
<script>
$(".changeLang").click(function(event) {
event.preventDefault();
var url = $(this).attr("href");
$.ajax({
url: url,
cache: false,
beforeSend: function() {
$(".loaderOverlay").fadeIn();
},
success: function(html) {
$("#container").html(html);
$(".loaderOverlay").fadeOut();
pageCvInit();
initAjaxHeadline();
}
});
});
</script>
the url may be ****/fr so in the controller there is a method like that :
public function getFr() {
$lang = $this->retrieveLang("FR");
return View::make('cv.cv', array('lang' => $lang));
}
I tried to put a condition on the
#extends()
#section()
#stop
part, but every time the ajax function is called, the whole body passes by the ajax method (even the , tags) and I just want to reload the body.
How do I do this?
Many thanks
Not sure how you mean by the whole body passes by ajax and you just want to reload the body.
Try changing your on success to filter out the body of the received html.
success: function(html) {
$("#container").html($(html).filter('body').html());
$(".loaderOverlay").fadeOut();
pageCvInit();
initAjaxHeadline();
}
You only need to reload the div you want that see the changes, in success put this:
$("#mydiv").load(location.href + " #mydiv");
I need to pass json data to my Symfony Controller. My ajax function looks like this:
var data = '{"firstname":"John"}';
$.ajax({
type: "POST",
url: save_url, //path to controller action
data: {json:data},
success: function(response) {
// Do something
}
});
In my controller, I try to get my data through:
public function createAction(Request $request) {
$data = $this->getRequest()->get('firstname');
return $this->render('MyBundle:Counter:test.html.twig', array(
'data' => $data
));
Just to see if this works, I send $data to be echoed in a template. In Firebug I can see the data being sent and everything seems to work, but $data is empty and nothing is echoed. Where am I doing this wrong?
EDIT: When I check the response in Fireburg console, I see my data there, in place, but it never appears in the template. var_dump($data) tells that $data is null. So, it seems data is being sent but the controller ignores it.
As Marek noticed:
$this->getRequest()
already returns the request object, you're accessing the request property of the request, that doesn't add up. Either try:
$data = $this->request->get('json');
Or use:
$data = $this->getRequest()->get('json');
You can, of course assign the return value of $this->getRequest() to a variable, and call the get method on that var from there on end... anyway, here's my initial answer, it does contain some more tips, and considerations you may find useful:
You should be able to get the data this way, though AJAX requests + echoing in a template? That does sound a bit strange. I don't see you passing the $data variable to a $this->render call anywhere.
This is a copy-paste bit from a controller action in one of my projects. It works just fine there:
public function indexAction()
{
if (!$this->getRequest()->isXmlHttpRequest())
{//check if request is AJAX request, if not redirect
return $this->redirect(
$this->generateUrl('foo_bar_homepage')//changed this, of course
);
}
$id = $this->getRequest()->get('id',false);//works fine
However, I can't begin to grasp why you're doing this:
var data = '{"firstname":"John"}';
Why not simply go for:
$.ajax({
type: "POST",
url: url,//post how you get this URL please...
data: {firstname: 'John'},//jQ will sort this out for you
success: function(response)
{
console.log(response);
}
error: function()
{
console.log('an error occured');
console.log(arguments);//get debugging!
}
});
Then, in your controller you're able to:
$this->getRequest()->get('firstname');//it should be John
You could even pass {json:{firstname: 'john'}} as the data param to $.ajax, the only difference in your controller will be, that you have to do this:
$data = $this->getRequest()->get('json');
$firstName = $data['firstname'];
That should work just fine, unless there's somthing you're not telling us :)
RECAP:
This is what I'd write:
public function createAction()
{//no Request param in controller
if (!$this->getRequest()->isXmlHttpRequest())
{//no ajax request, no play...
$this->redirect(
$this->generateUrl('homepage_route')
);
}
$data = $this->getRequest()->get('firstname');
//return json response:
return new Response(json_encode(array('dataReceived' => $data));
//return rendered HTML page:
return $this->render('MyBundle:Counter:test.html.twig', array(
'data' => $data
));
}
Of course, then the JS code should read:
$.ajax({
type: "POST",
url: 'route/to/create'
data: {firstname:'John'},
success: function(response)
{
console.log(response);
}
});
I have tested this, and I see no reason why this shouldn't work. It works just fine for me...
Please note this was #EliasVanOotegem original example but there are some obvious steps missing
in the controller i'm reading a few replies as in "I cannot see how this works as i'm getting null" this is because your not correctly keying your object.
i.e.
var data = { name : 'john' };
$.ajax({
type: "POST",
url: url,//post how you get this URL please...
data: {json : data},//jQ will sort this out for you
success: function(response)
{
console.log(response);
}
error: function()
{
console.log('an error occured');
console.log(arguments);//get debugging!
}
});
as you can now see accessing the requerst object like
$request->get('json');
refers to the post key for the json data
Is the content what you're trying to retrieve, neither params nor headers.
Try:
$request->getContent();
In your case $request->request->get('json') should do.