简体   繁体   English

Ajax 发送两个空的 arrays 和一个填充的,PHP 只接收一个完整的

[英]Ajax sends two empty arrays and one filled, PHP receives only the full one

I'm completely new to PHP. Working with ajax, php and WordPress I'm sending an object with ajax:我是 PHP 的新手。使用 ajax、php 和 WordPress 我发送 object 和 ajax:

let import_data = {
 action: 'import_data',
 data: {
  first_array: [], // this one is empty
  second_array: [], // this one too
  third_array: [1,2,3] // this one is full
 }
};

I've checked the import_data object many times right before it was sent.在发送之前,我已经多次检查了 import_data object。 The php, however, always receives:然而,php 总是收到:

import_data = {
 action: 'import_data',
 data: {
  third_array: [1,2,3]
 }
}

The question is why is that happening and how can I achieve receiving all arrays, whether they are empty or not, ie问题是为什么会这样,我怎样才能收到所有 arrays,无论它们是否为空,即

import_data = {
 action: 'import_data',
 data: {
  first_array: [],
  second_array: [], 
  third_array: [1,2,3]
 }
}

I need to refactor a lot of code now due to this issue so I'm trying to solve it as easy as possible, but if there is a common known right way to deal with it I'll use it.由于这个问题,我现在需要重构很多代码,所以我试图尽可能简单地解决它,但如果有一个常见的已知正确方法来处理它,我会使用它。 Thanks in advance!提前致谢!

PS In case you wondering, yes, if all arrays being sent are full, php will receive all of them. PS 如果您想知道,是的,如果发送的所有 arrays 都已满,则 php 将全部收到。

UPD In the comments I got I might've wanted to add contentType or json.strngify my data. UPD在我收到的评论中,我可能想添加 contentType 或 json.strngify 我的数据。 It didn't help, but I might do it wrong, so I'll try to partly show my code below:它没有帮助,但我可能做错了,所以我会尝试在下面部分展示我的代码:

var import_data = {
     action: 'start_import',
     sliced_batch: {
        rows_to_add: [],
        rows_to_delete: [],
        rows_to_update: [1,2,3,4,5,...]
     }
};
    

