Laravel multiple API Resources for same model

Nazem Mahmud Piash
Nov 4 · 3 min read

We already know how Laravel API resources work. If you don’t know how to create and use laravel API resources you can find it here ( Laravel API Resources Documentaion ). One resource or resource collection is bind to a single model (resource class and model class have same name). Resource class identifies the model class by their name. But sometimes, we may need to return different type of data collection from the same model for developing purpose. For example, let’s say, from Employee table, sometimes we need only id and name & sometimes we need id, name, phone, address etc. In this case, we need to create different resource classes for the same model. But as we say, one model is bind to a single resource. And you can’t create multiple resources with same class name. Laravel won’t allow it normally.

So how can we achieve that !!!

Well, I have found two ways to achieve that.

First one is, by creating resource class with the same model name in different folder

php artisan make:resource Employeephp artisan make:resource Another/Employee

First command will create resource file Employee.php, in app\Http\Resources directory. And the second one will create, Employee.php in app\Http\Resources\Another directory. But this is a very poor approach. This approach should not be followed.

Second approach is, create resources as much as necessary. Every resources extends JsonResource. Now, whichever model we want to bind with a resource, we can bind that using constructor.

class EmployeeInfo extends JsonResource
{
function __construct(Employee $model)
{
parent::__construct($model);
}

// ...
}

Here, I am going to explain this with the following example.

Example

Say, we have two models. Employee and Gender. The relation between these two models is,

<?php

namespace
App\Models\Employee;

...

class Employee extends Model
{
...
function gender(){
return $this->belongsTo('App\Models\Gender', 'gender_id', 'id');
}
}

Migration file for genders table


class CreateGendersTable extends Migration
{
public function
up()
{
Schema::create('genders', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
}

...

}

Migration file for employees table

class CreateEmployeesTable extends Migration
{
public function
up()
{
Schema::create('employees', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->unsignedBigInteger('gender_id');
$table->timestamps();
});
}
...
}

Now, I will create two resources.

First resource,

This resource bind employee model normally as resource model binding. It will return only id and name of an employee.

class Employee extends JsonResource
{

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

Second resource,

It will return id, name and gender name of an employee. Here, the Employee model object is passed through the constructor.

class EmployeeGenderInfo extends JsonResource
{
function __construct(Employee $model)
{
parent::__construct($model);
}
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'gender_name' => $this->gender->name, ];
}
}

Now the $this keyword refers the Employee model. So, now this resource also can use Employee model data to return.

One more thing

We need to define the model through constructor only in the resource class. if we have a resource collection for the same resource, we don’t need to define that model again. We can write the resource collection normally like other resource collection. Like, from the given example, for the resource collection of the second resource, simply write

class EmployeeGenderInfo extends ResourceCollection
{

public function
toArray($request)
{

return [
'data' => $this->collection,
'meta' => ['api-version' => '1.0']
];
}
}

This is my first blog here. Please, forgive me if anything is wrong and you also can share your opinion. So that, I can correct my mistakes.

Thank you.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade