Como posso usar o Guzzle para enviar uma solicitação POST em JSON?


180

Alguém sabe a maneira correta de postusar o JSON Guzzle?

$request = $this->client->post(self::URL_REGISTER,array(
                'content-type' => 'application/json'
        ),array(json_encode($_POST)));

Eu recebo uma internal server errorresposta do servidor. Funciona usando o Chrome Postman.


A solicitação parece ok ... você verificou o conteúdo de $ _POST para ter certeza de que realmente obtém os valores antes de codificá-los? : var_dump ($ _ POST)
ylerjen

De acordo com docs agora, você pode simplesmente usar o que @davykiash disse 'json' => $data: stackoverflow.com/a/44154428/842768
giovannipds

Respostas:


262

Para o Guzzle 5 e 6, você faz assim:

use GuzzleHttp\Client;

$client = new Client();

$response = $client->post('url', [
    GuzzleHttp\RequestOptions::JSON => ['foo' => 'bar'] // or 'json' => [...]
]);

Documentos


13
Este é o caminho certo para fazer ( exemplo oficial aqui )
Pierre de LESPINAY

5
É recomendável usar RequestOptionsconstantes para as chaves do array de opções ( GuzzleHttp\RequestOptions::JSONneste caso) - isso facilita a detecção de erros de digitação, pois de repente eles se tornam avisos em vez de apenas bugs silenciosos esperando para causar problemas.
ksadowski

7
@MichalGallovic É o mesmo. O objetivo de usar a constante é evitar erros de digitação. O uso de uma constante que não existe gera um erro, mas o envio de uma opção inútil (como jssonpor exemplo) não gera nenhum erro, e você pode levar algum tempo para encontrar seu erro de digitação.
Zessx

1
Eu estava procurando por uma hora por esta resposta. Por que isso não está na documentação (especialmente no guia de configuração rápida)? Louco!?!
Sevenearths 13/03/19

1
@giovannipds GuzzleHttp \ RequestOptions :: JSON é um alias para 'json', também é bom.
Michal Gallovic

44

Para Guzzle <= 4 :

É uma solicitação de postagem bruta, portanto, colocar o JSON no corpo resolveu o problema

$request = $this->client->post($url,array(
                'content-type' => 'application/json'
        ),array());
$request->setBody($data); #set body!
$response = $request->send();

return $response;

8
Isso não funciona mais com o GuzzleHttp. @Charlie tem a resposta certa
hbt

Acho que precisamos apenas especificar a versão do Guzzle na pergunta.
precisa saber é o seguinte

1
Se você quiser definir o cabeçalho tipo de conteúdo em Guzzle 6, você pode fazê-lo como este:$client->post($url, ['body' => $string, 'headers' => ['Content-type' => 'application/json']]);
marcovtwout

Eu tentei isso com o Guzzle3 não está funcionando, mesmo que seja da maneira mencionada no documento: guzzle3.readthedocs.io/http-client/… , faz dois dias que estou tentando resolver esse pb, mas em vão
Hanane

De acordo com docs agora, você pode simplesmente usar o que @davykiash disse 'json' => $data: stackoverflow.com/a/44154428/842768
giovannipds

42

A maneira simples e básica (guzzle6):

$client = new Client([
    'headers' => [ 'Content-Type' => 'application/json' ]
]);

$response = $client->post('http://api.com/CheckItOutNow',
    ['body' => json_encode(
        [
            'hello' => 'World'
        ]
    )]
);

Para obter o código de status da resposta e o conteúdo do corpo, fiz isso:

echo '<pre>' . var_export($response->getStatusCode(), true) . '</pre>';
echo '<pre>' . var_export($response->getBody()->getContents(), true) . '</pre>';

2
Esta é realmente uma maneira simples e fácil. Resolvi meu problema sobre como definir corpo e cabeçalhos. Muito obrigado
Faisal Sarfraz

Esta resposta funciona para mim quando a resposta aceita não.
vietnguyen09

32

Isso funcionou para mim (usando o Guzzle 6)

$client = new Client(); 
$result = $client->post('http://api.example.com', [
            'json' => [
                'value_1' => 'number1',
                'Value_group' =>  
                             array("value_2" => "number2",
                                    "value_3" => "number3")
                    ]
                ]);

echo($result->getBody()->getContents());

25
$client = new \GuzzleHttp\Client();

$body['grant_type'] = "client_credentials";
$body['client_id'] = $this->client_id;
$body['client_secret'] = $this->client_secret;

$res = $client->post($url, [ 'body' => json_encode($body) ]);

$code = $res->getStatusCode();
$result = $res->json();

2
Isso também define o cabeçalho correto? Eu acho que ['json' => $body]é o melhor caminho aqui, como mencionado pela resposta de Michael.
Ja͢ck 16/06

1
$res->json();só funciona no Guzzle 5.3. Foi removido na v6.
David

1
Davi está correto. Isso ocorre devido à implementação do PSR-7. Use em json_decode()vez disso.
Andreas

10
$client = new \GuzzleHttp\Client(['base_uri' => 'http://example.com/api']);

$response = $client->post('/save', [
    'json' => [
        'name' => 'John Doe'
    ]
]);

return $response->getBody();

8

Isso funciona para mim com o Guzzle 6.2:

$gClient =  new \GuzzleHttp\Client(['base_uri' => 'www.foo.bar']);
$res = $gClient->post('ws/endpoint',
                            array(
                                'headers'=>array('Content-Type'=>'application/json'),
                                'json'=>array('someData'=>'xxxxx','moreData'=>'zzzzzzz')
                                )
                    );

