Symfony DomCrawler is not outputing anything - php

This is the code I am using
$client = new Client();
$requests = [
$client->createRequest('GET', 'http://httpbin.org'),
$client->createRequest('GET', 'http://httpbin.org')
];
$options = [
'complete' => [
[
'fn' => function (CompleteEvent $event) {
$crawler = new Crawler('GET', $event->getRequest()->getUrl());
echo '<p>'.$crawler->filter('title')->text().'</p>';
},
'priority' => 0,
'once' => false
]
]
];
$pool = new Pool($client, $requests, $options);
$pool->wait();
It gives no error but it outputs nothing either. I have tried replacing the URLs but still I get no output.

Your primary issue with the code sample is the instantiation of your Symfony\Component\DomCrawler\Crawler object. As currently written, "GET" is the sole content of $crawler; as a result the call to $crawler->filter() returns an instance of Symfony\Component\DomCrawler\Crawler that contains an empty DOMNodeList. This is why your output is empty.
Replace:
$crawler = new Crawler('GET', $event->getRequest()->getUrl());
with:
$crawler = new Crawler(null, $event->getRequest()->getUrl());
$crawler->addContent(
$event->getResponse()->getBody(),
$event->getResponse()->getHeader('Content-Type')
);

Related

Getting the specific part of a JSON

I have an API and I use that API to get the exchange rates.
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://v6.exchangerate-api.com/v6/3307b104e7b3be179b55050e/latest/USD');
$currency = $res->getBody();
I want to get the conversion_rates data only from the JSON and ignore the rest.
I use Laravel.
might work
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', 'https://v6.exchangerate-api.com/v6/3307b104e7b3be179b55050e/latest/USD');
$data = $res->getBody()->getContents();
$dataArray = json_decode($data, true);
$rates = $dataArray['conversion_rates'] ?? [];
You need $res->json()['conversion_rates']
Calling it from tinker (just to test):
Http::withOptions(['verify' => false])
->get('https://v6.exchangerate-api.com/v6/3307b104e7b3be179b55050e/latest/USD')
->json()['conversion_rates'];
it gives back
=> [
"USD" => 1,
"AED" => 3.6725,
"AFN" => 104.838,
"ALL" => 106.8525,
"AMD" => 482.8513,
...
]
Final solution, based on your editing:
$response = Http::withOptions(['verify' => false])
->get('https://v6.exchangerate-api.com/v6/3307b104e7b3be179b55050e/latest/USD');
$conversion_rates = $response->json()['conversion_rates'];

How to pass Guzzle Mock Handler to a PHP class to test an API call that has json response

I have a php class that uses guzzle to call an API and get a response:
public function getResponseToken()
{
$response = $this->myGUzzleClient->request(
'POST',
'/token.php,
[
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded'
],
'form_params' => [
'username' => $this->params['username'],
'password' => $this->params['password'],
]
]
);
return json_decode($response->getBody()->getContents())->token;
}
I am trying to test this method using guzzle mock handler, this is what I have done so far but not working:
public function testGetResponseToken()
{
$token = 'stringtoken12345stringtoken12345stringtoken12345';
$mockHandler = new MockHandler([
new Response(200, ['X-Foo' => 'Bar'], $token)
]
);
$handlerStack = HandlerStack::create($mockHandler);
$client = new Client(['handler' => $handlerStack]);
$myService = new MyService(
new Logger('testLogger'),
$client,
$this->config
);
$this->assertEquals($token, $myService->getResponseToken());
}
the error I am getting says "Trying to get property of non-object", so looks to me MyService is not using the handler to make the call. What am I doing wrong?
The class works as expected outside of the test context. Also note the client in normally injected in MyService from service.yml (I am using symfony).
Your handler work fine, you just mock the wrong response data. You should make the response as raw json.
Try
$token = 'stringtoken12345stringtoken12345stringtoken12345';
$mockHandler = new MockHandler(
[
new Response(200, ['X-Foo' => 'Bar'], \json_encode([ 'token' => $token ]))
]
);
Now it should be works

API response returns JSON without Response Body

