I am trying to make an API request in the following format:
/api/v1/courses?enrollment_state=active&include[]=total_students&include[]=term
How can I do so using the HttpClient Component query string parameters?
$response = $client->request('GET', '/api/v1/courses', [
'query' => [
'enrollment_state' => 'active',
'include[]' => 'term',
'include[]' => 'total_students',
],
]);
As the above approach does not work due to duplicate array key?
I have also tried:
'include[]' => ['term', 'total_students']
To create the equivalent to:
https://www.example.com/?token=foo&abc[]=one&abc[]=two
Just do:
$client->request(
'GET',
'https://www.example.com/',
[
'query' => [
'token' => 'foo',
'abc' => ['one', 'two']
]
]
);
as #user1392897 says, #yivi snippet returns indexes in the url query string.
https://www.example.com/?foo[0]=bar&foo[1]=baz
That's because it use the http_build_query built in function and it's the function behaviour. You can read this thread php url query nested array with no index about it.
A workaround it to build the query string yourself from the array and append it to your url, the the 2nd parameter of the HttpClient->request() method.
function createQueryString(array $queryArray = []): ?string
{
$queryString = http_build_query($queryArray, '', '&', \PHP_QUERY_RFC3986);
$queryString = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '%5B%5D=', $queryString); //foo[]=x&foo[]=y
return '' !== $queryString ? $queryString : null;
}
$queryArray = [
'abc' => ['one', 'two']
];
$queryString = createQueryString($queryArray);
$url = 'https://www.example.com/';
if (is_string($queryString)) {
$url = sprintf('%s?%s', $url, $queryString);
}
$response = $client->request('GET', $url);
Related
how are you ?
I'm using Guzzle to send post method but when i tried to send the post method with variable getting error so i tried to convert it to sting but still same
this is my current code
if $ mobile value is 55454545445 , them the 'numbers' => "{$mobile}" will be different not "55454545445"
$user = Auth::user();
$mobile = $user->mobile;
$client = new Client();
$booking = Booking::where('id', '=', e($id))->first();
if($booking)
{
$booking->booking_status_id = 3;
$booking->save();
$client = new Client([
'headers' => [ 'Content-Type' => 'application/json' ]
]);
$data = array('userName' => "test",
'apiKey' => "1",
'numbers' => "{$mobile}",
'userSender' => "sender",
'msg' =>'msg',
'msgEncoding' => "UTF8",);
$dataJson = json_encode($data);
$response = $client->post('https://www.test.test',
['body' => $dataJson]
);
i used this
"0{$mobile}"
instead of
"{$mobile}"
and its work
I have created a function that contacts a remote API using Guzzle but I cannot get it to return all of the data available.
I call the function here:
$arr = array(
'skip' => 0,
'take' => 1000,
);
$sims = api_request('sims', $arr);
And here is the function, where I have tried the following in my $response variable
json_decode($x->getBody(), true)
json_decode($x->getBody()->getContents(), true)
But neither has shown any more records. It returns 10 records, and I know there are over 51 available that it should be returning.
use GuzzleHttp\Client;
function api_request($url, $vars = array(), $type = 'GET') {
$username = '***';
$password = '***';
//use GuzzleHttp\Client;
$client = new Client([
'auth' => [$username, $password],
]);
$auth_header = 'Basic '.$username.':'.$password;
$headers = ['Authorization' => $auth_header, 'Content-Type' => 'application/json'];
$json_data = json_encode($vars);
$end_point = 'https://simportal-api.azurewebsites.net/api/v1/';
try {
$x = $client->request($type, $end_point.$url, ['headers' => $headers, 'body' => $json_data]);
$response = array(
'success' => true,
'response' => // SEE ABOVE //
);
} catch (GuzzleHttp\Exception\ClientException $e) {
$response = array(
'success' => false,
'errors' => json_decode($e->getResponse()->getBody(true)),
);
}
return $response;
}
By reading the documentation on https://simportal-api.azurewebsites.net/Help/Api/GET-api-v1-sims_search_skip_take I assume that the server is not accepting your parameters in the body of that GET request and assuming the default of 10, as it is normal in many applications, get requests tend to only use query string parameters.
In that function I'd try to change it in order to send a body in case of a POST/PUT/PATCH request, and a "query" without json_encode in case of a GET/DELETE request. Example from guzzle documentation:
$client->request('GET', 'http://httpbin.org', [
'query' => ['foo' => 'bar']
]);
Source: https://docs.guzzlephp.org/en/stable/quickstart.html#query-string-parameters
My data_array like this :
Array (
[0] => 1
[1] => 2
[2] => 3 )
My code like this :
public function test(Request $request)
{
$client = new GuzzleHttpClient();
...
$concat_data = implode(',', $data_array);
$result = $client->request('POST', $url, [
'headers'=>[
'content-type'=>'application/json',
'Authorization'=> 'Bearer '.auth()->user()->api_token
],
'json'=>['ids'=>[$concat_data]]
]);
$content = json_decode($result->getBody()->getContents());
}
If the code is executed, it does not work perfectly. It just updates the data with id = 1
But, if I try with static data like this :
public function test(Request $request)
{
$client = new GuzzleHttpClient();
...
$concat_data = implode(',', $data_array);
$result = $client->request('POST', $url, [
'headers'=>[
'content-type'=>'application/json',
'Authorization'=> 'Bearer '.auth()->user()->api_token
],
'json'=>['ids'=>[1,2,3]]
]);
$content = json_decode($result->getBody()->getContents());
}
It works. It success updates the data with id = 1, id = 2, and id = 3
It seems my way of storing implode results in an array is still wrong
How can I solve this problem?
Note
If the code executed, it will update value of ids
implode converts an array to a string, whereas from your working static version, it looks like the API accepts a raw array. You're sending it the string "1,2,3", which it doesn't understand.
You should be able to just use
'json' => ['ids' => $data_array]
and skip the implode call entirely.
Migrating from 5 to 6, and I've run into a snag and can't find the relevant docs.
Guzzle docs here, http://guzzle.readthedocs.io/en/latest/quickstart.html#creating-a-client, site that we can add "any number of default request options".
I want to send "foo=bar" with every request. E.g.:
$client = new Client([
'base_uri' => 'http://google.com',
]);
$client->get('this/that.json', [
'query' => [ 'a' => 'b' ],
]);
This will generate GET on http://google.com/this/that.json?a=b
How do I modify the client construction so that it yields:
http://google.com/this/that.json?foo=bar&a=b
Thanks for your help!
Alright, so far, this works here:
$extraParams = [
'a' => $config['a'],
'b' => $config['b'],
];
$handler = HandlerStack::create();
$handler->push(Middleware::mapRequest(function (RequestInterface $request) use ($extraParams) {
$uri = $request->getUri();
$uri .= ( $uri ? '&' : '' );
$uri .= http_build_query( $extraParams );
return new Request(
$request->getMethod(),
$uri,
$request->getHeaders(),
$request->getBody(),
$request->getProtocolVersion()
);
}));
$this->client = new Client([
'base_uri' => $url,
'handler' => $handler,
'exceptions' => false,
]);
If anyone knows how to make it less sinister-looking, I would say thank you!
I found a nice solution here.
Basically, anything defined in the first array of arguments, become part of the config for the client.
this means you can do this when initialising:
$client = new Client([
'base_uri' => 'http://google.com',
// can be called anything but defaults works well
'defaults' => [
'query' => [
'foo' => 'bar',
]
]
]);
Then, when using the client:
$options = [
'query' => [
'nonDefault' => 'baz',
]
];
// merge non default options with default ones
$options = array_merge_recursive($options, $client->getConfig('defaults'));
$guzzleResponse = $client->get('this/that.json', $options);
It's woth noting that the array_merge_recursive function appends to nested arrays rather than overwrites. If you plan on changing a default value, you'll need a different utility function. It works nicely when the default values are immutable though.
A "less sinister-looking" example based on the answer by #Saeven and the comment from #VladimirPak.
$query_defaults = [
'a' => $config['a'],
'b' => $config['b'],
];
$handler = \GuzzleHttp\HandlerStack::create();
$handler->push(\GuzzleHttp\Middleware::mapRequest(function (\Psr\Http\Message\RequestInterface $request) use ($query_defaults) {
$query = \GuzzleHttp\Psr7\Query::parse($request->getUri()->getQuery());
$query = array_merge($query_defaults, $query);
return $request->withUri($request->getUri()->withQuery(\GuzzleHttp\Psr7\Query::build($query)));
}));
$this->client = new \GuzzleHttp\Client([
'base_uri' => $url,
'handler' => $handler,
'exceptions' => false,
]);
I'm not sure how less sinister-looking it is though. lol
the solution proposed in github looks pretty ugly. This does not look much better, but at least is more readable and also works. I'd like feedback if anyone knows why should not be used:
$query = $uri . '/person/id?personid=' . $personid . '&name=' . $name;
return $result = $this->client->get(
$query
)
->getBody()->getContents();
Guzzle client creates by default from this code
$client->get('https://example.com/{?a}', array('a' => array('c','d')));
this url
https://example.com/?a=c,d
What is the best practice to send array in query string in RESTful application? The question is, how can I determine on the server side whether c,d is a string or an array? Isn't it better to send arrays using square brackets, e.g. a[]=c&a[]=d? How can I set Guzzle to use square brackets? Or it is better to use JSON encoded variables? On the server side I'm using Tonic.
Working Solution:
$vars = array('state[]' => array('Assigned','New'), 'per_page' => $perPage, 'page' => $pageNumber);
$query = http_build_query($vars, null, '&');
$string = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', $query); // state[]=Assigned&state[]=New
$client = new Client([follow instruction to initialize your client ....]);
$response = $client->request('GET', $uri, ['query' => $string]);
Now you have same name parameters in your request.
Dung.
Source: http_build_query with same name parameters
It seems the answer is here.
I wanted to do something like ?status[]=first&status[]=second
You can do this in Guzzle like shown in the link above:
$client = new Client('http://test.com/api');
$request = $client->get('/resource');
$query = $request->getQuery();
$query->set('status', array('first', 'second'));
Guzzle has a helper function you can use called build_query(). This uses PHP's http_build_query().
Here's an example of how to use it:
$params = [
'a[]' => [
'c',
'd'
],
'page' => 1
];
$query = \GuzzleHttp\Psr7\build_query($params);
$response = $client->request('GET', 'https://example.com/', [
'query' => $query
]);
I'm not 100% sure this quite answers the question. But I found the question while looking for how to construct complex queries using Guzzle and none of the answers here were the solution I ended up using. I'm adding it here in case it's ever useful for any other devs.
Using Guzzle 6, you can do this type of request:
$endPoint = "https://example.com";
$queryParams = [
'a' => [
[
"b" => "c"
]
]
];
$options = [
'debug' => true, // so you can see what the request looks like
'query' => $queryParams
];
$client->request('GET', $endPoint, $options);
As a real world example, query params like this:
$queryParams = [
'filters' => [
[
"field" => "status",
"value" => "open",
"operator" => "equal"
],
[
"field" => "total",
"operator" => "greater_than",
"value" => 50
],
],
'limit' => 500,
'start' => 7
];
produce a url like this:
https://example.com?filters=[{"field":"status","operator":"equal","value":"open"},{"field":"total","operator":"less_than","value":50}]&limit=500&start=7
The point being that the query key of the $options array, seems very powerful. I'd recommend having a play with that before going down the route of writing complex regular expressions.
$query = array('x' => array(
'a',
'b',
'c'
));
$query_string = http_build_query($query, null, '&'); //build query string
$query_string = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '[]=', $query_string); //x[]=a&x[]=b
$response = $guzzle->client->get($path, array('query' => $query_string)); //Make guzzle request
return json_decode($response->getBody()->getContents()); //Return JSON decoded array
This is how you can process x with array of values in guzzle, tested with version 6 or later