PHPackages                             juampi92/api-resources - 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. juampi92/api-resources

ActiveLibrary[API Development](/categories/api)

juampi92/api-resources
======================

Manage your resources maintaining API versioning

v1.10.0(1y ago)112930.9k↓38.9%211MITPHPPHP ^7.4|^8.0|^8.1|^8.2CI passing

Since Feb 17Pushed 1y ago6 watchersCompare

[ Source](https://github.com/juampi92/api-resources)[ Packagist](https://packagist.org/packages/juampi92/api-resources)[ Docs](https://github.com/juampi92/api-resources)[ GitHub Sponsors](https://github.com/Juampi92)[ RSS](/packages/juampi92-api-resources/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (6)Versions (15)Used By (1)

Api Resources
=============

[](#api-resources)

[![Latest Version](https://camo.githubusercontent.com/1fee615da20c697d117eeadbe0a8de49eb3c60cc058c79c661fa42d18b72c398/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652f6a75616d706939322f6170692d7265736f75726365732e7376673f7374796c653d666c61742d737175617265)](https://github.com/juampi92/api-resources/releases)[![GitHub Tests Action Status](https://camo.githubusercontent.com/73383c44605eaf4369e2280d24fb4f696caa46f14f4b58fb871053fdf745029d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6a75616d706939322f6170692d7265736f75726365732f72756e2d74657374732e796d6c3f6272616e63683d6d6173746572266c6162656c3d5465737473267374796c653d666c61742d737175617265)](https://github.com/juampi92/api-resources/actions?query=workflow%3ATests+branch%3Amaster)[![Total Downloads](https://camo.githubusercontent.com/732120aa389c860bc3f9ae0ab63b4e1d805f07b50d0bcb60260fb81c83aa411f/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6a75616d706939322f6170692d7265736f75726365732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/juampi92/api-resources)[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)

Manage your resources maintaining API versioning. With a simple middleware separate routes by api version, and smart instanciate [Http\\Resources](https://laravel.com/docs/5.5/eloquent-resources) based on this version.

Add the middleware `'api.v:2'` on your api/v2 group.

And then `api_resource('App\User')->make($user)` is the same as `new App\Http\Resources\App\v2\User($user)`, but version free.

```
App\Http\Resources\
  |- App\
    |- v1\
      |- User.php
    |- v2\
      |- Rank.php
      |- User.php
```

### The idea behing this

[](#the-idea-behing-this)

A while back I faced this API versioning problem, so I wrote this [medium post](https://medium.com/@juampi92/api-versioning-using-laravels-resources-b1687a6d2c22) with my solution and this package reflects this.

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

[](#installation)

You can install this package via composer using:

```
composer require juampi92/api-resources
```

The package will automatically register itself.

### Config

[](#config)

To publish the config file to `config/api.php` run:

```
php artisan vendor:publish --provider="Juampi92\APIResources\APIResourcesServiceProvider"
```

This will publish a file `api.php` in your config directory with the following content:

```
return [
  /*
  |--------------------------------------------------------------------------
  | API Version
  |--------------------------------------------------------------------------
  |
  | This value is the latest version of your api. This is used when
  | there's no specified version on the routes, so it will take this as the
  | default, or latest.
   */
   'version' => '1',

   /*
   |--------------------------------------------------------------------------
   | Resources home path
   |--------------------------------------------------------------------------
   |
   | This value is the base folder where your resources are stored.
   | When using multiple APIs, you can leave it as a string if every
   | api is in the same folder, or as an array with the APIs as keys.
    */
    'resources_path' => 'App\Http\Resources',

    /*
    |--------------------------------------------------------------------------
    | Resources
    |--------------------------------------------------------------------------
    |
    | Here is the folder that has versioned resources. If you store them
    | in the root of 'resources_path', leave this empty or null.
     */
    'resources' => 'App'
 ];
```

### Middleware

[](#middleware)

Install this middleware on your `Http/Kernel.php` under the `$routeMiddleware`

```
  protected $routeMiddleware = [
    ...
    'api.v'           => \Juampi92\APIResources\Middleware\APIversion::class,
    ...
  ];
```

Configure correctly
-------------------

[](#configure-correctly)

For this package to work, you need to understand how it requires resources.

If we have the following config:

```
[
  'version' => '2',
  'resources_path' => 'App\Http\Resources',
  'resources' => 'Api'
]
```

This means that if you include the `Api\User` resource, it will instantiate `App\Http\Resources\Api\v2\User`.

`Api` works for sub organizing your structure, but you can put your Resources versionate folders in the root, like this:

```
[
  'version' => '2',
  'resources_path' => 'App\Http\Resources',
  'resources' => ''
]
```

Now if we include `User`, it will instantiate `App\Http\Resources\v2\User`.

### Fallback

[](#fallback)

When you use a version that is **NOT** the latest, if you try to include a Resource that's **NOT** defined inside that version's directory, this will automatically fallback in the **LATEST** version.

This way you don't have to duplicate new resources on previous versions.

Usage
-----

[](#usage)

### Middleware

[](#middleware-1)

When you group your API routes, you should now apply the middleware `api.v` into the group like this:

```
// App v1 API
Route::group([
    'middleware' => ['app', 'api.v:1'],
    'prefix'     => 'api/v1',
], function ($router) {
    require base_path('routes/app_api.v1.php');
});

// App v2 API
Route::group([
    'middleware' => ['app', 'api.v:2'],
    'prefix'     => 'api/v2',
], function ($router) {
    require base_path('routes/app_api.v2.php');
});
```

That way, if you use the Facade, you can check the current version by doing `APIResource::getVersion()` and will return the version specified on the middleware.

### Facade

[](#facade)

There are many ways to create resources. You can use the Facade accessor:

```
use Juampi92\APIResources\Facades\APIResource;

class SomethingController extends Controller {
    ...

    public function show(Something $model)
    {
      return APIResource::resolve('App\Something')->make($model);
    }
}
```

### Global helper

[](#global-helper)

```
class SomethingController extends Controller {
    ...

    public function show(Something $model)
    {
      return api_resource('App\Something')->make($model);
    }
}
```

### Collections

[](#collections)

Instead of `make`, use `collection` for arrays, just like Laravel's documentation.

```
class SomethingController extends Controller {
    ...

    public function index()
    {
      $models = Something::all();
      return api_resource('App\Something')->collection($models);
    }
}
```

If you wanna use a ResourceCollection, you might wanna rewrite the `collects()` method.

```
class UserCollection extends ResourceCollection
{
    protected function collects()
    {
        return APIResource::resolveClassname('App\User');
    }
}
```

This way, the ResourceCollection will always have the correct class.

`resolveClassname` will try to use the current version of the class, but if it's not possible, will use the latest.

Nested resources
----------------

[](#nested-resources)

To take advantage of the **fallback** functionality, it's recomended to use `api_resource` inside the resources. This way you preserve the right version, or the latest if it's not defined.

```
class Post extends Resource {
    public function toArray($request)
    {
      return [
        'title' => $this->title,
          ...
        'user' => api_resource('App\User')->make($this->user);
      ];
    }
}
```

Multiple APIs
-------------

[](#multiple-apis)

There might be the case where you have more than one API living on the same project, but using diferent versions. This app supports that. First, the `config/api.php`

```
return [
  'default' => 'api',
  'version' => [
    'api'     => '2',
    'desktop' => '3'
  ],
  'resources_path' => 'App\Http\Resources'
  // Or one path each
  'resources_path' => [
    'api'     => 'App\Http\Resources',
    'desktop' => 'Vendorname\ExternalPackage\Resources'
  ],
  'resources' => [
    'api'     => 'Api',
    'desktop' => ''
  ],
];
```

Then, you need to configure the **middleware**. Instead of using `api.v:1`, you now have to specify the name: `api.v:3,desktop`.

Then the rest works as explained before.

API Route
---------

[](#api-route)

Sometimes you must return a route url on the api response. If you wanna keep the api version (which is always the current version), api-resources has the solution for you.

```
// When defining the routes
Route::group([
    'middleware' => ['app', 'api.v:1'],
    'prefix'     => 'api/v1',
    // Using name on a group will prefix it.
    'name'       => 'api.v1.',
], function ($router) {
    Route::get('/auth/login', [
        // This will be api.v1.auth.login
        'name' => 'auth.login',
        'use' => '...',
    ]);
});
```

With this we have `api.v1.auth.login` and `api.v2.auth.login` when creating a new version.

Now just do `api_route('api.auth.login')`, and it will output `/api/v1/auth/login` or `/api/v2/auth/login` accordingly.

### How it works

[](#how-it-works)

It's grabbing the config `api.resources` and doing a strtolower, so if you have `'resources' => 'App'`, will transform `app.auth.login` into `app.v1.auth.login`. If you need to customize it, add a new config entry in `config/api.php` like this:

```
    /*
    |--------------------------------------------------------------------------
    | Route prefix
    |--------------------------------------------------------------------------
    |
    | By default, the route prefix is the lowercase resources folder.
    | So it'd be `app.v1.auth.login` has the prefix `app`.
    |
    | Using `app` will do api_route(`app.auth.login`) => `app.v?.auth.login`.
    |
     */

    'route_prefix' => 'app'
```

If works with multiple APIs as explained before.

Testing
-------

[](#testing)

Run the tests with:

```
vendor/bin/phpunit
```

Credits
-------

[](#credits)

- [Juan Pablo Barreto](https://github.com/juampi92)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

56

—

FairBetter than 98% of packages

Maintenance49

Moderate activity, may be stable

Popularity51

Moderate usage in the ecosystem

Community21

Small or concentrated contributor base

Maturity83

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 91.4% 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 ~220 days

Recently: every ~296 days

Total

13

Last Release

370d ago

Major Versions

v1.6.0 → v2.x-dev2022-02-12

PHP version history (4 changes)v1.0.0PHP &gt;=7.0.0

v2.x-devPHP ^8.1

v1.7.0PHP ^7.4|^8.0|^8.1

v1.8.0PHP ^7.4|^8.0|^8.1|^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/1f8d31c9bb6d7862e21aac7af0f7b2615dc06485b4c30b19b8d9fdffaa42c712?d=identicon)[juampi92](/maintainers/juampi92)

---

Top Contributors

[![juampi92](https://avatars.githubusercontent.com/u/2080215?v=4)](https://github.com/juampi92 "juampi92 (32 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (1 commits)")[![olimarferraz](https://avatars.githubusercontent.com/u/6013739?v=4)](https://github.com/olimarferraz "olimarferraz (1 commits)")[![Sithira](https://avatars.githubusercontent.com/u/8215941?v=4)](https://github.com/Sithira "Sithira (1 commits)")

---

Tags

apilaravelphpapilaravel

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/juampi92-api-resources/health.svg)

```
[![Health](https://phpackages.com/badges/juampi92-api-resources/health.svg)](https://phpackages.com/packages/juampi92-api-resources)
```

###  Alternatives

[essa/api-tool-kit

set of tools to build an api with laravel

52680.5k](/packages/essa-api-tool-kit)[resend/resend-laravel

Resend for Laravel

1191.4M6](/packages/resend-resend-laravel)[mollie/laravel-mollie

Mollie API client wrapper for Laravel &amp; Mollie Connect provider for Laravel Socialite

3624.1M28](/packages/mollie-laravel-mollie)[dragon-code/laravel-json-response

Automatically always return a response in JSON format

1118.6k1](/packages/dragon-code-laravel-json-response)[surface/laravel-webfinger

A Laravel package to create an ActivityPub webfinger.

113.8k](/packages/surface-laravel-webfinger)

PHPackages © 2026

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