Reputation: 1987
I am having a ajax post call to a cakePhp Controller:
$.ajax({
type: "POST",
url: 'locations/add',
data: {
abbreviation: $(jqInputs[0]).val(),
description: $(jqInputs[1]).val()
},
success: function (response) {
if(response.status === "success") {
// do something with response.message or whatever other data on success
console.log('success');
} else if(response.status === "error") {
// do something with response.message or whatever other data on error
console.log('error');
}
}
});
When I try this I get the following error message:
Controller actions can only return Cake\Network\Response or null.
Within the AppController I have this
$this->loadComponent('RequestHandler');
enabled.
the Controller function looks like this:
public function add()
{
$this->autoRender = false; // avoid to render view
$location = $this->Locations->newEntity();
if ($this->request->is('post')) {
$location = $this->Locations->patchEntity($location, $this->request->data);
if ($this->Locations->save($location)) {
//$this->Flash->success(__('The location has been saved.'));
//return $this->redirect(['action' => 'index']);
return json_encode(array('result' => 'success'));
} else {
//$this->Flash->error(__('The location could not be saved. Please, try again.'));
return json_encode(array('result' => 'error'));
}
}
$this->set(compact('location'));
$this->set('_serialize', ['location']);
}
What do I miss here? Is there any additional settings needed?
Upvotes: 14
Views: 31395
Reputation: 4540
Though I'm not a CakePHP Guru, in my case i'm using cake > 4 and I need some results by ajax call. For this, from my controller i wrote,
echo json_encode(Dashboard::recentDealers()); die;
and in my JS file i just need to parse the data using
JSON.parse(data)
The ajax call like
$.get('/recent-dealers', function (data, status) {
console.log (JSON.parse(data)); });
});
Upvotes: 0
Reputation: 2219
As of cakePHP 4.x.x the following should work assuming that your controller and routes are set as shown below: controller: <your_project_name>/src/Controller/StudentsController.php
public function index()
{
$students = $this->Students->find('all');
$this->set(compact('students'));
$this->viewBuilder()->setOption('serialize',['students']);
}
Routes: <your_project_name>/config/routes.php
<?php
use Cake\Routing\Route\DashedRoute;
use Cake\Routing\RouteBuilder;
/** @var \Cake\Routing\RouteBuilder $routes */
$routes->setRouteClass(DashedRoute::class);
$routes->scope('/', function (RouteBuilder $builder) {
$builder->setExtensions(['json']);
$builder->resources('Students');
$builder->fallbacks();
});
Run bin/cake server and visit http://localhost:8765/students.json using postman/insomnia or just the normal browser. See further documentation for setting up Restful controllers and Restful Routing
Don't forget to set the method to GET on postman and insomnia.
Upvotes: 0
Reputation: 5276
Most answers I've seen here are either outdated, overloaded with unnecessary information, or rely on withBody()
, which feels workaround-ish and not a CakePHP way.
Here's what worked for me instead:
$my_results = ['foo'=>'bar'];
$this->set([
'my_response' => $my_results,
'_serialize' => 'my_response',
]);
$this->RequestHandler->renderAs($this, 'json');
More info on RequestHandler
. Seemingly it's not getting deprecated anytime soon.
UPDATE: CakePHP 4
$this->set(['my_response' => $my_results]);
$this->viewBuilder()->setOption('serialize', true);
$this->RequestHandler->renderAs($this, 'json');
Upvotes: 21
Reputation: 1774
Instead of returning the json_encode result, set the response body with that result and return it back.
public function add()
{
$this->autoRender = false; // avoid to render view
$location = $this->Locations->newEntity();
if ($this->request->is('post')) {
$location = $this->Locations->patchEntity($location, $this->request->data);
if ($this->Locations->save($location)) {
//$this->Flash->success(__('The location has been saved.'));
//return $this->redirect(['action' => 'index']);
$resultJ = json_encode(array('result' => 'success'));
$this->response->type('json');
$this->response->body($resultJ);
return $this->response;
} else {
//$this->Flash->error(__('The location could not be saved. Please, try again.'));
$resultJ = json_encode(array('result' => 'error', 'errors' => $location->errors()));
$this->response->type('json');
$this->response->body($resultJ);
return $this->response;
}
}
$this->set(compact('location'));
$this->set('_serialize', ['location']);
}
Since CakePHP 3.4, we should use
return $this->response->withType("application/json")->withStringBody(json_encode($result));
Instead of :
$this->response->type('json');
$this->response->body($resultJ);
return $this->response;
Upvotes: 22
Reputation:
In the latest version of CakePHP $this->response->type()
and $this->response->body()
are deprecated.
Instead you should use $this->response->withType()
and $this->response->withStringBody()
E.g:
(this was pinched from the accepted answer)
if ($this->request->is('post')) {
$location = $this->Locations->patchEntity($location, $this->request->data);
if ($this->Locations->save($location)) {
//$this->Flash->success(__('The location has been saved.'));
//return $this->redirect(['action' => 'index']);
$resultJ = json_encode(array('result' => 'success'));
$this->response = $this->response
->withType('application/json') // Here
->withStringBody($resultJ) // and here
return $this->response;
}
}
Upvotes: 2
Reputation: 2688
RequestHandler is not required to send json. In controller's action:
$this->viewBuilder()->setClassName('Json');
$result = ['result' => $success ? 'success' : 'error'];
$this->set($result);
$this->set('_serialize', array_keys($result));
Upvotes: 0
Reputation: 4765
When you return JSON data you need to define the data type and response body information like below:
$cardInformation = json_encode($cardData);
$this->response->type('json');
$this->response->body($cardInformation);
return $this->response;
In you case just change this return json_encode(array('result' => 'success'));
line with below code:
$responseResult = json_encode(array('result' => 'success'));
$this->response->type('json');
$this->response->body($responseResult);
return $this->response;
Upvotes: 0
Reputation: 3234
there are few things to return JSON
response:
RequestHandler
componentjson
_serialize
valuefor example you can move first 3 steps to some method in parent controller class:
protected function setJsonResponse(){
$this->loadComponent('RequestHandler');
$this->RequestHandler->renderAs($this, 'json');
$this->response->type('application/json');
}
later in your controller you should call that method, and set required data;
if ($this->request->is('post')) {
$location = $this->Locations->patchEntity($location, $this->request->data);
$success = $this->Locations->save($location);
$result = [ 'result' => $success ? 'success' : 'error' ];
$this->setJsonResponse();
$this->set(['result' => $result, '_serialize' => 'result']);
}
also it looks like you should also check for request->is('ajax)
; I'm not sure about returning json
in case of GET
request, so setJsonResponse
method is called within if-post
block;
in your ajax-call success handler you should check result
field value:
success: function (response) {
if(response.result == "success") {
console.log('success');
}
else if(response.result === "error") {
console.log('error');
}
}
Upvotes: 8