php - jQuery ajax 调用无法从 CakePHP 3.8 读取 json 编码数据(获取空数组)

标签 php json ajax jquery-3 cakephp-3.8

我在读取 CakePHP3 API 响应来自 jQuery 的 ajax 调用返回的 json 编码数据时遇到了一个奇怪的问题。我已经阅读了超过 20 篇关于 stackoverflow 和其他地方的帖子,以及人们遇到的常见问题,因为错误的 dataType、contentType 或者服务器没有从 ajax 获取数据。这些情况都不适用于这里(我尝试了不同的设置,但对我的问题没有影响)。

问题:

我的 ajax 调用将一些参数发送到我的 CakePHP3 API,该 API 正确获取参数并返回 CakePHP 实体的 json 编码数组(每个实体在发送回 ajax 调用之前添加了一个附加属性“available_yield”)。我在浏览器中使用直接 URL 获得正确的输出(使用 json 验证器检查它,一切都很好),但我的 ajax 调用(我使用 Chrome devtools 中的控制台和网络选项卡进行调查)显示一个空数组,用于格式良好的json。

我的调查显示问题发生在我修改 CakePHP 实体时。如果我从 API json 编码返回原始数据,jquery ajax 将获得正确的数据。但是当我修改任何实体时,jquery ajax 中的数组为空。

从 CakePHP 调试显示,除​​了添加的属性外,两个数组(未修改和已修改)看起来完全相同,即它们格式良好并且在所有方面都可以,两者都是 json,在浏览器中都可以。但是修改后的一个不被 jquery 接受为 json。

目前的解决方案似乎是:不要修改您的数据!但这就是我们在将相关和处理过的数据发送到客户端之前在服务器上所做的,不是吗?

有没有人遇到过类似的问题?

我附上我的代码:

CakePHP API 函数:

function myFunction(){
$params = $this->getRequest()->getQueryParams();
        //debug($params);
        $componentReference = $params['component_reference'];
        $componentTypeId = $params['component_type_id'];

        $matchingCrops = $this->Crops->find()->select(['id', 'grower_name', 'bulk'])->where(['reference' => $componentReference]);

        $cropsWithYieldInfo = []; //to hold modify crop
        foreach($matchingCrops as $crop){
            $availableYield = $this->Crops->calculateAvailableYield($crop->id); //returns a string
            if(isset($availableYield) && !empty($availableYield)){
                $crop->available_yield = number_format($availableYield,1);  //tried $crop['available_yield'] as well, same result
                $cropsWithYieldInfo[] = $crop;
            }
        }

//        debug($cropsWithYieldInfo);
//        debug($matchingCrops);

        //$content = json_encode($cropsWithYieldInfo);  // <<-- changing to $matchingCrops makes ajax see the array, but the array does not have my calculated data
        $content = json_encode($matchingCrops);

        $this->response = $this->response->withStringBody($content);
        $this->response = $this->response->withType('json');  
        $this->autoRender = false; 
        return $this->response;
} 

我的 AJAX:
function myAjax(){
 $.ajax({
                type: 'GET',
                url: url,
                //contentType: "application/json",
                dataType: "json"
            })
            .done(function (data) {
                console.log(data);  
            })
            .fail(function (data) {
                console.log('AJAX call to /'+errMsg+' function failed');
            })
}

API 返回的 JSON 数据:

编辑:
可能很重要:
当我通过浏览器中的 URL 访问 API 时,它总是返回修改后的数据;看起来我的代码修改了 $matchingCrops 集中的实际实体。因此,如果将 $content 设置为 $matchingCrops 或 $cropsWithYieldInfo,则浏览器中的结果始终相同。但是当通过 ajax 访问 API 时它有所不同:当 $content = json_encoded($matchingCrops) 时我得到原始未修改的数据数组,当 $content = json_encoded($cropsWithYieldInfo) 时我得到一个空数组。

