PHPackages                             hds-solutions/laravel-api-helpers - 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. hds-solutions/laravel-api-helpers

ActiveLibrary[API Development](/categories/api)

hds-solutions/laravel-api-helpers
=================================

A package with helpers to generate APIs on your Laravel project

v1.2.3(1y ago)144.8k↑123.1%11GPL-3.0PHPPHP ^8.0|^8.1|^8.2|^8.3|^8.4

Since Aug 4Pushed 1y ago2 watchersCompare

[ Source](https://github.com/hschimpf/laravel-api-helpers)[ Packagist](https://packagist.org/packages/hds-solutions/laravel-api-helpers)[ RSS](/packages/hds-solutions-laravel-api-helpers/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (10)Dependencies (4)Versions (12)Used By (1)

Laravel API Helpers
===================

[](#laravel-api-helpers)

This library simplifies the process of building API controllers by providing convenient classes for managing filtering, ordering, relationship loading, and pagination of resource collections.

[![Latest stable version](https://camo.githubusercontent.com/56f2b3bfde7b57e216e178e30e9d5795c4782380fd6160006f84805c2c20ff0f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6864732d736f6c7574696f6e732f6c61726176656c2d6170692d68656c706572733f7374796c653d666c61742d737175617265266c6162656c3d6c617465737426636f6c6f723d303039324342)](https://github.com/hschimpf/laravel-api-helpers/releases/latest)[![License](https://camo.githubusercontent.com/53730735ddaecca0f36799aa161f0c0967640943bf6aab561c63e67a93c4bb23/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f68736368696d70662f6c61726176656c2d6170692d68656c706572733f7374796c653d666c61742d73717561726526636f6c6f723d303039363634)](https://github.com/hschimpf/laravel-api-helpers/blob/main/LICENSE)[![Total Downloads](https://camo.githubusercontent.com/a48c4197aa5f4d7bcf2f9ce7f8dc072abb78e39ed5ebe671226a44ca260b450c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6864732d736f6c7574696f6e732f6c61726176656c2d6170692d68656c706572733f7374796c653d666c61742d73717561726526636f6c6f723d373437343734)](https://packagist.org/packages/hds-solutions/laravel-api-helpers)[![Monthly Downloads](https://camo.githubusercontent.com/f261b2faa9d5927bfb70f631f548a87d8f35d5101e6311dd5ea05fa8230c707a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646d2f6864732d736f6c7574696f6e732f6c61726176656c2d6170692d68656c706572733f7374796c653d666c61742d73717561726526636f6c6f723d373437343734266c6162656c3d)](https://packagist.org/packages/hds-solutions/laravel-api-helpers)[![Required PHP version](https://camo.githubusercontent.com/4e057400d14ae83a2c1c131d6a56f13fed7e41aba315f0bfbc1f7ed1525f44cc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f6864732d736f6c7574696f6e732f6c61726176656c2d6170692d68656c706572732f7068703f7374796c653d666c61742d73717561726526636f6c6f723d303036343936266c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://packagist.org/packages/hds-solutions/laravel-api-helpers)

Features
--------

[](#features)

- Easy management of request query filters for filtering resource collections based on allowed columns.
- Simplified sorting of resource collections based on allowed columns.
- Convenient loading of extra relationships for resource collections.
- Pagination support for resource collections.

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

[](#installation)

### Dependencies

[](#dependencies)

- PHP &gt;= 8.0
- Laravel Framework &gt;= 9.0

### Via composer

[](#via-composer)

```
composer require hds-solutions/laravel-api-helpers
```

Usage
-----

[](#usage)

To make use of the library, you will need to create specific classes that extend the provided abstract classes. The provided classes contain the implementation of the necessary logic for each feature (filtering, sorting, relationship loading, and pagination).

### ResourceFilters

[](#resourcefilters)

The `ResourceFilters` class manages the query filters for resource collections. It allows you to define the allowed columns and their corresponding filter operators.

In the extended class, you can define the list of allowed columns that can be used for filtering, along with their allowed operators.

The available operators are:

- `eq`: Translates to a `field_name = "value"` filter.
- `ne`: Translates to a `field_name != "value"` filter.
- `has`: Translates to a `field_name LIKE "%value%"` filter.
- `lt`: Translates to a `field_name < "value"` filter.
- `lte`: Translates to a `field_name  "value"` filter.
- `gte`: Translates to a `field_name >= "value"` filter.
- `in`: Translates to a `field_name IN ("value1", "value2", ...)` filter.
- `btw`: Translates to a `field_name BETWEEN "value1" AND "value2"` filter.

Operators are also grouped by field type:

- `string`: Translates to the operators `eq`, `ne` and `has`.
- `numeric`: Translates to the operators `eq`, `ne`, `lt`, `lte`, `gt`, `gte`, `in`, and `btw`.
- `boolean`: Translates to the operators `eq` and `ne`.
- `date`: Translates to the operators `eq`, `ne`, `lt`, `lte`, `gt`, `gte`, and `btw`.

#### Example implementation

[](#example-implementation)

You just need to extend the `ResourceFilters` class and define the allowed filtrable columns.

```
namespace App\Http\Filters;

class CountryFilters extends \HDSSolutions\Laravel\API\ResourceFilters {

    protected array $allowed_columns = [
        'name'      => 'string',
        'code'      => 'string',
        'size_km2'  => [ 'gt', 'lt', 'btw' ],
    ];

}
```

You can also override the default filtering implementation of a column by defining a method with the same name as the filtrable column. The method **must** have the following arguments:

- `Illuminate\Database\Eloquent\Builder`: The current instance of the query builder.
- `string`: The operator requested for filtering.
- `mixed`: The value of the filter.

```
namespace App\Http\Filters;

use Illuminate\Database\Eloquent\Builder;

class CountryFilters extends \HDSSolutions\Laravel\API\ResourceFilters {

    protected array $allowed_columns = [
        'name'          => 'string',
        'code'          => 'string',
        'size_km2'      => [ 'gt', 'lt', 'btw' ],
        'regions_count' => 'number',
    ];

    protected function regionsCount(Builder $query, string $operator, $value): void {
        return $query->whereHas('regions', operator: $operator, count: $value);
    }

}
```

#### Example requests

[](#example-requests)

- Filtering by country name:

    ```
    GET https://localhost/api/countries?name[has]=aus
    Accept: application/json
    ```

    Example response:

    ```
    {
        "data": [
            {
                "id": 123,
                "name": "Country name",
                "size_km2": 125000,
                ...
            },
            { ... },
            { ... },
            { ... },
            ...
        ],
        "links": {
            ...
        }
        "meta": {
            ...
        }
    }
    ```
- Filtering by country size:

    ```
    GET https://localhost/api/countries?size_km2[btw]=100000,500000
    Accept: application/json
    ```

    Example response:

    ```
    {
        "data": [
            {
                "id": 123,
                "name": "Country name",
                "size_km2": 125000,
                ...
            },
            { ... },
            { ... },
            { ... },
            ...
        ],
        "links": {
            ...
        }
        "meta": {
            ...
        }
    }
    ```
- Filtering by countries that have more than N regions:

    ```
    GET https://localhost/api/countries?regions_count[gte]=15
    Accept: application/json
    ```

    Example response:

    ```
    {
        "data": [
            {
                "id": 123,
                "name": "Country name",
                "size_km2": 125000,
                ...
            },
            { ... },
            { ... },
            { ... },
            ...
        ],
        "links": {
            ...
        }
        "meta": {
            ...
        }
    }
    ```

### ResourceOrders

[](#resourceorders)

The `ResourceOrders` class manages the sorting of resource collections. It allows you to define the allowed columns to sort the resource collection and a default sorting fields.

In the extended class, you can define the list of allowed columns that can be used for sorting the resource collection.

#### Example implementation

[](#example-implementation-1)

You just need to extend the `ResourceOrders` class and define the allowed sortable columns.

```
namespace App/Http/Orders;

class CountryOrders extends \HDSSolutions\Laravel\API\ResourceOrders {

    protected array $default_order = [
        'name',
    ];

    protected array $allowed_columns = [
        'name',
    ];

}
```

You can also override the default sorting implementation of a column by defining a method with the studly version of the sortable column. The method **must** have the following arguments:

- `Illuminate\Database\Eloquent\Builder`: The current instance of the query builder.
- `string`: The direction of the sort.

```
namespace App/Http/Orders;

use Illuminate\Database\Eloquent\Builder;

class CountryOrders extends \HDSSolutions\Laravel\API\ResourceOrders {

    protected array $default_order = [
        'name',
    ];

    protected array $allowed_columns = [
        'name',
        'regions_count',
    ];

    protected function regionsCount(Builder $query, string $direction): void {
        $query->orderBy('regions_count', direction: $direction);
    }

}
```

#### Example requests

[](#example-requests-1)

The request sorting parameters must follow the following syntax: `order[{index}][{direction}]={field}`

- Sorting by country name:

    ```
    GET https://localhost/api/countries?order[0][asc]=name
    Accept: application/json
    ```

    Example response:

    ```
    {
        "data": [
            {
                "id": 123,
                "name": "Country name",
                ...
            },
            { ... },
            { ... },
            { ... },
            ...
        ],
        "links": {
            ...
        }
        "meta": {
            ...
        }
    }
    ```
- Sorting by country name and regions count in descending order:

    ```
    GET https://localhost/api/countries?order[0][asc]=name&order[1][desc]=regions_count
    Accept: application/json
    ```

    Example response:

    ```
    {
        "data": [
            {
                "id": 123,
                "name": "Country name",
                ...
            },
            { ... },
            { ... },
            { ... },
            ...
        ],
        "links": {
            ...
        }
        "meta": {
            ...
        }
    }
    ```

### ResourceRelations

[](#resourcerelations)

The `ResourceRelations` class manages the loading of extra relationships for resource collections. It allows you to specify the allowed relationships to be loaded and the relationships that should always be loaded.

In the extended class, you can define the list of allowed relationships that can be added to the resource collection.

#### Example implementation

[](#example-implementation-2)

```
namespace App/Http/Relations;

class CountryRelations extends \HDSSolutions\Laravel\API\ResourceRelations {

    protected array $with_count = [
        'regions',
    ];

    protected array $allowed_relations = [
        'regions',
    ];

}
```

You can also capture the loaded relationship to add filters, sorting, or any action that you need. The method **must** have the following arguments:

- `Illuminate\Database\Eloquent\Relations\Relation`: The instance of the relationship being loaded.

```
namespace App/Http/Relations;

class CountryRelations extends \HDSSolutions\Laravel\API\ResourceRelations {

    protected array $with_count = [
        'regions',
    ];

    protected array $allowed_relations = [
        'regions',
    ];

    protected function regions(Relation $regions): void {
        $regions->where('active', true);
    }

}
```

#### Example requests

[](#example-requests-2)

- Loading countries with their regions relationship collection:

    ```
    GET https://localhost/api/countries?with[]=regions
    Accept: application/json
    ```

    Example response:

    ```
    {
        "data": [
            {
                "id": 123,
                "name": "Country name",
                "regions_count": 5,
                "regions": [
                    { ... },
                    { ... },
                    { ... },
                    ...
                ]
            },
            { ... },
            { ... },
            { ... },
            ...
        ],
        "links": {
            ...
        }
        "meta": {
            ...
        }
    }
    ```

### PaginateResults

[](#paginateresults)

The `PaginateResults` class handles the pagination of resource collections. It provides support for paginating the results or retrieving all records.

#### Example requests

[](#example-requests-3)

- Request all countries: ```
    GET https://localhost/api/countries?all=true
    Accept: application/json
    ```

    Example response: ```
    {
        "data": [
            {
                "id": 123,
                "name": "Country name",
                "regions_count": 5
            },
            { ... },
            { ... },
            { ... },
            { ... },
            { ... },
            { ... },
            { ... },
            { ... },
            { ... },
            { ... },
            { ... }
        ]
    }
    ```

### Controller implementation

[](#controller-implementation)

Here is an example of a controller using the `Pipeline` facade to implement all the previous features.

```
namespace App/Http/Controllers/Api;

use App\Models\Country;

use App\Http\Filters;
use App\Http\Relations;
use App\Http\Orders;

use HDSSolutions\Laravel\API\Actions\PaginateResults;

use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Pipeline;

class CountryController extends Controller {

    public function index(Request $request): ResourceCollection {
        return new ResourceCollection(
            Pipeline::send(Country::query())
                ->through([
                    Filters\CountryFilters::class,
                    Relations\CountryRelations::class,
                    Orders\CountryOrders::class,
                    PaginateResults::class,
                ])
                ->thenReturn()
        );
    }

    public function show(Request $request, int $country_id): JsonResource {
        return new Resource(
            Pipeline::send(Country::where('id', $country_id))
                ->through([
                    Relations\CountryRelations::class,
                ])
                ->thenReturn()
                ->firstOrFail()
            )
        );
    }

}
```

More request examples
---------------------

[](#more-request-examples)

```
GET https://localhost/api/regions
Accept: application/json
```

Example response:

```
{
    "data": [
        {
            "id": 5,
            "name": "Argentina",
            "code": "AR",
            "regions_count": 24
        },
        {
            "id": 1,
            "name": "Canada",
            "code": "CA",
            "regions_count": 13
        },
        {
            "id": 3,
            "name": "Germany",
            "code": "DE",
            "regions_count": 16
        },
        ...
    ],
    "links": {
        "first": "https://localhost/api/regions?page=1",
        "last": "https://localhost/api/regions?page=13",
        "prev": null,
        "next": "https://localhost/api/regions?page=2"
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 13,
        "links": [
            {
                "url": null,
                "label": "&laquo; Previous",
                "active": false
            },
            {
                "url": "https://localhost/api/regions?page=1",
                "label": "1",
                "active": true
            },
            {
                "url": "https://localhost/api/regions?page=2",
                "label": "2",
                "active": false
            },
            {
                "url": null,
                "label": "...",
                "active": false
            },
            {
                "url": "https://localhost/api/regions?page=12",
                "label": "12",
                "active": false
            },
            {
                "url": "https://localhost/api/regions?page=13",
                "label": "13",
                "active": false
            },
            {
                "url": "https://localhost/api/regions?page=2",
                "label": "Next &raquo;",
                "active": false
            }
        ],
        "path": "https://localhost/api/regions",
        "per_page": 15,
        "to": 15,
        "total": 195
    }
}
```

```
GET https://localhost/api/regions?name[has]=aus
Accept: application/json
```

Example response:

```
{
    "data": [
        {
            "id": 34,
            "name": "Australia",
            "code": "AU",
            "regions_count": 8
        },
        {
            "id": 12,
            "name": "Austria",
            "code": "AT",
            "regions_count": 9
        }
    ],
    "links": {
        ...
    },
    "meta": {
        ...
    }
}
```

```
GET https://localhost/api/regions?regions_count[gt]=15&order[][desc]=name
Accept: application/json
```

Example response:

```
{
    "data": [
        ...
        {
            "id": 3,
            "name": "Germany",
            "code": "DE",
            "regions_count": 16
        },
        {
            "id": 5,
            "name": "Argentina",
            "code": "AR",
            "regions_count": 24
        },
        ...
    ],
    "links": {
        ...
    },
    "meta": {
        ...
    }
}
```

Extras
------

[](#extras)

### Before and after callbacks

[](#before-and-after-callbacks)

The `ResourceFilters` and `ResourceOrders` classes have two methods (`before` &amp; `after`) that allow a better customization on the query builder. You can override them to make more manipulations to the query builder.

### ResourceRequest

[](#resourcerequest)

The `ResourceRequest` class has the following features:

- The `hash()` method gives you a unique identifier based on the query parameters.
- The `authorize()` method is a WIP feature that will handle resource access authorization.

### Caching requests

[](#caching-requests)

You can use the `hash()` method of the `ResourceRequest` class and use it as a cache key. The parameter `cache` is ignored and not used to build the request identifier.

In the following example, we capture the `cache` request parameter to force the cache to be cleared.

```
namespace App/Http/Controllers/Api;

use App\Models\Country;

use App\Http\Filters;
use App\Http\Relations;
use App\Http\Orders;

use HDSSolutions\Laravel\API\Actions\PaginateResults;
use HDSSolutions\Laravel\API\ResourceRequest;

use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Pipeline;

class CountryController extends Controller {

    public function index(ResourceRequest $request): JsonResponse | ResourceCollection {
        // forget cached data if is requested
        if ($request->boolean('cache', true) === false) {
            cache()->forget($request->hash(__METHOD__));
        }

        // remember data for 8 hours, using request unique hash as cache key
        return cache()->remember(
            key: $request->hash(__METHOD__),
            ttl: new DateInterval('PT8H'),
            callback: fn() => (new ResourceCollection($request,
                Pipeline::send(Country::query())
                    ->through([
                        Filters\CountryFilters::class,
                        Relations\CountryRelations::class,
                        Orders\CountryOrders::class,
                        PaginateResults::class,
                    ])
                    ->thenReturn()
                )
            )->response($request)
        );
    }

    public function show(Request $request, int $country_id): JsonResponse | JsonResource {
        if ($request->boolean('cache', true) === false) {
            cache()->forget($request->hash(__METHOD__));
        }

        return cache()->remember(
            key: $request->hash(__METHOD__),
            ttl: new DateInterval('PT8H'),
            callback: fn() => (new Resource(
                Pipeline::send(Model::where('id', $country_id))
                    ->through([
                        Relations\CountryRelations::class,
                    ])
                    ->thenReturn()
                    ->firstOrFail()
                )
            )->response($request)
        );
    }

}
```

Security Vulnerabilities
========================

[](#security-vulnerabilities)

If you encounter any security-related issues, please feel free to raise a ticket on the issue tracker.

Contributing
============

[](#contributing)

Contributions are welcome! If you find any issues or would like to add new features or improvements, please feel free to submit a pull request.

Contributors
------------

[](#contributors)

- [Hermann D. Schimpf](https://hds-solutions.net)

Licence
=======

[](#licence)

This library is open-source software licensed under the [MIT License](LICENSE). Please see the [License File](LICENSE) for more information.

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance42

Moderate activity, may be stable

Popularity29

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity68

Established project with proven stability

 Bus Factor1

Top contributor holds 100% 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 ~59 days

Total

11

Last Release

463d ago

PHP version history (3 changes)v1.0.0-betaPHP ^8.0|^8.1

v1.1.4PHP ^8.0|^8.1|^8.2|^8.3

v1.2.3PHP ^8.0|^8.1|^8.2|^8.3|^8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/50f96185442e90979dd407a9503e3362a285741fac3e00545bf570235ff7901e?d=identicon)[hschimpf](/maintainers/hschimpf)

---

Top Contributors

[![hschimpf](https://avatars.githubusercontent.com/u/493357?v=4)](https://github.com/hschimpf "hschimpf (34 commits)")

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/hds-solutions-laravel-api-helpers/health.svg)

```
[![Health](https://phpackages.com/badges/hds-solutions-laravel-api-helpers/health.svg)](https://phpackages.com/packages/hds-solutions-laravel-api-helpers)
```

###  Alternatives

[statamic/cms

The Statamic CMS Core Package

4.8k3.5M920](/packages/statamic-cms)[darkaonline/l5-swagger

OpenApi or Swagger integration to Laravel

2.9k36.4M126](/packages/darkaonline-l5-swagger)[knuckleswtf/scribe

Generate API documentation for humans from your Laravel codebase.✍

2.3k13.5M60](/packages/knuckleswtf-scribe)[mozex/anthropic-laravel

Laravel integration for the Anthropic API: facade, config publishing, install command, testing fakes, messages, streaming, tool use, thinking, and batches.

72287.1k1](/packages/mozex-anthropic-laravel)[justbetter/laravel-magento-client

A client to interact with Magento

49108.7k14](/packages/justbetter-laravel-magento-client)[scriptdevelop/whatsapp-manager

Paquete para manejo de WhatsApp Business API en Laravel

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

PHPackages © 2026

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