De acordo com a documentação, guzzle faça o json_encode


7
use GuzzleHttp\Client;

$client = new Client();

$response = $client->post('url', [
    'json' => ['foo' => 'bar']
]);

Veja Documentos .


2

Versão Php: 5.6

Versão Symfony: 2.3

Guzzle: 5.0

Recentemente, tive uma experiência sobre o envio de json com o Guzzle. Eu uso o Symfony 2.3 para que minha versão do guzzle possa ser um pouco mais antiga.

Também mostrarei como usar o modo de depuração e você poderá ver a solicitação antes de enviá-la,

Quando fiz o pedido, como mostrado abaixo, obtive a resposta bem-sucedida;

use GuzzleHttp\Client;

$headers = [
        'Authorization' => 'Bearer ' . $token,        
        'Accept'        => 'application/json',
        "Content-Type"  => "application/json"
    ];        

    $body = json_encode($requestBody);

    $client = new Client();    

    $client->setDefaultOption('headers', $headers);
    $client->setDefaultOption('verify', false);
    $client->setDefaultOption('debug', true);

    $response = $client->post($endPoint, array('body'=> $body));

    dump($response->getBody()->getContents());

0

A resposta de @ user3379466 pode ser configurada da $dataseguinte maneira:

$data = "{'some_key' : 'some_value'}";

O que nosso projeto precisava era inserir uma variável em uma matriz dentro da string json, que fiz da seguinte maneira (caso isso ajude alguém):

$data = "{\"collection\" : [$existing_variable]}";

Assim $existing_variablesendo, digamos, 90210, você obtém:

echo $data;
//{"collection" : [90210]}

Também digno de nota é que você também pode definir o 'Accept' => 'application/json'caso, caso o terminal que você está atingindo se importe com esse tipo de coisa.


Apenas um heads-up ... você pode simplificar o seu $datausando json_encode:$data = json_encode(array('collection' => $existing_variable));
phpisuber01 30/10

0

@ user3379466 está correto, mas aqui reescrevo na íntegra:

-package that you need:

 "require": {
    "php"  : ">=5.3.9",
    "guzzlehttp/guzzle": "^3.8"
},

-php code (Digest is a type so pick different type if you need to, i have to include api server for authentication in this paragraph, some does not need to authenticate. If you use json you will need to replace any text 'xml' with 'json' and the data below should be a json string too):

$client = new Client('https://api.yourbaseapiserver.com/incidents.xml', array('version' => 'v1.3', 'request.options' => array('headers' => array('Accept' => 'application/vnd.yourbaseapiserver.v1.1+xml', 'Content-Type' => 'text/xml'), 'auth' => array('username@gmail.com', 'password', 'Digest'),)));

$url          = "https://api.yourbaseapiserver.com/incidents.xml";
        
$data = '<incident>
<name>Incident Title2a</name>
<priority>Medium</priority>
<requester><email>dsss@mail.ca</email></requester>
<description>description2a</description>
</incident>';

    $request = $client->post($url, array('content-type' => 'application/xml',));

    $request->setBody($data); #set body! this is body of request object and not a body field in the header section so don't be confused.

    $response = $request->send(); #you must do send() method!
    echo $response->getBody(); #you should see the response body from the server on success
    die;

--- Solução para o * Guzzle 6 * --- -package que você precisa:

 "require": {
    "php"  : ">=5.5.0",
    "guzzlehttp/guzzle": "~6.0"
},

$client = new Client([
                             // Base URI is used with relative requests
                             'base_uri' => 'https://api.compay.com/',
                             // You can set any number of default request options.
                             'timeout'  => 3.0,
                             'auth'     => array('you@gmail.ca', 'dsfddfdfpassword', 'Digest'),
                             'headers' => array('Accept'        => 'application/vnd.comay.v1.1+xml',
                                                'Content-Type'  => 'text/xml'),
                         ]);

$url = "https://api.compay.com/cases.xml";
    $data string variable is defined same as above.


    // Provide the body as a string.
    $r = $client->request('POST', $url, [
        'body' => $data
    ]);

    echo $r->getBody();
    die;

Obrigado. Não foi possível encontrar nenhuma solução guzzle3 em nenhum outro lugar para projetos herdados do php5.3, gostaria de vê-la com quebra de linha, como o seu guzzle6 também, pois isso me pouparia muito tempo.
taur 10/07

0

As respostas acima não funcionaram para mim de alguma forma. Mas isso funciona bem para mim.

 $client = new Client('' . $appUrl['scheme'] . '://' . $appUrl['host'] . '' . $appUrl['path']);

 $request = $client->post($base_url, array('content-type' => 'application/json'), json_encode($appUrl['query']));

0

Basta usar isso funcionará

   $auth = base64_encode('user:'.config('mailchimp.api_key'));
    //API URL
    $urll = "https://".config('mailchimp.data_center').".api.mailchimp.com/3.0/batches";
    //API authentication Header
    $headers = array(
        'Accept'     => 'application/json',
        'Authorization' => 'Basic '.$auth
    );
    $client = new Client();
    $req_Memeber = new Request('POST', $urll, $headers, $userlist);
    // promise
    $promise = $client->sendAsync($req_Memeber)->then(function ($res){
            echo "Synched";
        });
      $promise->wait();
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.