Values in api come undefined - laravel

i am making a GET api in Laravel the api in postman works great but when i use it in Laravel to fetch specific data they come undefined. This is the api.php route:
Route::get('list',[GetController::class,'getValues']);
This is the GetController :
function getValues()
{
return response()->json([ValuesResource::collection(Order::all())], 200);
}
This is the ValuesResource :
public function toArray($request)
{
return [
'order_number' => $this->order_number,
'client_id' => $this->client_id,
'description' => $this->description,
'client' => new ClientResource($this->client),
];
}
This is the ClientResource :
public function toArray($request)
{
return [
'name' => $this->name,
'age' => $this->age,
'salary' => $this->salary,
];
}
And this is the blade JQuery code :
async function getData() {
const apiUrl = "http://127.0.0.1:8000/api/list";
const response = await fetch(apiUrl)
const barChatData = await response.json()
console.log(barChatData);
const salary = barChatData.map((x) => x.salary)
//console.log(barChatData.map((x) => x.salary))
const age = barChatData.map((x) => x.age)
const name = barChatData.map((x) => x.name)
employeeSalaryData = salary
employeeAgeData = age
employeeLabel = name
}
In postman i get this result:
[
[
{
"order_number": "b7f55e7ce5",
"client_id": 1,
"description": "order1",
"client": {
"name": "Mr. Omari Schaefer DVM",
"age": "29",
"salary": "150"
}
}
]
]
While on browser they come undefined, if i do just
console.log(barChatData);
I get this array
[Array(1)]
0
:
Array(1)
0
:
{order_number: 'b7f55e7ce5', client_id: 1, description: 'order1', client: {…}}
length
:
1
So the values are coming but i cant fetch them with specific row.

Your code seems to be working fine but need a couple things to change as your fetched data is there.
there is array inside barChatData so map it like this:
const age = barChatData[0].map((item) => {
return item.client.age;
});
const name = barChatData[0].map((item) => {
return item.client.name;
});
const salary = barChatData[0].map((item) => {
return item.client.salary;
});

Related

how can I customize json responses of laravel api and show them in vuex

