首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >jQuery ajax调用无法从CakePHP 3.8中读取json编码的数据(获取一个空数组)

jQuery ajax调用无法从CakePHP 3.8中读取json编码的数据(获取一个空数组)
EN

Stack Overflow用户
提问于 2020-02-06 17:46:55
回答 2查看 674关注 0票数 1

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

问题:

ajax调用向我的ajax API发送一些参数,API正确地获取参数并返回CakePHP实体的json编码数组(每个实体在被发送回ajax调用之前有一个附加属性'available_yield‘)。我使用浏览器中的直接URL获得正确的输出(使用json验证器检查它,这一切都很好),但是我的ajax调用(我在Chrome中使用控制台和网络选项卡来调查)显示了一个格式良好的json的空数组。

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

来自CakePHP的调试表明,除了添加的属性之外,两个数组(未经修改和修改)看起来完全相同,即它们在所有方面都是良好的和OK的,都是json中的,在浏览器中都是OK的。但jquery不接受修改后的json。

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

有人有类似的问题吗?

我附上我的代码:

CakePHP API函数:

代码语言:javascript
运行
复制
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;
} 

my AJAX:

代码语言:javascript
运行
复制
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仍然会得到空数组)。

代码语言:javascript
运行
复制
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以空数组的形式获得;browser总是从API中获得):

代码语言:javascript
运行
复制
[{"id":12345,"grower_name":"XYZ","bulk":false,"available_yield":"4.1"},{"id":23456,"grower_name":null,"bulk":true,"available_yield":"190.0"}]

未修改(ajax正确地实现了这一点):

代码语言:javascript
运行
复制
[{"id":12345,"grower_name":"XYZ","bulk":false},{"id":23456,"grower_name":null,"bulk":true}]
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-02-07 12:31:27

OMG...found!好吧,这很尴尬,但我还是会把它作为一个教训,并作为对其他人的警告:,如果你在晚上遇到了无法解决的问题,回家好好睡一觉,早上再开始吧!

问题的原因:

1)我的计算函数实际上是返回一个浮点数,而不是字符串,而且我是在检查空值,所以当它返回0时,代码没有将'available_yield‘属性添加到$crop实体中(因为负责这一点的代码行也在错误的位置!)应该在if块之外)

在这一点上,我仍然是‘好的,但我应该得到一致的行为,无论在浏览器和ajax调用!’,除非.

2)我没有注意到我在浏览器检查和ajax调用中使用了不同的id,因此计算机是正确的.:/

总是学习..。

重新检查每一行并调试所有可能的vars!

  • double-check您的测试数据!

工作正常的代码的版本:

代码语言:javascript
运行
复制
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
        $cropsWithYieldString = '';
        foreach($matchingCrops as $crop){
            $availableYield = $this->Crops->calculateAvailableYield($crop->id); //returns a float not string! 
            if(isset($availableYield)){ //<<- that was the cause of the problem; !empty(float) will ignore 0, just check if it's set
                $crop->available_yield = number_format($availableYield,1); 
            }
            $cropsWithYieldInfo[] = $crop;
        }

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

        $content = json_encode($cropsWithYieldInfo); 

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

}

谢谢你们的时间,你们让我全神贯注于寻找解决方案。

票数 0
EN

Stack Overflow用户

发布于 2020-02-07 12:34:53

代码语言:javascript
运行
复制
$array = ['foo'=>'bar'];

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

比我更喜欢阿贾克斯!因此,您不需要对对象进行字符串化,您可以直接将它用于数据属性。

代码语言:javascript
运行
复制
$.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');那样显示响应

代码语言:javascript
运行
复制
$.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以来,use应该使用

代码语言:javascript
运行
复制
$content = json_encode($matchingCrops);
return $this->response->withType("application/json")->withStringBody($content);

而不是这个

代码语言:javascript
运行
复制
$content = json_encode($matchingCrops);

$this->response = $this->response->withStringBody($content);
$this->response = $this->response->withType('json');  
$this->autoRender = false; 
return $this->response;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60100831

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档