Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

princeoo7's avatar

How to filter Data to be displayed in an api call

Below is my api output at the moment.


0	
id	1
title	"Enim illo aut."
slug	"enim-illo-aut."
created_at	"2020-10-12T10:55:34.000000Z"
updated_at	"2020-10-12T10:55:34.000000Z"
attributes	
0	
id	1
product_id	1
name	"color"
created_at	"2020-10-12T10:55:34.000000Z"
updated_at	"2020-10-12T10:55:34.000000Z"
attribute_values	
0	
value	"#b82e1c, #e8d984, #148bc4, #fbc33a, #0f6c54"
1	
id	2
product_id	1
name	"size"
created_at	"2020-10-12T10:55:34.000000Z"
updated_at	"2020-10-12T10:55:34.000000Z"
attribute_values	
0	
value	"6, 7, 8, 9, 10, 11, 12"
2	
id	3
product_id	1
name	"brand"
created_at	"2020-10-12T10:55:34.000000Z"
updated_at	"2020-10-12T10:55:34.000000Z"
attribute_values	
0	
value	"34"
3	
id	4
product_id	1
name	"description"
created_at	"2020-10-12T10:55:34.000000Z"
updated_at	"2020-10-12T10:55:34.000000Z"
attribute_values	
0	
value	"Sit totam quos nobis sed. Sit nulla accusamus laudantium voluptatibus error. Autem deserunt aspernatur ex et saepe. Minima reiciendis repellendus et molestiae."
status	
code	2
value	"Active"

What I want to achieve is as below:

	
0	
-id	1
-title	"Enim illo aut."
-slug	"enim-illo-aut."
-created_at	"2020-10-12T10:55:34.000000Z"
-updated_at	"2020-10-12T10:55:34.000000Z"
-attributes	
--0	
---name	"color"
---value	"#b82e1c, #e8d984, #148bc4, #fbc33a, #0f6c54"
--1	
---name	"size"
---value	"6, 7, 8, 9, 10, 11, 12"
--2	
---name	"brand"
---value	"34"
--3	
---name	"description"
---value	"Sit totam quos nobis sed. Sit nulla accusamus laudantium voluptatibus error. Autem deserunt aspernatur ex et saepe. Minima reiciendis repellendus et molestiae."
-status	
--code	2
--value	"Active"

How can I do it ?

I have 3 tables involved as below:

  1. Product Table
  2. Product Attributes Table
  3. Product Attributes Value Table

Relations as per model are:

  1. Product Mode:

    protected $appends = ['attributes', 'status'];
   
    public function getAttributesAttribute() {
        return $this->attributes()->get();
    }

    public function attributes() {
        return $this->hasMany(ProductAttribute::class)->with(['attributeValues']);
    }

  1. Product Attribute Model :
public function attributeValues() {
        return $this->hasMany(ProductAttributeValue::class);
    }

How should I achieve the expected output ?

0 likes
10 replies
automica's avatar
automica
Best Answer
Level 54

@princeoo7 if you want to transform the output of a query before presenting it to the view, then you should look at API Resources

https://laravel.com/docs/8.x/eloquent-resources#introduction

This will allow you to prepare the output for your json.

eg:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class User 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,
            'email' => $this->email,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

see https://laravel.com/docs/8.x/eloquent-resources#concept-overview

so in your case, your toArray method may look like:

 public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'slug' => $this->slug,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
	    'attributes' => $this->attributes
        ];
    }
1 like
princeoo7's avatar

Can you make an example based on my code ?

I got this when I tried to do the given:

Exception
Property [id] does not exist on this collection instance. 

I added below then I got the output but only one record:

public function toArray($request)
    {
        // return parent::toArray($request);
        return [
            "id" => $this[0]->id,
            "title" => $this[0]->title,
            "slug" => $this[0]->slug,
            "attributes" => $this[0]->attributes,
            "created_at" => $this[0]->created_at,
            "updated_at" => $this[0]->updated_at,
        ];
    }

How I called it in my controller:

public function index(Request $request) {
        return new ProductResource(Product::latest()->limit(2)->get());
    }

UPDATE:

got it working with below code:

public function index(Request $request) {
        return ProductResource::collection(Product::latest()->limit(2)->get());
    }

and removing the key form the return in resources.

princeoo7's avatar

Now the issue is in ProductAttributeResource where I am not able to access attribute_values.

return [
            "name" => $this->name,
            "value" => $this->attribute_values->value,
        ];

automica's avatar

@princeoo7 you'll probably have to create a resource collection for those too.

or

 $this->attribute_values()->pluck('value'),

// not sure if you need the brackets on attribute_values() here or not. please let me know which works and i'll update my message
princeoo7's avatar

@automica I am getting null as that is also a relationship based value.

but if I do return parent::toArray($request) in ProductAttributeResource I get the below answer:

0	
- name	"color"
- attribute_values	
- value	"#b82e1c, #e8d984, #148bc4, #fbc33a, #0f6c54"

if I do :

return [
            "name" => $this->name,
            "value" => $this->attribute_values,
        ];

I get below output:

0	
name	"color"
value	null

so the value is null for $this->attribute_values.

Now If I do :

"value" => ProductAttributeValue::where("id", $this->id)->first()->value,

Then only I get the desired output:

{"data":[{"id":1,"title":"Enim illo aut.","slug":"enim-illo-aut.","attributes":[{"name":"color","value":"#b82e1c, #e8d984, #148bc4, #fbc33a, #0f6c54"},{"name":"size","value":"6, 7, 8, 9, 10, 11, 12"},{"name":"brand","value":"34"},{"name":"description","value":"Sit totam quos nobis sed. Sit nulla accusamus laudantium voluptatibus error. Autem deserunt aspernatur ex et saepe. Minima reiciendis repellendus et molestiae."}],"created_at":"2020-10-12T10:55:34.000000Z","updated_at":"2020-10-12T10:55:34.000000Z"},{"id":2,"title":"Necessitatibus delectus.","slug":"necessitatibus-delectus.","attributes":[{"name":"color","value":"#ba94e8, #64a995, #71daa4, #28086a, #5963fe"},{"name":"size","value":"6, 7, 8, 9, 10, 11, 12"}],"created_at":"2020-10-12T10:55:34.000000Z","updated_at":"2020-10-12T10:55:34.000000Z"}]}

is their a better way to do this ?

automica's avatar

@princeoo7 your relationship is attributeValues so

$this->attributeValues->value;

should return some results

princeoo7's avatar

@automica no it only gives me {} as output for values attribute.

But I got it working as below after posting the above line here :P

$this->attributeValues->value,

1 like
automica's avatar

@princeoo7 cool. I've updated my answer to reflect what you've done, just incase anyone else is following along.

1 like

Please or to participate in this conversation.