Passing return data to another function in same controller laravel - laravel

Try to connect to external API.
In first function, I already received token with authentication.
To send POST request, I need to put xtoken that I received from first function as second function.
I don't know how to send value to second function (registerUser)
Route::get('/connect', 'Guzzlecontroller#registerUser')->name('registeruser');
this is my route file
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Client;
use App\Http\Controllers\Auth\RegisterController;
class GuzzleController extends Controller
{
public function Gettoken()
{
$client = new \GuzzleHttp\Client();
$request = $client->get(
'http://api01.oriental-game.com:8085/token',
[
'headers' => [
'X-Operator' => 'mog189b',
'X-key' => 'sQxAVNaEMe0TCHhU',
]
]
);
$response = $request->getBody();
$tokenReturn = json_decode($response, true);
$xtoken = array("x-token:" . $tokenReturn['data']['token'],);
$this->registerUser($xtoken);
}
public function registerUser($xtoken)
{
$client = new \GuzzleHttp\Client();
$url = "http://api01.oriental-game.com:8085/register";
$request = $client->post($url, [
'headers' => $xtoken,
'body' => [
'username' => 'test1',
'country' => 'Korea',
'fullname' => 'test user1',
'language' => 'kr',
'email' => 'testuser1#test.com',
]
]);
$response = $request->send();
dd($response);
}
}
Too few arguments to function App\Http\Controllers\GuzzleController::registerUser(), 0 passed and exactly 1 expected
this is error I am getting.
please help me to how to send $xtoken value to registerUser function

The problem is Laravel is calling registerUser directly instead of going through getToken. So the token is never retrieved and passed to the register action.
Instead of calling registerUser() from Gettoken(). Have Gettoken() return the token and call it from registerUser()
public function Gettoken()
{
...
return $xtoken;
}
public function registerUser()
{
$xtoken = $this->Gettoken();
...
}

Related

How do I run a phpunit test on Redis pub/sub?

I'm building a messenger system with Redis publishing on the Laravel end and subscribing on a node server. I would like to test what is stored in the redis pub method using PHPUnit, but I have no idea where to start.
Controller
class MessageController extends Controller
{
public function store(Conversation $conversation, Request $request)
{
$user = Auth::user();
$message = Message::create([
'body' => $request->input('message'),
'conversation_id' => $conversation->id,
'sender_id' => $user->id,
'type' => 'user_message'
]);
$redis = Redis::connection();
$data = new MessageResource($message);
$redis->publish('message', $data);
}
}
Current Test
/** #test */
public function a_user_can_send_a_message()
{
$this->actingAs($user = User::factory()->create());
$message = Message::factory()->make(['sender_id' => $user->id]);
$conversation Conversation::factory()->create();
$response = $this->json('POST', '/api/message/'. $conversation->id, ['message' => $message->body])
->assertStatus(201);
$response->assertJsonStructure([
'data' => [
'body',
'sender',
]
]);
}
Essentially what I'm trying to see is if message has been published on Redis. I'm unsure how to do this, and I think you would probably need to clear the message from Redis after, would you not?
Your test should be like this:
public function test_a_user_can_send_a_message()
{
$redisSpy = Redis::spy();
$redisSpy->shouldReceive('connection')->andReturnSelf();
$this->actingAs($user = User::factory()->create());
$message = Message::factory()->make(['sender_id' => $user->id]);
$conversation = Conversation::factory()->create();
$this->postJson("/api/message/{$conversation->id}", ['message' => $message->body]);
$this->assertDatabaseCount('messages', 1);
$redisSpy->shouldHaveReceived('publish')
->with('message', new MessageResource(Message::first()));
}
As you can see, I have added Redis::spy(); this is going to allow is to "spy" what is called from Redis. You can still mock methods, and we have to do so, because you use Redis::connect(); and then $redis->publish(...), so we will return the spy when connect is called, that is why we do shouldReceive('connection')->andReturnSelf().
At the end of the code, we check that $redis->publish was called with parameters 'message' and a resource with the desired message. Both must match for this assertion to pass, else you will see a mock error.

an added value of array of request disappears in Laravel Controller

the user id is existed Before doing create. so it causes an error in the first one.
I made it the other way. the second one below works correctly.
I would like to know why the first one is wrong and it's gone.
//Error
public function store(ContactRequest $request)
{
$request->user_id = $request->user()->id;
Log::debug($request->user()->id);
Log::debug($request);
Contact::create($request->all());
}
//OK
public function store(ContactRequest $request,Contact $contact)
{
$request->user_id = $request->user()->id;
$contact->title = $request->title;
$contact->body = $request->body;
$contact->user_id = $request->user()->id;
$contact->save();
}
the log of the first one is here.
What happened to the user_id!?
[2020-05-30 15:59:10] local.DEBUG: 59
[2020-05-30 15:59:10] local.DEBUG: array (
'_token' => 'gGWuxW6C2JRSCYDuCAC9HauynGclKQEQB7qUh6Rw',
'title' => 'TITLE',
'body' => 'MESSAGE',
'action' => 'SEND',
)
Contact is model class.
ContactRequest is here.
class ContactRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'title' => 'required|max:100',
'body' => 'required|max:1000'
];
}
public function attributes() {
return [
'title' => 'title',
'body' => 'CONTENTS'
];
}
}
You will have to use $request->merge(['user_id'=>$request->user()->id]).
Another tips is that you can simply use Auth::user()->id which also return the user id of current user.
What if you do this:
Auth::user() - >contact($request->all()) - >save() ;
Or also as an experiment:
$contact = new Contact($request->all()) ;
$contact->user_id = Auth::user() - >id;
$contact->save() ;
Actually the second snippet will surely work. The first one I did not test though it looks nice. :)

