Laravel API Resource not returning data with one to many relationship - laravel

In my DoctorController, I have show method like below -
public function show(Doctor $doctor){
DoctorResource::withoutWrapping();
return new DoctorResource($doctor->load('expertises'));
}
In my DoctorResource, if I do
public function toArray($request){
return parent::toArray($request);
}
It returns -
{
"id": 1,
"name": "John Doe",
"mobile": "1234567890",
"email": null,
"avatar": null,
"bio": "Lorem Ipsum 2",
"email_verified_at": null,
"mobile_verified_at": null,
"is_account_verified": 0,
"account_status": "Active",
"created_at": "2020-12-03T07:45:07.000000Z",
"updated_at": "2020-12-03T10:49:30.000000Z",
"expertises": [
{
"id": 1,
"expertise": "ABC",
"created_at": null,
"updated_at": null,
"pivot": {
"doctor_id": 1,
"expertise_id": 1,
"created_at": "2020-12-03T10:49:29.000000Z",
"updated_at": "2020-12-03T10:49:29.000000Z"
}
},
{
"id": 2,
"expertise": "XYZ",
"created_at": null,
"updated_at": null,
"pivot": {
"doctor_id": 1,
"expertise_id": 2,
"created_at": "2020-12-03T10:49:29.000000Z",
"updated_at": "2020-12-03T10:49:29.000000Z"
}
}
]
}
But I want to return certain fields from my DoctorResource, So I did this but it is giving me an error. Exception: Property [expertise] does not exist on this collection instance.
public function toArray($request){
return [
'id' => $this->id,
'name' => $this->name,
'mobile' => $this->mobile,
'email' => $this->email,
'avatar' => $this->avatar,
'bio' => $this->bio,
'expertises' => [
'name' => $this->expertises->expertise
]
];
}

you have define another Json Resource to do that:
first you can retrive the model and add keys and values based on each model properties like :
public function toArray($request){
return [
'id' => $this->id,
'name' => $this->name,
'mobile' => $this->mobile,
'email' => $this->email,
'avatar' => $this->avatar,
'bio' => $this->bio,
'expertises' => ExpertiesResource::collection($this->experties);
];
}
and you have to define Resource Collection as Follow:
class ExpertiesResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
"id" => $this->id,
"exp" => $this->exp,
.....
];
}
}
when your JsonResource has an Array of Object(Resource), you have to Define That Resource and make use of it like use App\Http\Resources\ExpertiesResource

Related

How to pull actual values from foreign id when an array of ids is returned?

I am making an e-commerce site where the person can make an offer for the product. And I want to display all the offers on product at a place where I get the product.After that want to get the information about the user who made the offer and the parent offer in the same query.
I am getting the product like this
`public function show(Product $product)
{
// return response()->json($product);
return new SingleProductResource($product);
}`
The SingleProductResource returns the following
`public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'type' => $this->type,
'images' => $this->images,
'status' => $this->status,
'owner' => $this->user,
'offers' => $this->offers,
];
}`
Offers returns an array like this
`"offers": [
{
"id": 2,
"user_id": null,
"product_id": 1,
"offer_amount": "3",
"parent_id": 2,
"created_at": "2022-11-12T07:54:10.000000Z",
"updated_at": "2022-11-12T07:54:10.000000Z"
},
{
"id": 4,
"user_id": 1,
"product_id": 1,
"offer_amount": "3",
"parent_id": 2,
"created_at": "2022-11-12T08:01:29.000000Z",
"updated_at": "2022-11-12T08:01:29.000000Z"
},
{
"id": 5,
"user_id": null,
"product_id": 1,
"offer_amount": "3",
"parent_id": null,
"created_at": "2022-11-12T08:01:56.000000Z",
"updated_at": "2022-11-12T08:01:56.000000Z"
}
]`
But I want to get the user information directly in this query.
I cannot do this(see comment below) inside the resource as $this->offers returns an array.
`return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'type' => $this->type,
'images' => $this->images,
'status' => $this->status,
'creator' => $this->user,
'offers' => $this->offers->user, //this
];`
You will need to trim your $product in some way. For example
$products = Product::leftJoin('offers', 'products.id', 'offers.product_id')
->where('user_id')
->where('products.id', $product['id'])
->get();
return new SingleProductResource::collection($products);

