在 PHP 中进行 REST PUT

doing a REST PUT in PHP

我希望我的问题能被理解,我的英语不太好。

我几乎是 PHP 的新手,我刚刚发现 REST APIs:我正在尝试使用我的 PHP 脚本中的 REST API。可以找到 API 的文档 here

我的最终目标是从此 Web 服务获取单个产品并通过添加 wholesalePrices 数组对其进行更新。

我已经设法使用 file_get_contents() 执行 GET 请求,以获取我要更新的产品 ID。现在我有了这样的 id 但无法理解如何执行 PUT 请求:据我所知,在 PHP 中主要有两种方法进行 REST 调用:一种是 file_get_contents,另一种是使用卷曲。

因为我对 GET 请求使用了 file_get_contents,所以我继续使用这种方法,但是我的代码:

$wholesalePrices = json_encode($wholesalePrices);
$dataRAW = array(
                  "wholesalePrices" => $wholesalePrices 
                );
$dataToPut = http_build_query($dataRAW);
$context = [
              'http' => [
                          'method' => 'PUT',
                          'header' =>  "Authorization: apikeystring\r\n" . "Content-Length: " . strlen($dataToPut) . "\r\n" . "Content-Type: application/json\r\n",
                          'content' => $dataToPut
                        ]                             
           ];
$context = stream_context_create($context);
$url = "https://app.ecwid.com/api/v3/xxxxxxx/products/".urlencode($productId)."?token=".urlencode(myToken);   
$result = file_get_contents ($url, false, $context);

returns 一个 PHP 警告:

Warning: file_get_contents(https://app.ecwid.com/api/v3/xxxxxxxxx/products/xxxxxxxxx?token=xxxxxxxxxxx): failed to open stream: HTTP request failed! HTTP/1.1 400 Wrong JSON format: A JSONObject text must begin with '{' at 1 [character 2 line 1] in upload.php on line 95

var_dumping $wholesalePrices 就在 json_encode() 结果

之后

string '[{"quantity":1,"price":0},{"quantity":5,"price":6},{"quantity":25,"price":12},{"quantity":100,"price":25}]' (length=106)

我哪里错了?


好的,我尝试使用 RamRaider 方法,现在我的代码是这样的

$data = json_encode(array('wholesalePrices' => $wholesalePrices)/*, JSON_FORCE_OBJECT*/);
          $dataRAW = array(
                            "wholesalePrices" => $wholesalePrices 
                     );      
          $dataToPut = $dataRAW;
          $dataToPut = http_build_query($dataRAW);
$context = array('http' => array('method'    =>  'PUT',
                           'header'    =>  "Authorization: apikeystring\r\nContent-Length: ".strlen($data)."\r\nContent-Type: application/json\r\n",
                           'content'   =>  $data));

          $context = stream_context_create($context);
          $url = "https://app.ecwid.com/api/v3/".urlencode(MY_STORE_ID)."/products/".urlencode($productId)."?token=".urlencode(MY_TOKEN);   
$result = file_get_contents ($url, false, $context);

但我收到一条 HTTP request failed! HTTP/1.1 400 Field Product.wholesalePrices should be an array 消息。 如果我改为评论 , JSON_FORCE_OBJECT,则 HTTP 消息变为 409 Conflict 并引用 $result = file_get_contents ($url, false, $context); 行,所以也许我在正确的轨道上,但我该如何解决此类错误?


好的,做了一些修改:现在 - 在 json_encode() 之后 - 我的 dataToPut(我在 HTTP 请求中放入 "Content")var_dumps 如下(WPPair 是a class 我专门创建来重现所需的格式):

object(stdClass)[3]
  public 'wholesalePrices' => 
    array (size=3)
      1 => 
        object(WPpair)[5]
          public 'quantity' => int 5
          public 'price' => int 6
      2 => 
        object(WPpair)[4]
          public 'quantity' => int 25
          public 'price' => int 12
      3 => 
        object(WPpair)[6]
          public 'quantity' => int 100
          public 'price' => int 25

所以我认为它必须适合 api。但是我仍然收到 HTTP 请求失败! HTTP/1.1 400 错误请求


好的,最后我设法为我的 JSON 形成了一个(也许)正确的结构,更重要的是 Postman 使用 HTTP

验证了我的 dataToPut

200 OK

并且我的测试记录结果已更新。 这是在 json_encode():

之后 dataToPut 上的 print_r() 输出

string '{"id":56782231,"wholesalePrices":[{"quantity":5,"price":5.64},{"quantity":25,"price":5.28},{"quantity":100,"price":4.5}]}' (length=121)

但是,如果我尝试从我的 PHP 页面发送相同的 JSON,我仍然会收到

failed to open stream: HTTP request failed!

事实上,我的记录仍然没有更新。

这是我的代码:

$dataToPut = $dataRAW;
$dataRAW = http_build_query($dataRAW);
$context = [
            'http' => [
                       'method' => 'PUT',
                       'header' =>  "Authorization: apikeystring\r\n" . "Content-Length: ".sizeof($dataToPut)."\r\n" . "Content-Type: application/json\r\n",
                       'content' => $dataToPut
                      ]                             
           ];
$context = stream_context_create($context);
$url = "https://app.ecwid.com/api/v3/xxxxxxx/products/".urlencode($productId)."?token=".urlencode(myToken);
$dataToPut = json_encode($dataToPut);
$result = file_get_contents($url, false, $context); 

这次我哪里错了?


在使用 cURL 而不是 file_get_contents 连接到 API 重写我的代码后,我设法让它工作。 现在 API 调用部分如下所示:

      $dataToPut = $dataRAW;
      $dataRAW = http_build_query($dataRAW);
      $context = [
                    'http' => [
                                'method' => 'PUT',
                                'header' =>  "Authorization: apikeystring\r\n" . "Content-Length: ".sizeof($dataToPut)."\r\n" . "Content-Type: application/json\r\n",
                                'content' => $dataToPut
                              ]                             
                 ];
      $context = stream_context_create($context);


      $url = "https://app.ecwid.com/api/v3/xxxxxxx/products/".urlencode($productId)."?token=".urlencode($myToken);
      $curl = curl_init();
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
      curl_setopt($curl, CURLOPT_HTTPHEADER, array('Host: app.ecwid.com','Content-Type: application/json;charset=utf-8','Cache-Control: no-cache'));
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($curl, CURLOPT_POSTFIELDS, $dataToPut);

      // Make the REST call, returning the result
      $response = curl_exec($curl);
      echo ($response."<br/>");
      if (!$response) {
        echo("Connection Failure: ".curl_error($curl));
        die();
      }
      curl_close($curl);

如果没有看到他们 api 的文档,我可能会让您误入歧途,但错误消息确实表明他们的 api 需要 json 数据,而您对数据进行编码然后添加到一个似乎以某种方式回到前面的数组。

$data = json_encode( array( 'wholesalePrices' => $wholesalePrices  ), JSON_FORCE_OBJECT );

/* Perhaps this also is not required */
#$data = http_build_query( $data );

$context = array(
    'http' => array(
            'method'    =>  'PUT',
            'header'    =>  "Authorization: apikeystring\r\nContent-Length: " . strlen( $data ) . "\r\nContent-Type: application/json\r\n",
            'content'   =>  $data
        )                             
    );

$context = stream_context_create( $context );
$url = "https://app.ecwid.com/api/v3/7560546/products/".urlencode( $productId )."?token=".urlencode( myToken );   
$result = file_get_contents( $url, false, $context );

快速浏览了 api 文档后,我发现了以下内容:

PUT https://app.ecwid.com/api/v3/{storeId}/products/{productId}?token={token}

Request body

A JSON object of type 'Product’ with the following fields:

wholesalePrices -> Array<WholesalePrice>
 described as: "Sorted array of wholesale price tiers (quantity limit and price pairs)"

给定的产品更新请求示例是:

PUT /api/v3/4870020/products/39766764?token=123456789abcd HTTP/1.1
Host: app.ecwid.com
Content-Type: application/json;charset=utf-8
Cache-Control: no-cache

{
  "compareToPrice": 24.99,
  "categoryIds": [
    9691094
  ]
}

所以使用测试数据

        $wholesalePrices=array(
            array('quantity'=>10,'price'=>1000),
            array('quantity'=>2,'price'=>43),
            array('quantity'=>43,'price'=>34),
            array('quantity'=>7,'price'=>5),
            array('quantity'=>9,'price'=>63),
        );
        $data = json_encode( array( 'wholesalePrices' => $wholesalePrices  ) );
        echo '<pre>',$data,'</pre>';

以以下格式提供数据:

{
    "wholesalePrices":[
        {"quantity":10,"price":1000},
        {"quantity":2,"price":43},
        {"quantity":43,"price":34},
        {"quantity":7,"price":5},
        {"quantity":9,"price":63}
    ]
}