function ajax_call(import_data) {
// ... processes

 jQuery.ajax({
            url: start_import_ajax.url, // url from php file
            type: 'POST',
            contentType: "text; charset=utf-8", // sending string with cyrillic (ukrainian lng)
            dataType: 'application/json', // want  to recieve json
            data: JSON.stringify(import_data), 
            success: function(response) { 
               // ... processes import_data ...
               if(it is the end of data) return;
               else ajax_call(import_data);
            },
            error: function(e) {
              // here is where I end up
            }

}

PHP side is now pretty shy, as I just made a pause and wanted to see my data in console: PHP 这边现在很害羞,因为我暂停了一下,想在控制台中查看我的数据:

function start_import_callback() {
   
    echo json_decode($_POST);
    echo $_POST;
    echo json_decode($_POST['sliced_batch']);
    echo $_POST['sliced_batch'];

 
    wp_die();
}

I've tried all echo 's one by one, but always saw:我已经一一尝试了所有echo ,但总是看到:

{
    "readyState": 4,
    "responseText": "0",
    "status": 400,
    "statusText": "error"
}

When NOT stringifying and NOT specifying contentType/dataType it returns:当不进行字符串化并且不指定 contentType/dataType 时,它返回:

{
             action: 'import_data',
     sliced_batch: {
    rows_to_update:
            {
                "ID": "00000006125",
                "CatalogueNumber": "bla, bla",
                "Category": "bla, bla",
                "Manufacturer": "bla",
                "Nomenclature": "blablablablabla",
                "NomenclatureUkrainian": "bla",
                "StockStatus": "instock",
                "Price": "2 315",
                "Parent": "blabla",
                "Sorting": "99"
            },
            {},...
        ]
    }
}

So, rows_to_delete: [] and rows_to_add: [] are missing...所以, rows_to_delete: [] 和 rows_to_add: [] 丢失了......

You are using jQuery dataType options wrong!您使用的 jQuery dataType选项错误!
The dataType: value should be 'json' not 'application/json' because your value will request with HTTP accept: */* but if you use 'json' it will be accept: application/json . dataType:值应该是'json'而不是'application/json'因为您的值将请求 HTTP accept: */*但如果您使用'json'它将是accept: application/json

Option 1选项1

Use content type application/json .使用内容类型application/json

The contentType: should be 'application/json' or 'application/json;charset=utf-8' . contentType:应该是'application/json''application/json;charset=utf-8'

By this content type you will be now able to receive POST data in JSON but you cannot access them with $_POST because the data is not valid application/x-www-form-urlencoded .通过这种内容类型,您现在可以在 JSON 中接收 POST 数据,但您无法使用$_POST访问它们,因为数据不是有效application/x-www-form-urlencoded

Full code for client side:客户端的完整代码:

var import_data = {
     action: 'start_import',
     sliced_batch: {
        rows_to_add: [],
        rows_to_delete: [],
        rows_to_update: [1,2,3,4,5]
     }
};

function ajax_call(import_data) {
    // ... processes

    jQuery.ajax({
        url: 'test.php', // url from php file
        type: 'POST',
        contentType: "application/json;charset=utf-8", // sending string with cyrillic (ukrainian lng)
        dataType: 'json', // want  to recieve json
        data: JSON.stringify(import_data), 
        success: function(response) { 
           // ... processes import_data ...
           
        },
        error: function(e) {
          // here is where I end up
        }

    });
}

Code for PHP: PHP 的代码:

$data = json_decode(file_get_contents('php://input'), true);
// use $data['sliced_batch'] to access `rows_to_add`, `rows_to_delete` etc.

Option 2选项 2

Use content type application/x-www-form-urlencoded .使用内容类型application/x-www-form-urlencoded

With this content type, you will be able to access $_POST properly.使用此内容类型,您将能够正确访问$_POST

However, to use this request content type in header, the jQuery itself will be modify the value if it is empty jQuery will be just delete it,!但是,要在header中使用这个请求内容类型,jQuery本身会被修改值,如果它是空的jQuery将被删除,! So, you need to JSON string only sliced_batch property.所以,你需要 JSON 字符串只有sliced_batch属性。

Here is the JS code:这是JS代码:

var import_data = {
     action: 'start_import',
     sliced_batch: {
        rows_to_add: [],
        rows_to_delete: [],
        rows_to_update: [1,2,3,4,5]
     }
};

function ajax_call(import_data) {
    // ... processes

    // modify `sliced_batch` property to be JSON string to prevent jQuery remove empty properties.
    import_data.sliced_batch = JSON.stringify(import_data.sliced_batch);

    jQuery.ajax({
        url: 'test.php', // url from php file
        type: 'POST',
        // just remove contentType option. It is no need.
        //contentType: "application/json;charset=utf-8", // sending string with cyrillic (ukrainian lng)
        dataType: 'json', // want  to recieve json
        data: import_data, 
        success: function(response) { 
           // ... processes import_data ...
           
        },
        error: function(e) {
          // here is where I end up
        }

    });
}

PHP: PHP:

$sliced_batch = ($_POST['sliced_batch'] ?? '');
$sliced_batch = json_decode($sliced_batch, true);
// you can now access $sliced_batch['rows_to_add'], etc...

So, thanks once again to @vee for his explanation, but here's one more thing I'd like to share as it was crucial to get everything to work.因此,再次感谢@vee 的解释,但我还想分享一件事,因为让一切正常工作至关重要。
First , for json_decode method the JS object keys should be double -quoted, ie NOT首先,对于 json_decode 方法,JS object 键应该引号引起来,即 NOT

$bad_json = '{ bar: "baz" }';
json_decode($bad_json); // null

or或者

$bad_json = '{ 'bar': "baz" }';
json_decode($bad_json); // null

BUT

$bad_json = '{ "bar": "baz" }';
json_decode($bad_json); // array("bar" => "baz")

Second and most important!第二也是最重要的! When dealing with WordPress it sets its own rules and shows focuses, Depending on what answer you'd like to get, you may want to use function wp_unslash() .在处理 WordPress 时,它会设置自己的规则并显示焦点,根据您想要获得的答案,您可能需要使用 function wp_unslash() Looking at the stringified data in console I saw somth like this:查看控制台中的字符串化数据,我看到了这样的内容:

"\u0421\u0435\u0440\u0432\u0435\u0440: \u0424\u0430\u0439\u043b\u0456\u0432 av_imp_p_WEB.csv \u0456 av_imp_p_WEB_previous.csv \u043d\u0435 \u0431\u0443\u043b\u043e \u0432\u0438\u044f\u0432\u043b\u0435\u043d\u043e. \u041f\u043e\u0447\u0438\u043d\u0430\u044e \u0456\u043c\u043f\u043e\u0440\u0442 \u0432\u0441\u044c\u043e\u0433\u043e 
// it is more common for contentType: "application/x-www-form-urlencoded"

It is the dirty work of WooCommerce (as I read from another's people opinion) and it hinders parsing it the right way, so my full code is: JS这是 WooCommerce 的肮脏工作(正如我从其他人的意见中读到的)并且它阻碍了以正确的方式解析它,所以我的完整代码是:JS

 var import_data = {
          "action": "start_import",
           "sliced_batch": {
           "rows_to_add": my_data1,
           "rows_to_delete": my_data2,
           "rows_to_update": my_data3
            }
};

function ajax_call(import_data) {
 // ... processes
jQuery.ajax({ // ajax to php to save the file to uploads and move it to the plugin's folder
            url: start_import_ajax.url, // url from php file
            type: 'POST',
            //contentType: "application/json;charset=utf-8", //  what you send
            dataType: 'JSON', // what you would like as a response
            data: {
                "action": import_data.action,
                "sliced_batch": JSON.stringify(import_data.sliced_batch)
            },
                success: function(response) {
                    //response = JSON.parse(response); // if you'd like to console.log  what you've sent
                     console.log(response);
                 }
....

PHP PHP

 $sliced_batch = wp_unslash($_POST['sliced_batch']);
    $sliced_batch = json_decode($sliced_batch, true);

    $result = start_import($sliced_batch);

    if($result == 0) {
        echo json_encode(["status" => 0]);
    } else echo json_encode(["status" => 1]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM