PHPackages                             netsells/laravel-resourceful - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. netsells/laravel-resourceful

ActiveLibrary[API Development](/categories/api)

netsells/laravel-resourceful
============================

Laravel API Resources supercharged to get rid of N+1 problems.

v2.0.0(1y ago)243.5k↓50%3[1 PRs](https://github.com/netsells/laravel-resourceful/pulls)MITPHPPHP ^8.2CI failing

Since Feb 18Pushed 1y agoCompare

[ Source](https://github.com/netsells/laravel-resourceful)[ Packagist](https://packagist.org/packages/netsells/laravel-resourceful)[ RSS](/packages/netsells-laravel-resourceful/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (4)Dependencies (4)Versions (7)Used By (0)

Laravel Resourceful
===================

[](#laravel-resourceful)

Package that helps you use Laravel API Resources without killing your database! Say goodbye to N+1 👋

The Problem
-----------

[](#the-problem)

Picture a User model that has an "avatar" relation to a File model:

```
namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'avatar_url' => $this->avatar->url,
        ];
    }
}
```

To return a list of users from our API, we could have such a controller action:

```
namespace App\Http\Controllers;

use App\Models\User;

class UserController extends \Illuminate\Routing\Controller
{
    public function index()
    {
        return UserResource::collection(User::paginate());
    }
}
```

In the example above:

- if there is 1 user in our database, 2 queries will be executed
- if there are 100 users in our database, 101 queries will be executed - 1 to get the user, and then 1 query for each avatar for each user

We have a classic N+1 problem. The usual solution in Laravel is to perform eager loading within the controller:

```
namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Routing\Controller;

class UserController extends Controller
{
    public function index()
    {
        return UserResource::collection(User::query()->with('avatar')->paginate());
    }
}
```

This works, but has few problems:

- requires the controller to be aware of inner structure of each API resource
    - in the example above, our controller had to know that we need access to avatar relation in the User resource
    - this is hard to maintain, as we need to keep multiple places in sync
- it's hard to make the eager loading conditional
    - in the example above, we may want to return the avatar\_url only for users on a certain membership plan
    - and if we won't be returning the avatar\_url, then why load the Avatar model in the first place?
- it's hard to keep the eager loading DRY, since it is tied to the controller and not the API resource
    - imagine an ArticleResource, that returns a list of related reviewers, each reviewer being a UserResource
    - fetching the Articles in controller would need to eager load not just the related users, but also the avatars for each user
- since the eager loading is spread in multiple places, any N+1 optimisation is done for each place separately and benefits only that place
    - other endpoints relying on affected API resource will still have N+1 problem

This package fixes all those problems and makes the N+1 problem within your API a thing of the past!

Installation
------------

[](#installation)

using composer:

```
composer require netsells/laravel-resourceful
```

Usage
-----

[](#usage)

This package is a drop in replacement for the official API Resources. Instead of extending the builtin `Illuminate\Http\Resources\Json\JsonResource` we extend `Netsells\Http\Resources\Json\JsonResource`.

Continuing with the example above, we get:

```
namespace App\Http\Resources;

use Netsells\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'avatar_url' => $this->avatar->url,
        ];
    }
}
```

Of course, this doesn't change anything and things still work as they did with N+1 problem, however this first step allows you to easily switch over to this package.

There are few ways now to supercharge your API resource.

### Preloads method

[](#preloads-method)

First way is to select the relations for eager loading in a dedicated `preloads` method. You should return one or more "deferred resources", which can be easily created by calling `preload` helper with a list of relations you want loaded. The `preloads` method can optionally accept a Laravel Request as its first argument. Within the `preloads` method we have access to the Eloquent model being resolved. This allows us to introduce conditional logic for preloading specific relations based on request parameters / model attributes.

```
namespace App\Http\Resources;

use Illuminate\Http\Request;
use Netsells\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    public function preloads()
    {
        return $this->preload('avatar');
    }

    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'avatar_url' => $this->avatar->url,
        ];
    }
}
```

Now before the `toArray` is called, the `avatar` relation will be loaded for all the users in collection, so we've got full access to `$this->avatar` without issuing further queries.

[More examples can be seen in the tests.](tests/Integration/Resources/Super/FullLibrary/Preload/BookResource.php)

### Use callback method

[](#use-callback-method)

Second way is to provide a callback which will be called with the resolved relations.

```
namespace App\Http\Resources;

use Illuminate\Http\Request;
use Netsells\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'avatar_url' => $this->use('avatar', fn ($avatar) => $avatar->url),
        ];
    }
}
```

Now when `toArray` is called, the `avatar` relation hasn't been loaded yet. Our code in the `toArray` method will execute for all the users in collection, and each call to the `use` method will queue a relation to be loaded. We'll then resolve all the queued relations for all users in the most optimal way, and invoke the callback function with resolved relations.

[More examples can be seen in the tests.](tests/Integration/Resources/Super/FullLibrary/Callback/BookResource.php)

### Inline method

[](#inline-method)

Third way is to use an inline shortcut which is very convenient for loading one or many nested API Resources.

```
namespace App\Http\Resources;

use Illuminate\Http\Request;
use Netsells\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'avatar' => $this->one('avatar', AvatarResource::class),
        ];
    }
}

class AvatarResource extends JsonResource
{
    public function preloads()
    {
        return $this->preload('file');
    }

    public function toArray(): array
    {
        return [
            'id' => $this->id,
            'width' => $this->width,
            'height' => $this->height,
            'url' => $this->file->s3Url(),
        ];
    }
}
```

In the example above, we have introduced a nested resource, where a UserResource embeds a separate AvatarResource. Each resource is responsible for eager loading its own relations, and together all relations are loaded in most optimal way.

[More examples can be seen in the tests.](tests/Integration/Resources/Super/FullLibrary/Inline/BookResource.php)

###  Health Score

43

—

FairBetter than 91% of packages

Maintenance45

Moderate activity, may be stable

Popularity32

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity66

Established project with proven stability

 Bus Factor1

Top contributor holds 50% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~222 days

Recently: every ~179 days

Total

6

Last Release

431d ago

Major Versions

v1.2.0 → 2.x-dev2025-03-07

PHP version history (3 changes)v1.0.0PHP &gt;=8.0

1.x-devPHP ^8.1 || ^8.2

2.x-devPHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/8fd3cc944adfb60bb9f271b2ebcf1dde1c26380682db0ba28e029cc42e09cebf?d=identicon)[spamoom](/maintainers/spamoom)

![](https://www.gravatar.com/avatar/9d0c36dae9bb92655da366c4eda4a1d1dceb8d6172077a87588f94fc36ee225b?d=identicon)[kubatek94](/maintainers/kubatek94)

---

Top Contributors

[![ns-alvingeneralo](https://avatars.githubusercontent.com/u/111351974?v=4)](https://github.com/ns-alvingeneralo "ns-alvingeneralo (5 commits)")[![bensherred](https://avatars.githubusercontent.com/u/22666637?v=4)](https://github.com/bensherred "bensherred (2 commits)")[![generaloalvin](https://avatars.githubusercontent.com/u/41601742?v=4)](https://github.com/generaloalvin "generaloalvin (1 commits)")[![kubatek94](https://avatars.githubusercontent.com/u/6105798?v=4)](https://github.com/kubatek94 "kubatek94 (1 commits)")[![tomchkk](https://avatars.githubusercontent.com/u/6698306?v=4)](https://github.com/tomchkk "tomchkk (1 commits)")

---

Tags

laraveleager-loadingnetsellsapi resource

### Embed Badge

![Health badge](/badges/netsells-laravel-resourceful/health.svg)

```
[![Health](https://phpackages.com/badges/netsells-laravel-resourceful/health.svg)](https://phpackages.com/packages/netsells-laravel-resourceful)
```

###  Alternatives

[darkaonline/l5-swagger

OpenApi or Swagger integration to Laravel

2.9k34.0M112](/packages/darkaonline-l5-swagger)[openai-php/laravel

OpenAI PHP for Laravel is a supercharged PHP API client that allows you to interact with the Open AI API

3.7k7.6M74](/packages/openai-php-laravel)[statamic/cms

The Statamic CMS Core Package

4.8k3.2M720](/packages/statamic-cms)[knuckleswtf/scribe

Generate API documentation for humans from your Laravel codebase.✍

2.3k12.2M45](/packages/knuckleswtf-scribe)[vemcogroup/laravel-weather

Weather package for Laravel to use different providers to get weather info

5525.0k](/packages/vemcogroup-laravel-weather)[scriptdevelop/whatsapp-manager

Paquete para manejo de WhatsApp Business API en Laravel

762.6k](/packages/scriptdevelop-whatsapp-manager)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
