¿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.


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


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;

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>';

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

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
¿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();

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


7
use GuzzleHttp\Client;

$client = new Client();

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

Ver documentos .


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

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.


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('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;

--- 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('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;

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']));

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();
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.