Change model return array structure

When i request my model::all() i get the data like this:
{
"id": 2,
"user_id": 1,
"type_of_numbers": "mobile",
"pcd_accepted": null,
"first_possible_date": "2021-03-02 15:10:50",
"email": "example#customer.nl",
"customer_id": "Seb",
"customer_initials": "der",
"customer_prefix": "seb",
"customer_last_name": "er",
"customer_company": "seb b.v",
"customer_street": "fds fds fdse",
"customer_house_number": "12",
"customer_house_number_suffix": "A",
"customer_zip_code": "1000ff",
"customer_city": "test",
"status": "blocked",
"status_message": null,
"delayed_answer_reason": null,
"delayed_answer_date": null,
"created_at": "2021-03-02T13:01:15.000000Z",
"updated_at": "2021-03-02T13:02:15.000000Z"
},
How can i get this?
{
"id": 2,
"user_id": 1,
"type_of_numbers": "mobile",
"pcd_accepted": null,
"first_possible_date": "2021-03-02 15:10:50",
"email": "example#customer.nl",
"customer: {
"id": "Seb",
"initials": "der",
"prefix": "seb",
"last_name": "er",
"company": "seb b.v",
"street": "fds fds fdse",
"house_number": "12",
"house_number_suffix": "A",
"zip_code": "1000ff",
"city": "test"
},
"status": "blocked",
"status_message": null,
"delayed_answer_reason": null,
"delayed_answer_date": null,
"created_at": "2021-03-02T13:01:15.000000Z",
"updated_at": "2021-03-02T13:02:15.000000Z"
},
Is it possible to do this in the model? I tried using JsonResource but this works only if i pass 1 array and not a bulk.
JsonResource code:
class JsonResponse extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'note' => $this->note,
'planned_completion_date' => $this->planned_completion_date,
'pcd_accepted' => $this->pcd_accpeted,
'email' => $this->email,
'customer' => [
'id' => $this->customer_id,
'initials' => $this->customer_initials,
'prefix' => $this->customer_prefix,
'last_name' => $this->customer_last_name,
'company' => $this->customer_company,
'street' => $this->customer_street,
'house_number' => $this->customer_house_number,
'house_number_suffix' => $this->customer_house_number_suffix,
'zip_code' => $this->customer_zip_code,
'city' => $this->customer_city
],
'status' => $this->status,
'status_message' => $this->status_message,
'delayed_answer_reason' => $this->delayed_answer_reason,
'delayed_answer_date' => $this->delayed_answer_date,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at
];
}
}
Maybe an ideea would be to try resource collections https://laravel.com/docs/8.x/eloquent-resources#resource-collections

return user model with eager loading laravel

return $data =InteractiveSession::with('messages.user')->where('exercise_id',$exercise->id)->first();
This code will return data like below
{
"id": 1,
"exercise_id": 48,
"messages": [
{
"id": 1,
"from_user": 69,
"message": "Hi",
"interactive_session_id": 1,
"user": {
"id": 69,
"first_name": "Jobin"
}
}
]}
how can i return data like below??
{
"id": 1,
"exercise_id": 48,
"messages": [
{
"id": 1,
"from_user":{
"id": 69,
"first_name": "Jobin"
},
"message": "Hi",
"interactive_session_id": 1,
}
]}
i have tables interactivesession,message,users, using hasmany relation
You can create a relation for from_user to the user model, and then do return $data = InteractiveSession::with(['messages.user', 'fromUser'])->where('exercise_id',$exercise->id)->first(); (remember fromUser should be your relation name)
Try this:
$data = InteractiveSession::with('messages.user')->where('exercise_id',$exercise->id)->first();
$data->transform(function($record) {
$messages = $record->messages->transform(function($message) {
'id' => $message->id,
'from_user' => [
'id' => $message->user->id,
'first_name' => $message->user->first_name
],
'message' => $message->message,
'interactive_session_id' => $message->interactive_session_id
});
return [
'id' => $record->id,
'exercise_id' => $record->exercise_id,
'messages' => $messages
];
});

