Cakephp3:如何返回json数据?

jfgube3f  于 2022-11-12  发布在  PHP
关注(0)|答案(8)|浏览(179)

我有一个 AJAX 后调用到一个cakePhp控制器:

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

当我尝试这样做时,我得到以下错误消息:
控制器操作只能返回Cake\Network\Response或空值。
在AppController中,我有以下内容

$this->loadComponent('RequestHandler');

已启用。
控制器函数如下所示:

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

我错过了什么?是否需要任何额外的设置?

t98cgbkg

t98cgbkg1#

不要返回json_encode结果,而是使用该结果设置响应主体并将其返回。

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

编辑(署名:@沃伦·塞金特)

从CakePHP 3.4开始,我们应该使用

return $this->response->withType("application/json")->withStringBody(json_encode($result));

而不是:

$this->response->type('json');
$this->response->body($resultJ);
return $this->response;

CakePHP文档

az31mfrm

az31mfrm2#

我在这里看到的大多数答案要么是过时的,要么是不必要的信息过多,要么是依赖于withBody(),这让人感觉像是在变通,而不是CakePHP的方式。
以下是对我有效的方法:

$my_results = ['foo'=>'bar'];

$this->set([
    'my_response' => $my_results,
    '_serialize' => 'my_response',
]);
$this->RequestHandler->renderAs($this, 'json');

更多关于RequestHandler的信息。看起来它不会很快被弃用。

更新:蛋糕PHP 4

$this->set(['my_response' => $my_results]);
$this->viewBuilder()->setOption('serialize', true);
$this->RequestHandler->renderAs($this, 'json');

More info

9wbgstp7

9wbgstp73#

返回JSON响应的内容很少:
1.加载RequestHandler组件
1.将渲染模式设置为json
1.设置内容类型
1.设置所需数据
1.定义_serialize
例如,您可以将前3个步骤移至父控制器类中的某个方法:

protected function setJsonResponse(){
    $this->loadComponent('RequestHandler');
    $this->RequestHandler->renderAs($this, 'json');
    $this->response->type('application/json');
}

稍后在你的控制器中你应该调用这个方法,并设置所需的数据;

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

而且,看起来您还应该检查request->is('ajax);我不确定在GET请求的情况下是否返回json,因此在if-post块内调用setJsonResponse方法;
在ajax-call成功处理程序中,您应该检查result字段值:

success: function (response) {
             if(response.result == "success") {
                 console.log('success');
             } 
             else if(response.result === "error") {
                    console.log('error');
             }
         }
2ekbmq32

2ekbmq324#

在最新版本的CakePHP中,不赞成使用$this->response->type()$this->response->body()
而应使用$this->response->withType()$this->response->withStringBody()

例如:

(* 这是从已接受的答案中截取的 *)

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

相关文件

3phpmpom

3phpmpom5#

返回JSON数据时,需要定义数据类型和响应主体信息,如下所示:

$cardInformation = json_encode($cardData);
$this->response->type('json');
$this->response->body($cardInformation);
return $this->response;

在您的情况下,只需使用以下代码更改return json_encode(array('result' => 'success'));行:

$responseResult = json_encode(array('result' => 'success'));
$this->response->type('json');
$this->response->body($responseResult);
return $this->response;
bfnvny8b

bfnvny8b6#

发送json不需要RequestHandler。在控制器的操作中:

$this->viewBuilder()->setClassName('Json');
$result = ['result' => $success ? 'success' : 'error'];
$this->set($result);
$this->set('_serialize', array_keys($result));
k4emjkb1

k4emjkb17#

从cakePHP 4.x.x开始,假设您的控制器和路由设置如下所示,下面的代码应该可以正常工作:控制器:<your_project_name>/src/控制器/学生控制器.php

public function index()
    {
        $students = $this->Students->find('all');
        $this->set(compact('students'));
        $this->viewBuilder()->setOption('serialize',['students']);
    }

路径:<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();
});

运行bin/cake server并使用postman/unmomery或普通浏览器访问http://localhost:8765/students.json。有关设置Restful控制器和Restful路由的详细信息,请参阅相关文档
别忘了在 Postman 和失眠症上将方法设置为GET

nkcskrwz

nkcskrwz8#

虽然我不是一个CakePHP大师,在我的情况下,我使用cake〉4,我需要通过 AJAX 调用的一些结果.为此,从我的控制器我写,
echo json_encode( Jmeter 盘::最近交易商());死亡;
在我的JS文件中,我只需要使用
解析(数据)
AJAX 的呼叫像

$.get('/recent-dealers', function (data, status) {
   console.log (JSON.parse(data)); });
});

相关问题