这真的很奇怪:为什么浏览器总是得到修改后的数组,而 ajax 得到一个或另一个???我知道如果我修改 $crop 实体,那么它会修改结果集中的实体,但我希望这对于浏览器和 ajax 调用都是一致的。

编辑:
我尝试了一个稍微修改的代码,看看克隆实体是否会产生任何不同,但唯一的区别是现在浏览器得到了我期望发生的(原始未修改的数组,或修改后的数组)并且它与 ajax 得到的一致.但这并不能解决问题(如果数组被修改,ajax 仍然会得到空数组)。
foreach($matchingCrops as $crop){
            $modCrop = clone $crop;
            $availableYield = $this->Crops->calculateAvailableYield($crop->id); //returns a string
            if(isset($availableYield) && !empty($availableYield)){
                $modCrop->available_yield = number_format($availableYield,1);  //tried $crop['available_yield'] as well, same result
                $cropsWithYieldInfo[] = $modCrop;
            }
        }

修改(ajax 将其作为空数组获取;浏览器始终从 API 获取):
[{"id":12345,"grower_name":"XYZ","bulk":false,"available_yield":"4.1"},{"id":23456,"grower_name":null,"bulk":true,"available_yield":"190.0"}]


未修改(ajax 正确获取):
[{"id":12345,"grower_name":"XYZ","bulk":false},{"id":23456,"grower_name":null,"bulk":true}]

最佳答案

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

$this->set([
    'response' => $array,
    '_serialize' => 'response',
]);
$this->Request->renderAs($this, 'json');

比我会 seriliaze ajax !因此,您不需要对对象进行字符串化,您可以直接将其用于数据属性。
$.ajax({
    type: 'POST',
    url: url,                      
    data: {YourArray: YourVariables},
    success: function(data) {
      alert(data);
    }
});

您可以在这里找到更多信息:https://api.jquery.com/serialize/

让我们看看你的 ajax,你需要将数组中的值传递给 ajax 以获得你想要做的每个值的响应 +errMsg+ .

你的 ajax 在失败和成功时应该是这样的:

失败:function( jqXHR, Status, errMsg) {那么你可以显示类似 console.log('AJAX call to /'+errMsg+' function failed'); 的回复
$.ajax({
    type: "GET",
    url: url,
    data: {
      title: $(value[0]).val(),
      description: $(value[1]).val()
    },
    success: function (data) {
        if(data === "success") {
            // do something with data or whatever other data on success
            console.log('success');
        } else if(data === "error") {
            // do something with data or whatever other data on error
            console.log('error');
        }
    }
});

要显示指定的错误,您需要传递 title = $(value[0]).val()在成功函数中。

或者使用ajax serializeArray()each()这里的例子https://www.w3schools.com/jquery/tryit.asp?filename=tryjquery_ajax_serializearray

从 CakePHP 3.4 开始,使用应该使用
$content = json_encode($matchingCrops);
return $this->response->withType("application/json")->withStringBody($content);

而不是这个
$content = json_encode($matchingCrops);

$this->response = $this->response->withStringBody($content);
$this->response = $this->response->withType('json');  
$this->autoRender = false; 
return $this->response;

关于php - jQuery ajax 调用无法从 CakePHP 3.8 读取 json 编码数据(获取空数组),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60100831/

相关文章:

php - 使用 php 处理 mysql 错误的正确方法是什么?

php - onclick 将元素类传递给 javascript

javascript - 通过 javascript 将 json 对象发送到 python Web 服务

json - 如何在 Play Framework 模板中对列表进行排序?

javascript - 通过 Ajax 加载内容时,WORDPRESS 音频播放器未加载,MediaElement.js 未应用

javascript - 在 Ruby on Rails 中旋转图像,类似于 AJAX

javascript - AJAX 在第一个表单之后不处理表单

PHP返回对其他类中数组的引用

php - 使用 CodeIgniter 和 MySQL 从数据库获取数据时出现错误

php - 以 HTML 或 JSON 格式加载 ajax 数据?