Laravel - How to pass variable as parameter to external API using guzzle - laravel

I am using Laravel-5.8 and Guzzle to consume an external api:
public function index()
{
try{
$myparam = 'JKK123';
$client = new Client();
$res = $client->request('GET','https://examplet/tracking/$myparam', [
'query' => ['key' => 'jkkffd091']
])->getBody();
$geoLocation = json_decode($res->getContents(), true);
$currentLocation = collect($geoLocation)->sortByDesc(function ($data) {
return Carbon::parse($data['Timestamp'])->format('d-m-Y h:i:s');
})->first();
$currentLocationFilter = explode(',', $currentLocation['current_asset_position_coord'] ?? '');
dd($currentLocationFilter);
return view('index', [
'currentLocation' => $currentLocation,
'currentLocationFilter' => $currentLocationFilter,
'geoLocation' => $geoLocation
]);
}catch (Exception $exception) {
Log::error($exception);
return back();
}
}
I am trying to pass the variable as parameter to the API. I didn't put it directly because it changes. I just tried to test.
When I did this as shown in the code above
$res = $client->request('GET','https://examplet/tracking/$myparam', [ ...
and then
dd($currentLocationFilter);
I got:
array:1 [▼
0 => ""
]
But when I put the value directly,
$res = $client->request('GET','https://examplet/tracking/JKK123', [
I got the required result:
array:2 [▼
0 => "2.1234565432145"
1 => "1.7864321249555"
]
How do I paa the variable as parameter into the external API?
Thanks

Use double quotes for executing variable like this:
$res = $client->request('GET',"https://examplet/tracking/{$myparam}", [...

Related

Type error: Too few arguments to function Illuminate\Mail\Mailer::__construct(), 0 passed - Laravel 5.5

I keep getting while trying to use the mailer
FatalThrowableError in Mailer.php line 93:
Type error: Too few arguments to function Illuminate\Mail\Mailer::__construct(), 0 passed in /var/www/app/app/Services/SendOtpMail.php on line 42 and at least 2 expected
in Mailer.php line 93
at Mailer->__construct() in SendOtpMail.php line 42
at SendOtpMail->send('test#company.com', array('from' => 'no-reply#company.com', 'from_name' => 'Some Company', 'subject' => 'Login Verification', 'data' => array('token' => '3486', 'user' => object(User)), 'view' => 'emails.password')) in GetOtpForLoginService.php line 59
at GetOtpForLoginService->sendEmail('3486', object(User))
Send mail function
public function sendEmail($otp, $user)
{
$user = User::where('email', $user->email)->firstOrFail();
(new SendOtpMail())->send($user->email, [
'from' => env('MAIL_DEAFULT_SENDER'),
'from_name' => env('MAIL_DEAFULT_SENDER_ALIAS'),
'subject' => 'Login Verification',
'data' => [
'token' => $otp,
'user' => $user
],
'view' => 'emails.password'
]);
return true;
}
SendOtpMail.php
<?php
namespace App\Services;
use Illuminate\Mail\Mailer;
class SendOtpMail
{
public function send($to, array $options = array())
{
$callback = function($message) use ($options, $to) {
$message->from($options['from'], isset($options['from_name']) ? $options['from_name'] : null);
$message->to($to, isset($options['to_name']) ? $options['to_name'] : null);
if(isset($options['subject'])) $message->subject($options['subject']);
if(isset($options['priority'])) $message->priority($options['priority']);
if(isset($options['priority'])) $message->priority($options['priority']);
if(isset($options['files'])) {
if (is_array($options['files'])) {
foreach ($options['files'] as $file) {
$message->attach($options[$file]);
}
} else {
$message->attach($options['files']);
}
}
if(isset($options['cc'])) $message->subject($options['cc'], isset($options['cc_name']) ? $options['cc_name'] : null);
if(isset($options['bcc'])) $message->subject($options['bcc'], isset($options['bcc_name']) ? $options['bcc_name'] : null);
};
if(isset($options['view'])) {
$data = isset($options['data']) ? $options['data'] : array();
(new Mailer())->send($options['view'], $data, $callback);
} else {
(new Mailer())->raw($options['message'], $callback);
}
}
}
You are seeing that error because you are instantiating an Illuminate\Mail\Mailer object without specifying its required parameters in the constructor:
// from Laravel source code
public function __construct(string $name, Factory $views, TransportInterface $transport, Dispatcher $events = null)
{
$this->name = $name;
$this->views = $views;
$this->events = $events;
$this->transport = $transport;
}
I suggest you don't send emails this ways. Pls check the docs and follow the instructions.

Remove Nulls From Query Builder Laravel

Im having a little trouble with some return data that I'm getting when running a Query Builder then paginating the data
I was wondering if anyone knew how I could remove Null Results before I paginate the data.
// So Before I hit this
$return = $tld->paginate($request->get('limit'))->toArray();
This is the issue after I paginate
array:12 [
"current_page" => 1
"data" => array:12 [
0 => null
1 => array:3 [
I need to get rid of those Null values, I know how to do it after I paginate however I want to get rid of them before I paginate...
Im hoping that some of you laravel Gods can help me ..
Added this extra logic for $tld
private function newest(Request $request)
{
$this->validate($request, [
'timescale' => [
'required',
Rule::in(['today', 'this_week', 'this_month', 'all_time'])
]
]);
$tld = TimelineItem::where('timeline_items.created_at', '>', $this->timescaleToHours($request->get('timescale')));
if ($request->search_content) {
$tld = $this->searchContent($tld, $request->search_content, 0.4);
} else {
$tld = $tld->orderBy('timeline_items.created_at', 'DESC');
}
if ($request->types) {
$tld = $this->filters($tld, $request->types);
}
if ($request->tags) {
$tld = $this->tags($tld, $request->tags);
}
return $tld;
}
You can use filter() to remove null. Laravel Collection filter()
$response = $tld->paginate($request->get('limit'))->toArray();
$response['data'] = collect($response['data'])->filter()->toArray();
return $response;

Guzzle POST request: required body when execute request

I have a POST request with Guzzle like this:
// Return a collection
$cart = $this->getCart('2019-10-08 07:08:39');
//Return first entry of the collection with first()
$template = $this->getTemplate($config->key);
$isDetail = null;
foreach ($cart as $item) {
try {
$client = $this->getClient();
$headers = ['Content-Type' => 'application/json'];
$body = [
'user_id' => $item->mystore_user_id,
'title' => $template->title,
'message' => $template->message,
'avatar' => $template->avatar,
'detail_id' => $isDetail,
'schedule' => null
];
print_r($body);
$response = $client->post('push-noti/unicast', $headers, $body);
print_r(response()->json(json_decode($response->getBody(), true)));
} catch (QueryException | \Exception $ex) {
echo "Error!";
}
}
My body variable value is exist in each loop when it printed. But when I use it in $client->post, my request return error with user_id, title, message is required. I really don't know why is it?
Can you tell me what's wrong in my code?
Thank you!
Try
$response = $client->post('push-noti/unicast', ['body' => $body , 'headers' => $headers]);
If you are calling a third party API, replace push-noti/unicast with complete URL.

How to test and mock guzzle responses in different situations?

I want to test my API controller that using some guzzle requests from another services.
I have one request for making a download link.
this is my API route
Route::group(['prefix' => '/v1'], function () {
Route::get('/exampledl', 'DownloadController#downloadChecker');
});
DownloadChecker controller checks if user is admin or subscriber makes a guzzle request to one of my services on a different domain, if not do another Guzzle request to another service and for each situations responses are different. This is a part of controller checks admin role.
$client = new Client();
try {
$response = $client->request('GET', 'https://www.example.com/api/user?u=' . $request->uid);
$json = \GuzzleHttp\json_decode($response->getBody()->getContents(), True);
// if user doesn't exist in CM
//this part has been written to avoid repeating code
if (array_key_exists('user', $json) && $json['user'] == null) {
abort(403);
}
elseif (in_array("administrator", $json['Roles'])) {
User::create([
'uid' => (int)$request->uid,
'subscription.role' => 'administrator',
]);
$client = new Client();
$response = $client->request('GET', "https://vod.example2.com/vod/2.0/videos/{$a_id}?secure_ip={$u_ip}", [
'headers' => [
'authorization' => '**********'
]
]);
$json = \GuzzleHttp\json_decode($response->getBody()->getContents(), TRUE);
if (isset($json['data']['mp4_videos'])) {
$links = [];
foreach ($json['data']['mp4_videos'] as $mp_video) {
if (stripos($mp_video, "h_144") !== false) {
$links['144p'] = $mp_video;
}
elseif (stripos($mp_video, "h_240") !== false) {
$links['240p'] = $mp_video;
}
elseif (stripos($mp_video, "h_360") !== false) {
$links['360p'] = $mp_video;
}
elseif (stripos($mp_video, "h_480") !== false) {
$links['480p'] = $mp_video;
}
elseif (stripos($mp_video, "h_720") !== false) {
$links['720p'] = $mp_video;
}
elseif (stripos($mp_video, "h_1080") !== false) {
$links['1080p'] = $mp_video;
}
}
}
one of my tests.
public function test_user_notExist_admin()
{
$client = new Client();
$response = $client->request('GET', 'https://www.example.com/api/user_days_and_roles?u=' . request()->uid);
$json = \GuzzleHttp\json_decode($response->getBody()->getContents(), True);
$this->get('/api/v1/exampledl?uid=1&n_id=400&u_ip=104.58.1.45&dl_id=a81498a9')
->assertStatus(200)
->assertSee('links');
$this->assertDatabaseHas('users', [
'uid' => (int)request('uid'),
'subscription.role' => 'administrator',
]);
}
There are some other conditions check and I'm not sure how to mock these different situations.
Should I make unit test for every situations? Or is there any way to make guzzle in test environment return a custom response? Or any other way?
I got the answer.
for mocking a function in different situations it just needs to use $mock = \Mockery::mock and makePartial();
like this and it let us to make every return we want without execute the function:
public function test_user_notExist_admin()
{
$mock = \Mockery::mock(DownloadController::class, [
'get_download_links_from_download_server' => $this->links,
'post_details_to_log_server' => [200, "new"],
'connect' => [
"Roles" => [
"authenticated",
"subscriber"
]
, "days" => "38"
]
]
)->makePartial();
$this->get('/api/v1/exampledl?uid=1&n_id=400&u_ip=104.58.1.45&dl_id=a81498a9')
->assertStatus(200)
->assertSee('links');
$this->assertDatabaseHas('users', [
'uid' => (int)request('uid'),
'subscription.role' => 'administrator',
]);
}
I've created for each API call a method then I mocked them with Mockery in an Array.
Another way to mock functions one by one:
$mock = Mockery::mock(DownloadController::class)->makePartial();
$mock->shouldReceive('et_download_links_from_download_server')->andReturn('123465');
$this->app->instance(DownloadController::class,$mock);

How to define variable in controller in laravel

I have a URL used in blade template as:
href="{{ route('download', ['year' => $year, 'month' => $month, 'file' => $file_path]) }}"
when I am running my code then it is giving me an error as:
Undefined variable: year (View: C:\wamp64\www\Blog\employee-portal\resources\views\finance\invoice\edit.blade.php)
How can i define this $year variable in my controller?
In my controller the function is written as:
public function download($year, $month, $file, $inline = true)
{
$headers = [
'content-type' => 'application/pdf',
];
$file_path = FileHelper::getFilePath($year, $month, $file);
if (!$file_path) {
return false;
}
if ($inline) {
return Response::make(Storage::get($file_path), 200, $headers);
}
return Storage::download($file_path);
}
}
Edit function is written as:
public function edit(Invoice $invoice)
{
$projectStageBillings = $invoice->projectStageBillings;
$projectStageBilling = $projectStageBillings->first();
$client = $projectStageBilling->projectStage->project->client;
$client->load('projects', 'projects.stages', 'projects.stages.billings');
$billings = [];
foreach ($projectStageBillings as $key => $billing) {
$billing->load('projectStage', 'projectStage.project');
$billings[] = $billing;
}
return view('finance.invoice.edit')->with([
'invoice' => $invoice,
'clients' => Client::select('id', 'name')->get(),
'invoice_client' => $client,
'invoice_billings' => $billings,
]);
}
This error states that the view finance\invoice\edit.blade.php is missing the variable $year. And it is true, take a look at the return of your edit function:
return view('finance.invoice.edit')->with([
'invoice' => $invoice,
'clients' => Client::select('id', 'name')->get(),
'invoice_client' => $client,
'invoice_billings' => $billings,
]);
You are not sending any $year variable to the view here (the variables sent to the view are invoice,clients,invoice_client and invoice_billings.
To solve your problem, just send a $year variable to the view and you'll be ok :)

Resources