Как я могу использовать Guzzle для отправки запроса POST в JSON?

180

Кто-нибудь знает правильный способ postиспользования JSON Guzzle?

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

Я получаю internal server errorответ от сервера. Работает с использованием Chrome Postman.

user3379466
источник
Запрос выглядит нормально ... Вы проверили содержимое $ _POST, чтобы убедиться, что вы действительно получили значения перед их кодированием? : var_dump ($ _ POST)
ylerjen
Согласно документам, вы можете просто использовать то, что сказал @davykiash 'json' => $data: stackoverflow.com/a/44154428/842768
giovannipds

Ответы:

262

Для Guzzle 5, 6 и 7 вы делаете это так:

use GuzzleHttp\Client;

$client = new Client();

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

Документы

Михал Галлович
источник
13
Это правильный способ сделать ( официальный пример здесь )
Пьер де Леспин
5
Рекомендуется использовать RequestOptionsконстанты для ключей массива параметров ( GuzzleHttp\RequestOptions::JSONв данном случае) - это облегчает обнаружение опечаток, поскольку они внезапно становятся уведомлениями, а не просто незаметными ошибками, ожидающими проблем.
ksadowski
7
@MichalGallovic Это то же самое. Цель использования константы - избежать опечаток. Использование несуществующей константы вызовет ошибку, но отправка бесполезной опции (как, jssonнапример) не вызовет никакой ошибки, и вам может потребоваться некоторое время, чтобы найти опечатку.
Zessx
1
Я искал ответ в течение часа. Почему этого нет в документации (особенно в руководстве по быстрой установке)? Псих!?!
Семь Земель
1
@giovannipds GuzzleHttp \ RequestOptions :: JSON является псевдонимом 'json', либо в порядке.
Михал Галлович
44

Для Жрала <= 4 :

Это необработанный почтовый запрос, так что размещение JSON в теле решило проблему

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

return $response;
user3379466
источник
8
Это больше не работает с GuzzleHttp. У @Charlie правильный ответ
hbt
Я думаю, что нам просто нужно указать версию Guzzle в вопросе.
Фабрис
1
Если вы хотите установить заголовок типа контента в Guzzle 6, вы можете сделать это следующим образом:$client->post($url, ['body' => $string, 'headers' => ['Content-type' => 'application/json']]);
marcovtwout
Я пробовал это с Guzzle3 не работает, даже если это путь, упомянутый в документе: guzzle3.readthedocs.io/http-client/… , это было 2 дня, я пытаюсь решить этот pb, но тщетно
Ханане
Согласно документам, вы можете просто использовать то, что сказал @davykiash 'json' => $data: stackoverflow.com/a/44154428/842768
giovannipds
42

Простой и базовый способ (guzzle6):

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

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

Чтобы получить код статуса ответа и содержание тела, я сделал это:

echo '<pre>' . var_export($response->getStatusCode(), true) . '</pre>';
echo '<pre>' . var_export($response->getBody()->getContents(), true) . '</pre>';
Фрэнк Рот
источник
2
Это действительно один простой и легкий способ. Решил мою проблему с настройкой тела и заголовков. Большое спасибо
Фейсал
Этот ответ работает для меня, когда принятый ответ не работает.
vietnguyen09
32

Это сработало для меня (используя 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
источник
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
источник
2
Это также устанавливает правильный заголовок? Я думаю ['json' => $body], что здесь лучше, как уже упоминалось в ответе Майкла.
Ja Junck
1
$res->json();работает только в Guzzle 5.3. Это было удалено в v6.
Дэвид
1
Дэвид прав. Это из-за реализации PSR-7. Используйте json_decode()вместо этого.
Андреас
10
$client = new \GuzzleHttp\Client(['base_uri' => 'http://example.com/api']);

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

return $response->getBody();
Ямен Ашраф
источник
8

Это работает для меня с 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')
                                )
                    );

Согласно документации жрет делать код json_encode

arcos.lwm
источник
7
use GuzzleHttp\Client;

$client = new Client();

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

Смотрите Документы .

Нурул Худа
источник
2

Версия Php: 5.6

Версия Symfony: 2.3

Жрать: 5.0

Недавно у меня был опыт отправки json с Guzzle. Я использую Symfony 2.3, поэтому моя жаровня может быть немного старше.

Я также покажу, как использовать режим отладки, и вы можете увидеть запрос перед его отправкой,

Когда я сделал запрос, как показано ниже, получил успешный ответ;

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ç
источник
0

Ответ от @ user3379466 можно заставить работать $dataследующим образом:

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

Нашему проекту нужно было вставить переменную в массив внутри строки json, что я сделал следующим образом (на случай, если это кому-нибудь поможет):

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

Так $existing_variableчто, скажем, 90210, вы получите:

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

Также стоит отметить, что вы также можете установить и этот параметр 'Accept' => 'application/json'на тот случай, если конечная точка, к которой вы обращаетесь, заботится о подобных вещах.

J Boschiero
источник
Просто на голову ... вы можете упростить свой $data, используя json_encode:$data = json_encode(array('collection' => $existing_variable));
phpisuber01
0

@ user3379466 правильно, но здесь я переписываю полностью:

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

--- Решение для * Guzzle 6 * --- пакета, который вам нужен:

 "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;
помет
источник
Спасибо. Не смог найти нигде решения guzzle3 для устаревших проектов php5.3, хотел бы видеть, что перенос строки понравился бы и вашему guzzle6, поскольку это сэкономило бы мне много времени.
Тавр
0

Приведенные выше ответы у меня не сработали как-то. Но это прекрасно работает для меня.

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

 $request = $client->post($base_url, array('content-type' => 'application/json'), json_encode($appUrl['query']));
Сураджа
источник
0

Просто используйте это, это будет работать

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

источник