Using Guzzle, I'm consuming some external apis in JSON format,
usually I get the data with
$data = $request->getBody()->getContents();
But i can't get data from this different api.
It seems the data doesn't come in a 'Response Body'.
This api call works:
https://i.ibb.co/80Yk6dx/Screenshot-2.png
This doesn't work:
https://i.ibb.co/C239ghy/Screenshot-3.png
public function getRemoteCienciaVitaeDistinctions()
{
$client = new Client(['headers' => ['Accept' => 'application/json']]);
$request = $client->get(
'https://................/',
[
'auth' => ['...', '...'],
]
);
$data = $request->getBody()->getContents();
return $data;
}
the second call is working fine, but the response is empty,
as we can see in Screenshot-3, the Total = 0, so the response from this API is empty.
to handle that properly I suggest you this modification for your method :
public function getRemoteCienciaVitaeDistinctions()
{
$client = new Client(['headers' => ['Accept' => 'application/json']]);
$request = $client->get(
'https://................/',
[
'auth' => ['...', '...'],
]
);
//Notice that i have decoded the response from json objects to php array here.
$response = json_decode($request->getBody()->getContents());
if(isset($response->total) && $response->total == 0) return [];
return $response;
}
please check the documentation of the API that you are using

Guzzle not behaving like CURL

I want to migrate from pure CURL to Guzzle, but the API calls are not being registered correctly.
Working CURL (Class from here: https://stackoverflow.com/a/7716768/8461611)
...
$Curl = new CURL(); // setting all curl_opts there
// creating session
$session = explode(";", $Curl->post("http://www.share-online.biz/upv3_session.php", "username=".$un."&password=".$pw));
$session_key = $session[0];
$upload_server = $session[1];
// upload
$vars = ... // see below
var_dump(explode(";",$Curl->post($upload_server, $vars))); // works
Now the Guzzle stuff
...
$Curl = new GuzzleHttp\Client();
$jar = new GuzzleHttp\Cookie\FileCookieJar("cookie.txt", true);
//creating session
$session = explode(";", $Curl->request('POST', "http://www.share-online.biz/upv3_session.php",
["form_params" => ["username" => $un, "password" => $pw], 'cookies' => $jar])->getBody());
$session_key = $session[0];
$upload_server = $session[1];
$vars = ["username" => $un,
"password" => $pw,
"upload_session" => $session_key,
"chunk_no" => 1,
"chunk_number" => 1,
"filesize" => filesize($file),
"fn" => new CurlFile(realpath($file)),
"finalize" => 1,
"name" => "test",
"contents" => $file,
];
var_dump(
explode(";",$Curl->request(
'POST', "http://".$upload_server, ["multipart" => [$vars], 'cookies' => $jar])
->getBody()));
// outputs *** EXCEPTION session creation/reuse failed - 09-3-2017, 3:05 am ***
I assume I'm doing something wrong with cookies. They are being set as var_dump($jar); shows. API Docs : http://www.share-online.biz/uploadapi
First of all, Guzzle is not curl and cannot behave like curl. The only caveat is that it uses curl behind the scenes.
Here is the solution:
use GuzzleHttp\Client;
$client = new Client([
// Base URI is used with relative requests
'base_uri' => 'http://www.share-online.biz/',
'timeout' => 2.0,
]);
$response = $client->request('POST', 'upv3_session.php',
[
'form_params' => [
"username" => $un,
"password" => $pw
]
]
);
Use the output of your request like so:
$code = $response->getStatusCode(); // 200 || 400 | 500 etc
$reason = $response->getReasonPhrase();
$body = $response->getBody();
$response = $request->getBody(); //Explicitly cast to string.
$json_response = json_decode($response); //here the string response has be decoded to json string.
I hope it helps others that facing this situation
First of all, you have to call ...->getBody()->getContents() to get a string. Or cast body object to a string: (string) ...->getBody().
Then, you cannot use CurlFile class. Use fopen() to get a file handle and pass it directly to Guzzle like in the docs. Pay attentions that for file uploads you have to use multipart instead of form_params.

Laravel - Class 'App\Http\Controllers\Object' not found

I am currently trying to figure out why I get this error:
FatalThrowableError: Class 'App\Http\Controllers\Object' not found in Operators.php line 23
This is the Operators.php controller from where the error is coming from:
public function getOperatorData()
{
$api = new Client([
'base_uri' => 'https://www.space-track.org',
'cookies' => true,
]); $api->post('ajaxauth/login', [
'form_params' => [
'identity' => '#',
'password' => '#',
],
]);
$response = $api->get('basicspacedata/query/class/satcat/orderby/INTLDES%20desc/limit/1/metadata/false');
$mydata = json_decode($response->getBody()->getContents());
$object = new Object();
$object->intldes = $mydata->INTLDES;
$object->satname = $mydata->SATNAME;
$object->save();
return view('pages/satellite-database', compact('object'));
}
The specific line from where the error comes from is:
$object = new Object();
The line shown above should be creating a new model for querying`in a blade file later on.
I am usually able to solve these (either I forgot the 'use' or something), but I have been unable to solve this error.
Turns out the problem lay in the $mydata = json_decode($response->getBody()->getContents());.
Once I changed $mydata to return, I managed to make the JSON format properly and get the $object array to work.

Categories