¿Cómo puedo usar Guzzle para enviar una solicitud POST en JSON?

180

¿Alguien sabe la forma correcta de postusar JSON Guzzle?

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

Recibo una internal server errorrespuesta del servidor. Funciona usando Chrome Postman.

usuario3379466
fuente
La solicitud parece estar bien ... ¿ha verificado el contenido de $ _POST para asegurarse de que realmente obtiene los valores antes de codificarlos? : var_dump ($ _ POST)
ylerjen
Según los documentos ahora, puedes usar lo que @davykiash dijo 'json' => $data: stackoverflow.com/a/44154428/842768
giovannipds

Respuestas:

262

Para Guzzle 5 y 6 lo haces así:

use GuzzleHttp\Client;

$client = new Client();

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

Docs

Michal Gallovic
fuente
13
Esta es la forma correcta de hacerlo ( ejemplo oficial aquí )
Pierre de LESPINAY
55
Se recomienda usar RequestOptionsconstantes para las teclas de matriz de opciones ( GuzzleHttp\RequestOptions::JSONen este caso): hace que los errores tipográficos sean más fáciles de detectar, ya que de repente se convierten en avisos en lugar de solo errores silenciosos que esperan causar problemas.
ksadowski
77
@MichalGallovic Es lo mismo. El propósito de usar la constante es evitar errores tipográficos. El uso de una constante que no existe generará un error, pero el envío de una opción inútil (como jssonpor ejemplo) no generará ningún error, y puede tomarse un tiempo para encontrar su error tipográfico.
zessx
1
Estuve buscando una hora por esta respuesta. ¿Por qué esto no está en la documentación (especialmente la guía de configuración rápida)? ¡¿¡Loco!?!
Sevenearths
1
@giovannipds GuzzleHttp \ RequestOptions :: JSON es un alias de 'json', o está bien.
Michal Gallovic
44

Para Guzzle <= 4 :

Es una solicitud de publicación sin formato, por lo que poner el JSON en el cuerpo resolvió el problema

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

return $response;
usuario3379466
fuente
8
Esto ya no funciona con GuzzleHttp. @Charlie tiene la respuesta correcta
hbt
Creo que solo necesitamos especificar la versión de Guzzle en la pregunta.
Fabrice Kabongo
1
Si desea establecer el encabezado de tipo de contenido en Guzzle 6, puede hacerlo así:$client->post($url, ['body' => $string, 'headers' => ['Content-type' => 'application/json']]);
marcovtwout
He intentado esto con Guzzle3 no funciona incluso si es la forma mencionada en el documento: guzzle3.readthedocs.io/http-client/… , han pasado 2 días tratando de resolver este problema pero en vano
Hanane
Según los documentos ahora, puedes usar lo que @davykiash dijo 'json' => $data: stackoverflow.com/a/44154428/842768
giovannipds
42

La forma simple y básica (guzzle6):

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

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

Para obtener el código de estado de respuesta y el contenido del cuerpo, hice esto:

echo '<pre>' . var_export($response->getStatusCode(), true) . '</pre>';
echo '<pre>' . var_export($response->getBody()->getContents(), true) . '</pre>';
Frank Roth
fuente
2
Esta es realmente una manera simple y fácil. Resolvió mi problema sobre la configuración del cuerpo y los encabezados. Muchas gracias
Faisal Sarfraz
Esta respuesta funciona para mí cuando la respuesta aceptada no.
vietnguyen09
32

Esto funcionó para mí (usando 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());
davykiash
fuente
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();
CharlieJade
fuente
2
¿Esto también establece el encabezado correcto? Creo que ['json' => $body]es la mejor manera aquí, como lo menciona la respuesta de Michael.
Ja͢ck
1
$res->json();solo funciona en Guzzle 5.3. Se ha eliminado en v6.
David
1
David tiene razón. Esto se debe a la implementación de PSR-7. Usar en su json_decode()lugar.
Andreas
10
$client = new \GuzzleHttp\Client(['base_uri' => 'http://example.com/api']);

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

return $response->getBody();
Yamen Ashraf
fuente
8

Esto funciona para mí con 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 acuerdo con la documentación guzzle hacer el json_encode

arcos.lwm
fuente
7
use GuzzleHttp\Client;

$client = new Client();

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

Ver documentos .

Nurul Huda
fuente
2

Versión de PHP: 5.6

Versión de Symfony: 2.3

Guzzle: 5.0

Recientemente tuve una experiencia acerca de enviar json con Guzzle. Uso Symfony 2.3, por lo que mi versión de Guzzle puede ser un poco más antigua.

También le mostraré cómo usar el modo de depuración y puede ver la solicitud antes de enviarla,

Cuando hice la solicitud como se muestra a continuación, obtuve la respuesta exitosa;

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());
Tuncay Elvanağaç
fuente
0

La respuesta de @ user3379466 se puede hacer funcionar estableciendo $datalo siguiente:

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

Lo que nuestro proyecto necesitaba era insertar una variable en una matriz dentro de la cadena json, lo que hice de la siguiente manera (en caso de que esto ayude a alguien):

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

Entonces con $existing_variableser, digamos, 90210, obtienes:

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

También vale la pena señalar que es posible que también desee establecer el 'Accept' => 'application/json'en caso de que el punto final que está alcanzando se preocupe por ese tipo de cosas.

j boschiero
fuente
Solo un $datajson_encode$data = json_encode(array('collection' => $existing_variable));
aviso
0

@ user3379466 es correcto, pero aquí lo reescribo por completo:

-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('[email protected]', 'password', 'Digest'),)));

$url          = "https://api.yourbaseapiserver.com/incidents.xml";
        
$data = '<incident>
<name>Incident Title2a</name>
<priority>Medium</priority>
<requester><email>[email protected]</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;

--- Solución para * Guzzle 6 * --- -paquete que necesita:

 "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('[email protected]', '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;
Estiércol
fuente
Gracias. No pude encontrar ninguna solución de guzzle3 en ningún otro lugar para proyectos heredados de php5.3, me gustaría ver que también se rompiera la línea como su guzzle6, ya que me habría ahorrado mucho tiempo.
taur
0

Las respuestas anteriores no me funcionaron de alguna manera. Pero esto funciona bien para mí.

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

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

Simplemente use esto, 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();

fuente