PHPackages                             larsmbergvall/json-api-resources-for-laravel - 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. larsmbergvall/json-api-resources-for-laravel

ActiveLibrary[API Development](/categories/api)

larsmbergvall/json-api-resources-for-laravel
============================================

Simple JSON:API resource package for Laravel

0.3.0(3y ago)09[3 PRs](https://github.com/larsmbergvall/json-api-resources-for-laravel/pulls)MITPHPPHP ^8.1|^8.2

Since Mar 14Pushed 2y ago1 watchersCompare

[ Source](https://github.com/larsmbergvall/json-api-resources-for-laravel)[ Packagist](https://packagist.org/packages/larsmbergvall/json-api-resources-for-laravel)[ Docs](https://github.com/larsmbergvall/json-api-resources-for-laravel)[ RSS](/packages/larsmbergvall-json-api-resources-for-laravel/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (3)Dependencies (13)Versions (7)Used By (0)

JSON:API Resources for Laravel
==============================

[](#jsonapi-resources-for-laravel)

Table of Contents
-----------------

[](#table-of-contents)

- [Example](#example)
- [Installation](#installation)
- [Usage](#usage)
- [Attributes](#attributes)
    - [JsonApiType](#jsonapitypestring)
    - [JsonApiIncludeAttributes](#jsonapiincludeattributesstring)
    - [JsonApiIncludeRelationships](#jsonapiincluderelationshipsstring)
- [Creating JsonApiResources](#creating-jsonapiresources)
- [Middleware](#middleware)
- [The JsonApiResource class](#the-jsonapiresource-class)
- [The JsonApiResourceCollection class](#the-jsonapiresourcecollection-class)
- [Error transformation](#error-transformation)
- [Testing](#testing)
- [Changelog](#changelog)
- [Credits](#credits)
- [License](#license)

Example
-------

[](#example)

This is an example of the output generated by this package:

```
    public function books()
    {
        $books = Book::with(['author.country'])->take(2)->get();

        return JsonApiResourceCollection::make($books)->withIncluded();
    }
```

Returns this:

```
{
  "data": [
    {
      "id": "1",
      "type": "books",
      "attributes": {
        "title": "Dolores Dolor Totam",
        "year": 1871
      },
      "relationships": {
        "author": {
          "data": {
            "id": "1",
            "type": "author"
          }
        }
      },
      "links": {},
      "meta": {}
    },
    {
      "id": "2",
      "type": "books",
      "attributes": {
        "title": "Velit Quo Omnis",
        "year": 1969
      },
      "relationships": {
        "author": {
          "data": {
            "id": "2",
            "type": "author"
          }
        }
      },
      "links": {},
      "meta": {}
    }
  ],
  "included": [
    {
      "id": "1",
      "type": "author",
      "attributes": {
        "name": "Rylee Heller DDS",
        "country_id": 18,
        "bio": "Non iusto porro maxime. Quibusdam provident architecto magni sed id et. Voluptatem sint a numquam eius omnis aut.\n\nVoluptas quis voluptatem et fuga aspernatur eaque. Necessitatibus possimus iure corporis et quasi cum. Blanditiis quis sapiente ut dolores. Dolorem odio et quas aut et nihil qui.\n\nAut quod sint numquam. Ullam id odio velit neque non. Aut recusandae sint explicabo ut veritatis aliquid harum.",
        "born_at": "1986-10-22 08:00:02",
        "created_at": "2023-03-09 12:55:20",
        "updated_at": "2023-03-09 12:55:20"
      },
      "relationships": {},
      "links": {},
      "meta": {}
    },
    {
      "id": "2",
      "type": "author",
      "attributes": {
        "name": "Ms. Rosella Quigley Sr.",
        "country_id": 12,
        "bio": "Architecto voluptas nobis sed. Ea qui quas voluptatem est nisi. Voluptatem et quis ut asperiores fuga autem blanditiis repellendus. Qui non sapiente esse quasi corporis fugit ut aut.\n\nDolorem id dolore quis qui ullam dolorem. Qui voluptatibus quia reprehenderit dolor aut est corrupti. Debitis debitis cum vitae nam quis fugit nemo. Quia labore et delectus est qui.\n\nNumquam accusantium et in. Non tenetur iure explicabo expedita sint. Quam sit qui doloremque asperiores ducimus impedit enim. In recusandae et cumque nisi ea laudantium in.",
        "born_at": "1996-08-07 13:15:36",
        "created_at": "2023-03-09 12:55:20",
        "updated_at": "2023-03-09 12:55:20"
      },
      "relationships": {},
      "links": {},
      "meta": {}
    }
  ]
}
```

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

[](#installation)

You can install the package via composer:

```
composer require larsmbergvall/json-api-resources-for-laravel
```

**It is recommended** to use the middleware, either on all API calls:

```
// ./app/Http/Kernel.php

protected $middlewareGroups = [
    // ...
    // Web middleware and such
    // ...
    'api' => [
        // Other api middlewares
        JsonApiMiddleware::class,
    ],
]
```

Or, on a per-route basis:

```
// ./routes/api.php

Route::prefix('/v1')
    ->middleware(JsonApiMiddleware::class)
    ->group(function () {
        // Api v1 routes
    });
```

Usage
-----

[](#usage)

### Attributes

[](#attributes)

This package uses PHP 8 attributes to annotate Eloquent models. There is no need for additional resource classes. Attributes are used like this:

```
use Larsmbergvall\JsonApiResourcesForLaravel\Attributes\JsonApiIncludeAttributes;
use Larsmbergvall\JsonApiResourcesForLaravel\Attributes\JsonApiIncludeRelationships;
use Larsmbergvall\JsonApiResourcesForLaravel\Attributes\JsonApiType;

#[JsonApiType('books')] // Change `type` property
#[JsonApiIncludeAttributes(['title', 'isbn', 'year'])] // Which of the models attributes to include
 // Which of the models relationships to include.
 // NOTE: it only includes eager loaded relationships regardless of this attribute
#[JsonApiIncludeRelationships(['author'])]
class Book extends Model
{
    // ...
}
```

#### `#[JsonApiType(string)]`

[](#jsonapitypestring)

This attribute can be used to change the value of the `type` property in the final output json. This attribute is optional. If it is not used, `type` will be set to the singular version of the models name, i.e. `'type' => 'book'`.

#### `#[JsonApiIncludeAttributes(string[])]`

[](#jsonapiincludeattributesstring)

This attribute can be used to specify which of the models attributes should be included in the final output json. This attribute is optional. If it is not used, all visible model attributes will be included. It uses `$model->attributesToArray()` to get the attributes, so it will respect any `$hidden` fields.

#### `#[JsonApiIncludeRelationships(string[])]`

[](#jsonapiincluderelationshipsstring)

This attribute can be used to specify which of the models relationships should be included. This attribute is optional. If it is not used, no relationships will be included in the final output json.

**NOTE:** Regardless of what is included by this attribute, `JsonApiResource` only includes eager loaded relationships.

### Creating JsonApiResources

[](#creating-jsonapiresources)

If you have a single model, you should use `JsonApiResource`:

```
use Larsmbergvall\JsonApiResourcesForLaravel\JsonApi\JsonApiResource;

public function show(Book $book): JsonApiResource
{
    return JsonApiResource::make($book);
}
```

If you have a collection of models, you should use `JsonApiResourceCollection`:

```
use Larsmbergvall\JsonApiResourcesForLaravel\JsonApi\JsonApiResourceCollection;

public function index(): JsonApiResource
{
    // Can also be used with pagination:
    // return JsonApiResourceCollection::make(Book::orderBy('title')->paginate());

    return JsonApiResourceCollection::make(Book::all());
}
```

If you need to manually return a JSON:API response, or don't want to use the middleware, you can use the `jsonApiResponse()`-helper:

```
// return jsonApiResponse(JsonApiResource::make($book));
return jsonApiResponse($content, $status, $headers)
```

It sets the correct `Content-Type` header for JSON:API responses. Note that it doesn't transform validation errors.

Middleware
----------

[](#middleware)

The middleware primarily takes care of two things:

1. Making sure the response that is returned has the correct headers etc.
2. Transforming Laravels validation errors into the expected JSON:API error format

The middleware should be executed *after* any other middlewares that could change the `Content-Type` header of the response.

The JsonApiResource class
-------------------------

[](#the-jsonapiresource-class)

This class has a few public methods that you can use. Most likely you will not need to, because the `JsonApiResourceCollection` class handles that stuff automatically.

However, there is an important method: `withIncluded()`. By default, a `JsonApiResource` does not include it's related data. If you however run `$resource->withIncluded()` (or `JsonApiResource::make($book)->withIncluded())` it will do so.

**NOTE:** It only includes eager loaded relationships, so if you need to exclude something for a certain api route you can just choose not to load a relationship. However, it includes related data recursively, meaning that it also includes data related to the included data.

The JsonApiResourceCollection class
-----------------------------------

[](#the-jsonapiresourcecollection-class)

This class also has the `withIncluded()` method that you can use to include any related data to your resources. Just as with the `JsonApiResource`, it only includes relations that are already loaded. However, it includes related data recursively, meaning that it also includes data related to the included data.

### Error transformation

[](#error-transformation)

When validation fails in Laravel, normally you get a response that looks like this:

```
{
  "message": "The data.attributes.foo field is required.",
  "errors": {
    "data.attributes.foo": [
      "The data.attributes.foo field is required."
    ]
  }
}
```

But with the JsonApiMiddleware, this response changes to:

```
{
  "errors": [
    {
      "status": "422",
      "title": "Unprocessable Content",
      "detail": "The data.attributes.foo field is required.",
      "source": {
        "pointer": "data/attributes/foo",
        "parameter": "foo"
      }
    }
  ]
}
```

Testing
-------

[](#testing)

There are some testing utilities on the `JsonApiResource` and `JsonApiResourceCollection` classes that you can utilize to test your application.

Note that more testing utilities will be coming in future versions!

### assertHasData

[](#asserthasdata)

```
$author = Author::factory()->create();
$resource = JsonApiResource::make($author);

$id = $author->id;
$type = 'author';
$resource->assertHasData($id, $type);
```

### assertDoesntHaveData

[](#assertdoesnthavedata)

```
$author = Author::factory()->create();
$resource = JsonApiResourceCollection::make(collect([$author]));

$id = $author->id + 999;
$type = 'author';
$resource->assertDoesntHave($id, $type);
```

This is the opposite of `assertHasData`. It will fail if it finds the expected data.

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Credits
-------

[](#credits)

- [Lars Bergvall](https://github.com/larsmbergvall)
- [All Contributors](../../contributors)
- [Spatie](https://spatie.be/) for the amazing Laravel package skeleton

License
-------

[](#license)

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

###  Health Score

23

—

LowBetter than 27% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity4

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor2

2 contributors hold 50%+ of commits

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 ~1 days

Total

3

Last Release

1153d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ca3d1db5f7456791074b1f27186dfa46b2c0440de305883f432e090ef9f63fa5?d=identicon)[larsmbergvall](/maintainers/larsmbergvall)

---

Top Contributors

[![larsmbergvall](https://avatars.githubusercontent.com/u/35922396?v=4)](https://github.com/larsmbergvall "larsmbergvall (9 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (5 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (5 commits)")

---

Tags

laravelJSON-APIlarsmbergvalljson-api-resources-for-laravel

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/larsmbergvall-json-api-resources-for-laravel/health.svg)

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

###  Alternatives

[dedoc/scramble

Automatic generation of API documentation for Laravel applications.

2.0k7.8M57](/packages/dedoc-scramble)[scalar/laravel

Render your OpenAPI-based API reference

6183.9k2](/packages/scalar-laravel)[ryangjchandler/bearer

Minimalistic token-based authentication for Laravel API endpoints.

8129.8k](/packages/ryangjchandler-bearer)[combindma/laravel-facebook-pixel

Meta pixel integration for Laravel

4956.9k](/packages/combindma-laravel-facebook-pixel)[stechstudio/laravel-hubspot

A Laravel SDK for the HubSpot CRM Api

2971.0k](/packages/stechstudio-laravel-hubspot)[njoguamos/laravel-plausible

A laravel package for interacting with plausible analytics api.

208.8k](/packages/njoguamos-laravel-plausible)

PHPackages © 2026

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