HJow to add property in the request during 'prepareForValidation'

I am using Laravel 6.
I have this POST (for api usage) :
http://localhost:8000/api/v1/schools/d4866265-3965-4b91-8d0a-a621c9eb68c6/periods/854624d4-69b2-419b-9763-416b5d146e2d/exams/bd0127fe-185a-42f5-b121-15f856daee43
I use the formRequest validation. Like this :
public function rules(Request $request)
{
return [
'classroom_id' => [
'required',
new CoherenceSchoolPeriodClassroom($request->school_id, $request->period_id),
],
As you see, I need the $request->school_id for the test. But this data is not on the request payload, but present on the route.
So I would like to add this data using the prepareForValidation method :
protected function prepareForValidation(): void
{
$this->merge([
'school_id' => 'the school_id present on the route'
]);
}
My question is : how to get the school_id present in the route and merge it in request ?
Assuming your route parameter is called school_id, you can access it as a property or with the route() method.
'school_id' => $this->route('school_id')
// or
'school_id' => $this->school_id
If you only need it to validate the classroom_id you don't have to merge it into the request:
public function rules(Request $request)
{
return [
'classroom_id' => [
'required',
new CoherenceSchoolPeriodClassroom($this->route('school_id'), $request->period_id),
],
...
But you can merge it like so:
protected function prepareForValidation(): void
{
$this->merge([
'school_id' => $this->route('school_id')
]);
}

How to return response from async GuzzleHttp request to outer function or handle Exception in yii2?

I need to send async post request in background and save response (status code and request body to DB). I decide to use GuzzleHttp package (v6) for it.
The idea is run function sendAsyncRequest, send async request inside it, then get response from resource in array with keys code, data, return this array to outer function processAsyncRequest and then send it to function logResponse to save it to db.
use GuzzleHttp\Client as GuzzleClient;
class Logger
{
public function processAsyncRequest($client)
{
$response = $this->sendAsyncRequest($client->phone, ['utm_source' => $client->utm_source]);
$this->logResponse($client, $response);
}
public function sendAsyncRequest($phone, $params)
{
$url_params = http_build_query(['utm_source' => $client->utm_source]);
$guzzleClient = new GuzzleClient();
$headers = [
'Content-Type' => 'application/json',
'Authorization' => 'Basic xxxxxxxxxx',
];
$request = new Request('POST', 'url' . $phone . '/tokens/?' . $url_params, $headers);
$promise = $guzzleClient->sendAsync($request);
$promise->then(
function (ResponseInterface $response) {
return [
'code' => $response->getStatusCode(),
'body' => $response->getBody()->__toString(),
];
},
function(RequestException $e) {
return [
'code' => $e->getResponse()->getStatusCode(),
'body' => $e->getMessage(),
];
}
);
$res = $promise->wait();
return $res;
}
public function logResponse($client, $data)
{
$log = new Log();
$log->client_id = $client->id;
$log->url = 'url';
$log->response = $data['code'] . ', ' . $data['body'];
$log->comment = 'reg';
return $log->save();
}
}
The problems are:
function sendAsyncRequest returns object of GuzzleHttp\Psr7\Response, I see the error "Cannot use object of type GuzzleHttp\Psr7\Response as array" and I have no idea how to get my $res array from it.
how to correctly handle exception if promise will return error?

Trying to get property 'access_token' of non-object laravel-google-sheets

Good Night,I'm using google api sheets with laravel following this tutorial
https://github.com/kawax/laravel-google-sheets
when I try to do the first example
use Sheets;
$user = $request->user();
$token = [
'access_token' => $user->access_token,
'refresh_token' => $user->refresh_token,
'expires_in' => $user->expires_in,
'created' => $user->updated_at->getTimestamp(),
];
// all() returns array
$values = Sheets::setAccessToken($token)->spreadsheet('spreadsheetId')->sheet('Sheet 1')->all();
my code:
namespace App\Http\Controllers;
use Sheets;
use Google;
class PlanilhaController extends Controller
{
public function index(Request $request)
{
$user = $request->user();
$token = [
'access_token' => $user->access_token,
'refresh_token'=> $user->refresh_token,
'expires_in'=> $user->expires_in,
'created' => $user->updated_at->getTimestamp(),
];
$values = Sheets::setAccessToken($token)
>spreadsheet('spreadsheetId')->sheet('Sheet 1')->all();
// all() returns array
return view('planilha', compact('values'));
}
error: Trying to get property 'access_token' of non-object
which is not requested, but I do not know how to solve it
Actually you do not need that token, what you need is to set up your .env so it has following key
GOOGLE_APPLICATION_NAME=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REDIRECT=
GOOGLE_DEVELOPER_KEY=
GOOGLE_SERVICE_ENABLED=
GOOGLE_SERVICE_ACCOUNT_JSON_LOCATION=
POST_SPREADSHEET_ID=
POST_SHEET_ID=
then in your controller
$sheets = Sheets::spreadsheet(config('sheets.post_spreadsheet_id'))
->sheet(config('sheets.post_sheet_id'))
->get();
$header = $sheets->pull(0);
$posts = Sheets::collection($header, $sheets);
$posts = $posts->reverse()->take(10);
then in your config file write this
'post_spreadsheet_id' => env('POST_SPREADSHEET_ID'),
'post_sheet_id' => env('POST_SHEET_ID'),

Resources