Laravel Spatie Permissions - user and role relation get only id and name

I'm using Laravel Spatie Permissions to manage roles and permissions in my app. I'm traing to retrieve only Role id and name in the relation between users and roles. My UserResource looks like this:
class UserResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'surname' => $this->surname,
'email' => $this->email,
'inactive' => $this->inactive,
'roles' => $this->roles
];
}
}
And the json looks like this:
"data": [
{
"id": 1,
"name": "Admin",
"surname": "Sudo",
"email": "admin#sudo.com",
"inactive": 0,
"roles": [
{
"id": 1,
"name": "Admin",
"guard_name": "web",
"created_at": "2020-05-28 23:18:58",
"updated_at": "2020-05-28 23:18:58",
"pivot": {
"model_id": 1,
"role_id": 1,
"model_type": "App\\User"
}
}
]
},
]
What I really need it's a json like this:
"data": [
{
"id": 1,
"name": "Admin",
"surname": "Sudo",
"email": "admin#sudo.com",
"inactive": 0,
"roles": [
{
"id": 1,
"name": "Admin",
},
{
"id": 2,
"name": "Default",
},
{
"id": 3,
"name": "Guest",
}
]
},
]
I really don't know how to modified my models relations or the parameter $this->roles (in UserResources) to could get this json.
The easiest solution was using a map function:
'roles' => $this->roles->map(function($role){
return [
'id' => $role['id'],
'name' => $role['name']
];
})
You can create a RoleResource:
class RoleResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
];
}
}
And use it on your UserResource:
class UserResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'surname' => $this->surname,
'email' => $this->email,
'inactive' => $this->inactive,
'roles' => RoleResource::collection($this->roles),
];
}
}

Laravel API Resource Collection return specific fields from other resource

I am working on an api that will be accessible via a mobile app.
I have defined resources and collections for respective endpoints. My problem is now is that I want to return different api json data based on what ever collection.
Here is an example
Provinces has cities and suburbs, so in json format I need to have
"data": [
{
"id": 1,
"name": "Eastern Cape",
"cities": [
{
"name": "Alice"
},
],
"suburbs": [
"name": "Suburb 1"
]
},
]
I want different data when the cities resource is called in news api collection
"data": [
{
"id": 1,
"name": "Eastern Cape",
"cities": [
{
"name": "Alice",
"municipality": "municipality name",
},
],
"suburbs": [
"name": "Suburb 1",
"ward_number": "ward 1"
]
},
]
This is an NewsResource Api
public function toArray($request)
{
// return parent::toArray($request);
return [
'id'=> $this->id,
'title' => $this->title,
'slug' => $this->slug,
'content' => $this->content,
'created_at' => $this->created_at,
'category_id' => $this->news_category_id,
'featured_image' => url($this->featured_image),
'author' => new UserResource($this->user),
'category' => new NewsCategoryResource($this->category), //Only category Name to be displayed
'municipality' => new MunicipalityResource($this->municipality), // Only Municipality Name to be displayed
'comments' => new NewsCommentResource($this->comments),
];
}
I don't really know what is your code structure, but hope this help for you
You may use different queries, for example
/** For the obvious resource calling */
return SomeResource::collection (SomeModel::with(['suburbs', 'cities'])
/** Other filter queries */
->get());
/** For the cities resource calling */
return SomeResource::collection (SomeModel::with(['suburbs:id,ward_number', 'cities:id,municipality'])
/** Other filter queries */
->get());
In your Resource class which you use for the cities/suburbs data, do it like so
return [
/** Some data which you need */
'municipality' => $this->when($this->municipality !== null, $this->municipality),
'ward_number' => $this->when($this->ward_number !== null, $this->ward_number),
];

Resources