Cakephp3: How can I return json data?

前端 未结 8 3044
不思量自难忘°
不思量自难忘° 2021-02-19 09:39

I am having a ajax post call to a cakePhp Controller:

$.ajax({
                type: \"POST\",
                url: \'locations/add\',
                data: {
           


        
相关标签:
8条回答
  • 2021-02-19 09:51

    there are few things to return JSON response:

    1. load RequestHandler component
    2. set rendering mode as json
    3. set content type
    4. set required data
    5. define _serialize value

    for 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');
                 }
             }
    
    0 讨论(0)
  • 2021-02-19 10:04

    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)); });
    });
    
    0 讨论(0)
  • 2021-02-19 10:05

    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');
    

    More info

    0 讨论(0)
  • 2021-02-19 10:07

    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']);
    }
    

    Edit (credit to @Warren Sergent)

    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;
    

    CakePHP Documentation

    0 讨论(0)
  • 2021-02-19 10:08

    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;
        }
    }
    

    Relevant Documentation

    0 讨论(0)
  • 2021-02-19 10:14

    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));
    
    0 讨论(0)
提交回复
热议问题