Laravel customer API resource with relationships

Viewed 13498

Controller function:

public function index () {
    // TESTED
    // The getAllActiveSuppliers() function just return Supplier::pagniate(10)
    $suppliers = $this -> model -> getAllActiveSuppliers();
    return new SupplierResource($suppliers);
}

Returned Json:

    {
    "current_page": 1,
    "data": [
        {
            "id": 23,
            "name": "Test Name",
            "description": "Test Description",
            "created_by": {
                "id": 1,
                "name": "Test 1",
                "email": "admin@admin.com",
                "email_verified_at": null,
                "active": 1,
                "created_at": "2018-10-12 14:17:38",
                "updated_at": "2018-10-12 14:17:38"
            },
            "updated_by": {
                "id": 1,
                "name": "Test 1",
                "email": "admin@admin.com",
                "email_verified_at": null,
                "active": 1,
                "created_at": "2018-10-12 14:17:38",
                "updated_at": "2018-10-12 14:17:38"
            },
            "deleted_at": null,
            "created_at": "2018-10-31 01:46:11",
            "updated_at": "2018-11-02 22:05:14",

        }
    ],
    ...
}

What I am trying to do:

In the created_by and updated_by I just want to show name, email nothing else.

What I have tried to do:

I have tried to create an API resource collection

Supplier.php API Resource Collection :

public function toArray($request)
{
    return parent::toArray($request);
}
3 Answers

For anyone that may still need this as I was searching for myself in this topic

First create a resource for your relation with name, email fields

class UserResource extends JsonResource
{

    public function toArray($request)
    {
        return [
            'name' => $this->name,
            'email' => $this->email,
        ];
    }
}

Then create SupplierResource with relation created_by to User

class SupplierResource extends JsonResource
{

    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'description' => $this->description,
            'created_by' => new UserResource($this->created_by)
        ];
    }
}

In the Controller

public function index () {

    $suppliers = $this->model->getAllActiveSuppliers();
    
    return SupplierResource::collection($suppliers);
}

You first need to define a structure for a singular JsonResource object:

public function toArray($request)
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        ...
        'created_by' => $this->created_by->only('name', 'email'),
        ...
    ];
}

And then tell your ResourceCollection to use the class:

Customizing The Underlying Resource Class

Typically, the $this->collection property of a resource collection is automatically populated with the result of mapping each item of the collection to its singular resource class. The singular resource class is assumed to be the collection's class name without the trailing Collection string.

For example, UserCollection will attempt to map the given user instances into the User resource. To customize this behavior, you may override the $collects property of your resource collection

(From https://laravel.com/docs/5.7/eloquent-resources#concept-overview)

If your ResourceCollection doesn't do anything extra, you might not need it. Every JsonResource can transform itself for a collection with the collection() method, e.g. JsonResource::collection($models)

Think we can add item to parent::toArray($request)

public function toArray($request)
    {
        $array = parent::toArray($request);
        $array['created_by'] = $this->created_by->only('name', 'email');
        return $array;
    }
Related