在PHP中进行REST PUT

时间:2015-11-11 11:57:37

标签: php json rest file-get-contents put

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

我几乎不熟悉PHP,我刚刚发现了REST API:我尝试使用PHP脚本中的REST API。可以找到API的文档here

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

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

由于我使用file_get_contents作为我的GET请求,我继续这种方法,但是我的代码:

$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);

返回PHP警告:

  

警告:file_get_contents(https://app.ecwid.com/api/v3/xxxxxxxxx/products/xxxxxxxxx?token=xxxxxxxxxxx):无法打开流:HTTP请求失败! HTTP / 1.1 400错误的JSON格式:JSONObject文本必须以' {'在第95行的upload.php中的1 [字符2第1行]

var_dumping $ wholesalePrices就在json_encode()导致

之后
  

字符串' [{"数量":1,"价格":0},{"数量":5,"价格& #34;:6},{"量":25,"价格":12},{"量":100,"价格&#34 ; 25}]' (长度= 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);行,所以也许我在正确的轨道上,但我该如何解决此类错误?< / p>

好的,做了一些mods:现在 - 在json_encode()之后 - 我的dataToPut(我把它放在&#34; Content&#34;在HTTP请求中)var_dumps如下(WPPair是我专门创建的类来重现所需格式):

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()输出:

  

的字符串   &#39; {&#34; ID&#34;:56782231,&#34; wholesalePrices&#34;:[{&#34;量&#34;:5,&#34;价格&#34;:5.64}, {&#34;量&#34;:25,&#34;价格&#34;:5.28},{&#34;量&#34;:100,&#34;价格&#34;:4.5}]}& #39;   (长度= 121)

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

  

无法打开流:HTTP请求失败!

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

这是我的代码:

$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);

1 个答案:

答案 0 :(得分:1)

如果没有看到他们的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}

     

请求正文

     

“Product”类型的JSON对象,包含以下字段:

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