Trying different solutions, I am fooling around with
response()->json([ ])
To create responses that I can read in my vue / vuex application
The Laravel api function that stores a new Speler ( dutch for player ;)):
I have trouble sending the created, or found Speler-object, through the response to the vuex-store.
Tried to set the status to 202 when succesfully logged, yet the actual status sent is 200..
It is clear that I do not understand it well enough. Can anyone help and explain?
public function store(Request $request)
{
if (Game::where('id',$request['game_id'])->exists() ){
if (!Speler::where('name',$request['name'])->where('game_id',$request['game_id'])->exists()){
$newSpeler = Speler::create(
[
'name' => $request['name'],
'pass_code' => $request['pass_code'],
'game_id' => $request['game_id']
])->first());
return $newSpeler;
}
elseif ( Speler::where('name',$request['name'])->where('game_id',$request['game_id'])->where('pass_code', $request['pass_code'])->exists()){
$speler = Speler::where('name',$request['name'])->where('game_id',$request['game_id'])->where('pass_code', $request['pass_code']);
return response()->json(['speler'=> $speler, 202]);
}
return response()->json(['status' => 'This name is already used, pass-code is not correct', 409]);
}
return response()->json([ 'status' => 'The game-pin does not exist', 403 ]);
}
This is called form the vuex actions:
export const addSpeler = ({commit}, formData) => {
return new Promise((resolve, reject) => {
fetch(`api/speler`, {
method: 'post',
body:formData,
})
.then(res => {
if (res.status === 202){
resolve('De speler is succesfully logged on');
commit('SET_CURRENT_SPELER', res.data.speler);
}
else if (res.status === 201){
commit('SET_CURRENT_SPELER', res.data);
resolve('De speler is succesfully added')
}
else {
reject('De speler is not logged in. Name exists and does not match passcode');
}
})
.catch(err => {
reject(err.message)
});
})
}
and this is called from a vue method:
methods: {
addSpeler(){
this.errorMessage ='';
this.spelerAdded =false;
const formData = new FormData();
formData.append('name', this.name);
formData.append('pass_code',this.pass_code);
formData.append('game_id', this.currentGame.id);
this.$store.dispatch('addSpeler', formData )
.then(res => {
this.spelerAdded = true;
console.log(res.status);
})
.catch(err => {
this.errorMessage = err;
this.spelerAdded = false;
});
},
mutations.js:
export const SET_CURRENT_SPELER = (state, speler) => {
state.currentSpeler = speler;
}
state.js:
export default{
currentGame:{},
currentSpeler:{}
}
The comment by porloscerros answered the question perfectly :
the status goes as the second argument of the json method return response()->json(['speler'=> $speler], 202); (and not inside the array as you are doing). If you don't pass a second argument, the argument value is assigned to 200 by default json(mixed $data = [], int $status = 200, array $headers = [], int $options = 0)

Paypal - Capture Order - TypeError: strtolower(): Argument #1 ($string) must be of type string, int given

I am trying to use PayPal as a payment method on my website. I am using Laravel framework and GuzzleHttp package. Creating an order runs smoothly. Problem comes when trying to capture an order using id.
php artisan tinker
>>> $paypal = new App\Services\PayPalService;
=> App\Services\PayPalService {#3447}
>>> $paypal->createOrder(500.00, 'EUR');
=> {#3478
+"id": "3NK71944KB9544808",
+"status": "CREATED",
+"links": [
{#3476
+"href": "https://api.sandbox.paypal.com/v2/checkout/orders/3NK71944KB9544808",
+"rel": "self",
+"method": "GET",
},
{#3461
+"href": "https://www.sandbox.paypal.com/checkoutnow?token=3NK71944KB9544808",
+"rel": "approve",
+"method": "GET",
},
{#3472
+"href": "https://api.sandbox.paypal.com/v2/checkout/orders/3NK71944KB9544808",
+"rel": "update",
+"method": "PATCH",
},
{#3465
+"href": "https://api.sandbox.paypal.com/v2/checkout/orders/3NK71944KB9544808/capture",
+"rel": "capture",
+"method": "POST",
},
],
}
>>> $paypal->capture("3NK71944KB9544808");
TypeError: strtolower(): Argument #1 ($string) must be of type string, int given
Consuming API code:
public function makeRequest($method, $requestURL, $queryParams = [], $formParams = [], $headers = [], $isJSONRequest = false)
{
$client = new Client([
'base_uri' => $this->baseUri,
]);
if (method_exists($this, 'resolveAuthorization')) {
$this->resolveAuthorization($queryParams, $formParams, $headers);
}
$response = $client->request($method, $requestURL, [
$isJSONRequest ? 'json' : 'form_params' => $formParams,
'headers' => $headers,
'query' => $queryParams,
]);
if (method_exists($this, 'decodeResponse')) {
return $this->decodeResponse($response->getBody()->getContents());
}
return $response->getBody()->getContents();
}
Capturing an order code:
public function captureOrder($id)
{
return $this->makeRequest('POST', "/v2/checkout/orders/$id/capture", [], [], [
"Content-Type: application/json",
]);
}
Well, I switched to PayPal HTTP client and it worked just fine.

Axios returns error status code 500 when there is data present

I am using Laravel 8, VueJS and Axios for my application then every time I try to fetch all records from my database it returns an error with status code 500. Even though when fetching the data using Postman/Insomnia it returns the data without an error.
I tried to empty the table where it fetches the data the error disappears and it returns empty data with status code 200.
Store Module:
import axios from 'axios'
export default {
namespaced: true,
state: {
courses: [],
teacher: '',
},
getters: {
allCourses(state) {
return state.courses
},
},
actions: {
async fetchAllCourses({ commit }) {
const response = await axios.get('teacher/course-management/list')
console.log(response.data.data)
commit('SET_COURSES', response.data.data)
}
},
mutations: {
SET_COURSES(state, courses) {
state.courses = courses
}
}
Controller:
public function fetchAllCourses() {
try {
$courses = Course::all()->sortBy('id');
$data = $courses->transform(function ($course) {
// ! Get teacher id
$teacherId = $this->user->teacher->id;
// ! Get teacher name by id
$teacherName = $this->getTeacherName($teacherId);
return [
'id' => $course->id,
'teacher_id' => $course->teacher_id,
'teacher' => $teacherName,
'section' => $course->section,
'code' => $course->code,
'status' => $course->status,
'image' => $course->image,
];
});
return $this->success('Request success', $data);
} catch (\Exception $e) {
return $this->error($e->getMessage(), $e->getCode());
}
}
Problem solved.
public function fetchAllCourses() {
try {
$courses = Course::all()->sortBy('id');
$data = $courses->transform(function ($course) {
return [
'id' => $course->id,
'teacher_id' => $course->teacher_id,
'teacher' => $this->getTeacherName($course->teacher_id),
'section' => $course->section,
'code' => $course->code,
'status' => $course->status,
'image' => $course->image,
];
});
return $this->success('Request success', $data);
} catch (\Exception $e) {
return $this->error($e->getMessage(), $e->getCode());
}
}

Laravel Http Client 419 unknown status

For testing reasons, I want to make the following Post Request with the Laravel HTTP Client:
$test = Http::post(route('users.leads.store', ['user' => $user->id]), [
"company_name" => "TESTCOMPANY",
"zip" => "49685",
"city" => "BÜHREN",
"street" => "MÜHLENKAMP 3",
"contact_name" => "FABIANLUKASSEN",
"phone1" => "017691443785",
"email" => "FABIANLUKASSEN#TESTEN.DE",
"website" => "www.fabianlukassen.de",
"category" => "Hotel",
"closed_until" => now(),
"appointment_end" => now()->addDays(1),
"appointment_comment" => "HALLO ICH BIN FABIAN",
"additional_contacts" => "",
"phone2" => "",
"sub_category" => "",
"expert_status" => 0
]);
I know that the route is working just fine. However, with debugging in phpStorm, I can see that the $test variable contains a 419 error (unknown status). Does anyone know what's wrong?
(I'm using laravel 8)
I agree with #ElektaKode that the issue is likely due to lack of csrf token.
In order to disable CSRF middleware while testing,
switch off CSRF token for this route at /app/Http/Midddleware/VerifyCsrfToken.php, by updating:
protected $except = [ 'your-route-url' ];
Then you can use api authentication to follow it up.
The simplest way to use api authentication, follow this doc,
The other ways are either using Laravel passport or using jwt for api.(both will consume more time to set up, as you are using for testing using api authentication is your go to method.)
Usually in Laravel, 419 Page Expired error comes from CSRF middleware meaning there was a failure while validating CSRF token. Add your CSRF token to your test request or consider disabling CSRF middleware while testing.
Post Request with Laravels HTTP Client
$test = Http::post(route('users.leads.store', ['user' => $user->id]), [
"company_name" => "TESTCOMPANY",
"place_id" => null,
"street" => "MÜHLENKAMP 3",
"zip" => "49685",
"city" => "BÜHREN",
"title" => null,
"contact_name" => "FABIANLUKASSEN",
"additional_contacts" => null,
"phone1" => "+49 163 3006603",
"phone2" => null,
"email" => "FABIANLUKASSEN#TESTEN.DE",
"category" => "Hotel",
"sub_category" => null,
"website" => "www.fabianlukassen.de",
"status" => 1,
"expert_status" => 0,
"coordinates" => null,
"expert_id" => 1,
"agent_id" => null,
"blocked" => 0,
"important_note" => null,
]);
Route
Route::apiResource('users.leads', UserLeadController::class);
Store Method in the UserLeadController
public function store(User $user, CreateLeadRequest $request)
{
//TODO: Relocate validation to request class
if(!UserLeadController::isPhone("test", $request->phone1)) {
abort(400, "Keine gültige Telefonnummer!");
return;
}
if(!UserLeadController::isPhoneNumberUnique("test", $request->phone1)) {
abort(400, "Die Telefonnummer existiert bereits!");
return;
}
/**
* The logged in User
* #var User $agent
*/
$agent = Auth::user();
$phoneUtil = PhoneNumberUtil::getInstance();
$lead = new Lead();
$lead->fill($request->except(['appointment_end', 'appointment_comment']));
// Leads created by experts will be blocked
if ($user->id === $agent->id) {
$lead->blocked = true;
}
$numberProto = $phoneUtil->parse($lead->phone1, 'DE');
$lead->phone1 = $phoneUtil->format($numberProto, PhoneNumberFormat::INTERNATIONAL);
try {
$lead->save();
} catch (QueryException $e) {
//$message = 'Lead besteht bereits.';
//return Response::json(['errors' => $message], 422);
abort(422, "Lead besteht bereits!");
return;
}
if ($request->closed_until) {
$lead->closed_until = Carbon::create($request->closed_until);
$event_end = $request->appointment_end
? Carbon::parse($request->appointment_end)
: Carbon::parse($request->closed_until)->addMinutes(90);
$lead->calendarEvents()->save(new CalendarEvent([
'body' => $request->appointment_comment ?? "Wurde von {$this->roleDescriptor($agent->roles)}" . $agent->name . " angelegt.",
'type' => CalendarEventType::CALLCENTER_APPOINTMENT,
'event_begin' => $lead->closed_until,
'event_end' => $event_end,
]));
$lead->status = LeadState::APPOINTMENT;
$lead->expert_status = LeadExpertAcceptance::ACCEPTED;
} else {
$lead->status = LeadState::OPEN;
}
if (isset($request->agent)) {
$lead->agent_id = $request->agent;
}
try {
$user->leads()->save($lead);
$lead->comments()->save(new Comment([
'body' => "Wurde von {$this->roleDescriptor($agent->roles)}" . $agent->name . " angelegt.",
'user_id' => $agent->id,
'commentable_type' => 'lead',
'commentable_id' => $lead->id,
'reason' => 'CREATED',
'date' => now('Europe/Berlin'),
]));
if ($request->closed_until) {
$lead->comments()->save(new Comment([
'body' => "Termin wurde von {$this->roleDescriptor($agent->roles)}" . $agent->name . " vereinbart.",
'user_id' => $agent->id,
'commentable_type' => 'lead',
'commentable_id' => $lead->id,
'reason' => 'APPOINTMENT',
'date' => now('Europe/Berlin')->addMinute(),
]));
}
} catch (QueryException $e) {
//not sure if this works
$message = $e->getMessage();
abort(400, $message);
return;
}
if (empty($message)) {
return Response::json(['message' => 'Lead saved', 'lead' => new LeadSingleResource($lead)]);
} else {
return Response::json(compact('message'), 500);
}
}
//TODO: relocate function to rule object
protected static function isPhoneNumberUnique($attribute, $value) {
$withSpace = PhoneFormatter::formatInternational($value);
$withoutSpace = preg_replace('/ /', '', $withSpace);
$protos = [$withSpace, $withoutSpace]; // Necessary because legacy (25.06.2020).
$booleanTest = Company::query()->whereIn('phone', $protos)->doesntExist()
|| Lead::query()->whereIn('phone1', $protos)->orWhereIn('phone2', $protos)->doesntExist();
return $booleanTest;
}
//TODO: relocate function to rule object
protected static function isPhone($attribute, $value) {
if (!$value) {
return false;
}
$phoneUtil = \libphonenumber\PhoneNumberUtil::getInstance();
$test = $phoneUtil->isValidNumber($phoneUtil->parse($value, 'DE'));
return $test;
}
fillable variable in the Lead Model
protected $fillable = [
'company_name',
'place_id',
'street',
'zip',
'city',
'title',
'contact_name',
'additional_contacts',
'phone1',
'phone2',
'email',
'category',
'sub_category',
'website',
'status',
'expert_status',
'coordinates',
'expert_id',
'agent_id',
'blocked',
'important_note'
];
As mentioned before, I receive a 200 OK status. Also, in a Vue.js component, I have done the following axios post request, which also just works fine.
axios
.post(`/api/users/${this.user_id}/leads`, {
"company_name": this.companyName,
"zip": this.zipCode,
"city": this.city,
"street": this.streetAndHouseNumber,
"contact_name": this.contactPartner,
"phone1": this.contactPartnerPhoneNumber,
"email": this.contactPartnerEmail,
"website": this.website,
"category": this.category,
"closed_until": this.appointmentStart,
"appointment_end": this.appointmentEnd,
"appointment_comment": this.comment,
//not used but needed (don't know the purpose)
"additional_contacts": "",
"phone2": "",
"sub_category": "",
"expert_status":this.expert_status,
}).then(() => {
window.location.href = this.routeSuccess;
}).catch((error) => {
this.showErrorAlert = true;
this.errorAlertMessage = error.response.data.message;
});
}

Centralizing Post Data on the client and server

I'm building my first API and I have this nightmare scenario where I see myself defining the same request data in multiples places. How are people maintaining their key/value payloads?
Here's my VueJS component on the client side:
<script>
export default {
data() {
return {
name: '',
description: '',
selectedHeader: '',
}
},
computed: {
businessUrl() {
return this.name.replace(/[^A-Z0-9]+/ig, '') + '.test.com';
},
},
methods: {
preview() {
let data = {
'name': this.businessUrl,
'description' : this.description,
'selectedHeader': this.selectedHeader
};
axios.post('/builder/preview', data)
...
</script>
Server-side:
public function preview()
{
$validatedData = request()->validate([
'name' => 'required',
'description' => 'string',
'selectedHeader' => 'required',
]);
$business = new Business;
$business->name = request('name');
$business->description = request('description');
$business->header = request('selectedHeader');
return view('business', compact('business'));
}
If I want to change the 'name' field that is posted on my route I have to do it in up to 5 places if I include references in my HTML. Any patterns that people have developed to avoid this duplication?

Resources