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

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);

Related

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

How can i use php conditions inside json data?

Below is the code inside my CategoryResource.php
[
'id' => $this->id,
'name' => $this->name,
'categories' => CategoryResource::collection($this->children),
'items' => ItemListResource::collection($this->items)
];
and by this i am getting response like:
{
"status": true,
"data": {
"categories": [
{
"id": 10,
"name": "Fast Food",
"categories": [
{
"id": 11,
"name": "Pizza",
"categories": [],
"items": [
{
"id": 9,
"name": "Ham \u0026 Crab Stick",
"price": "20.00",
"image": "up/products/c11/Mrn4OpjngYRCkRJ28rJ1LbXUOXy0XjTRyXU7eFoi.jpg"
}
]
}
],
"items": []
}
]
}
}
i dont want "categories" : [] when category does not exist for a category.
please suggest some ideas or ways i can deal with this issue.
I assume that CategoryResource::collection($this->children) returns an array, maybe empty or not.
If that's true, then:
$dataArray = [
'id' => $this->id,
'name' => $this->name,
'items' => ItemListResource::collection($this->items)
];
$categories = CategoryResource::collection($this->children);
if (count(categories) > 0) $dataArray['categories'] = $categories;

Laravel API Resource not returning data with one to many relationship

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

Laravel: How to access Object inside an array

I trying to return access the attributes inside a array of object and it is giving this error Exception: Property [id] does not exist on this collection instance.
Here is what I have tried:
protected function formatted($classroom)
{
return [
'courses' => [
'id' => $classroom->courses->id,
'name' => $classroom->courses->name,
'slug' => $classroom->courses->slug,
'coursteachers' => [
'id' => '$classroom->courses->coursteachers->id',
'email' => '$classroom->courses->coursteachers->email',
'uid' => '$classroom->courses->coursteachers->uid',
]
],
];
}
And here is the actual data:
"courses": [
{
"id": 1,
"name": "Analytics",
"slug": "analytics",
"status_id": 1,
"deleted_at": null,
"pivot": {
"classroom_id": 2,
"courses_id": 1
},
"coursteachers": [
{
"id": 3,
"uid": "S0120-46890",
"email": "teacher#vschool.com",
"user_type": "Teacher",
}]
}]
You need to iterate through courses and also courseteachers since they both represent an array but rather an object
protected function formatted($classroom)
{
$result = [];
foreach($classroom->courses as $course) {
$result[] = [
'courses' => [
'id' => $classroom->courses->id,
'name' => $classroom->courses->name,
'slug' => $classroom->courses->slug,
'coursteachers' => $this->getCourseTeachers($cours)
],
];
}
return $result;
}
private function getClassroomTeachers($classroom) {
$result = [];
foreach($classroom->courses as $cours)
{
foreach ($cours->coursteachers as $key => $teacher) {
$result[] = [
// 'coursteachers'=> [
'id' => $teacher->id,
'email' => $teacher->email,
'uid' => $teacher->uid,
'last_name' => $teacher->profile->last_name,
'first_name' => $teacher->profile->first_name,
'middle_name' => $teacher->profile->middle_name,
// ],
];
}
}
return $result;
}
Since courses is an array, you should pick an object using the proper index.
Foe example: try $classroom->courses[0]->id instead of $classroom->courses->id. Here, '0' is the index.
Also it is better if you check if the index exists before you do it. For an example.
'id' : isset($classroom->courses[$index]) ? $classroom->courses[$index]->id : ''
Edit:
In case of a Eloquent collection you should use $classroom->courses->get($index)->id instead of array like retrieval.

Laravel 5.8 ManyToMany relationship child relation usign foreign key doesn't work

When I call my image resource it returns the correct data from my model:
Image resource:
return [
'id' => $this->id,
'name' => $this->name,
'presentation' => $this->presentation->description,
'slug' =>$this->filename
];
Image Model:
public function presentation()
{
return $this->hasOne(ProductPresentation::class, 'id', 'presentation_id');
}
Returns:
{
"data": [
{
"id": 1,
"name": "White Gold",
"presentation": "Product x",
"slug": "products/white-gold.jpg"
}
}
But when I call the manyToMany (Products -> images) relation I only get the the Id not the foreign relation
"data": [
{
"id": 1,
"name": "White Gold",
"price": "€ 10,00",
"images": [
{
"id": 1,
"name": "White Gold",
"filename": "products/white-gold.jpg",
"presentation_id": 1
}
]
},
The Products resource calls the image resource but this doesn't load the relation ( need "presentation": "Product x" instead of "presentation_id": 1)
Using resource:
return [
'id' => $this->id,
'name' => $this->name,
'price' => $this->formattedPrice,
'images' => $this->images
];
using model:
public function images()
{
return $this->belongsToMany(Image::class);
}
So the question would be how do I add the relation to belongsToMany(Image::class)
Try to change
return [
'id' => $this->id,
'name' => $this->name,
'price' => $this->formattedPrice,
'images' => $this->images
];
To
return [
'id' => $this->id,
'name' => $this->name,
'price' => $this->formattedPrice,
'images' => YourImageResource::collection($this->images)
];

Resources