laravel-json-api/eloquent
Serialize Eloquent models as JSON:API resources.
v4.7.0
1.6M downloads/mo
#2946 most downloaded on Packagist
laravel-json-api/eloquent
What this package is like to depend on
Last release 4 months ago
28 Mar 2026
Ships fairly regularly
a new release about every 3 months
Nearly every release is documented
notes for 20 of 20 stable releases
Nothing withdrawn
no release was ever pulled
6 years old
31 releases · first in 2021
2 releases in the last 12 months
see the full history below
Release timeline
31 releases · Jan 2021 to Mar 2026
2022
2023
2024
2025
2026
Releases
latest 31-
v4.7.028 Mar 2026Release notes
Open source →Added
- Package now supports Laravel 13.
Changed
- Dropped support for
laravel-json-api/corev4.
-
v4.6.030 Sep 2025 -
v4.5.024 Feb 2025 -
v4.4.030 Nov 2024Release notes
Open source →Added
- Allow
laravel-json-api/corev4 and v5.
Fixed
- Remove deprecation notices in PHP 8.4.
- Allow
-
v4.3.131 Oct 2024 -
v4.3.013 Oct 2024Release notes
Open source →Added
- #38 Added
WhereAllandWhereAnyfilters.
Fixed
- #39 Fixed a bug in the eager loader iterator where include
paths starting with the same word were incorrectly removed. E.g.
carandcarOwnerwould result in justcarOwner.
- #38 Added
-
v4.2.026 Aug 2024 -
v4.1.026 Jun 2024 -
v4.0.012 Mar 2024Release notes
Open source →Changed
- Package is now licensed under the MIT license.
- BREAKING Package now requires Laravel 11.
- Minimum PHP version is now
8.2. - Use
assert()within fillable relation field classes rather as an optimisation. - #34 BREAKING The soft delete driver now throws an exception if the model is not successfully soft-deleted. This can happen if a listener or observer on the model aborts the delete operation. Previously the driver just carried on, which was incorrect. The exception has to be thrown in this scenario because we are now in an invalid state - what the client requested and what actually happened does not match up. If developers want to avoid this scenario, they should use authorization or validation logic so that clients get an error response that explains why the soft delete cannot be fulfilled.
Fixed
- #31 BREAKING Use
selfas return type on Eloquent query classes. This is potentially breaking any of these classes have been extended.
-
v3.1.029 Oct 2023Release notes
Open source →Added
- #30 Allow a wider range of Eloquent relations in
the
QueryToManyandQueryToOneclasses. This means packages like culturegr/custom-relation will work with this package.
- #30 Allow a wider range of Eloquent relations in
the
-
v3.0.103 Apr 2023Release notes
Open source →Fixed
- #29 Avoid unnecessary query when there is no need to count a relationship.
-
v3.0.014 Feb 2023 -
v2.3.009 Feb 2023Release notes
Open source →Added
- New
MultiPaginatorthat allows a schema to offer multiple different pagination strategies.
- New
-
v2.2.123 Jan 2023Release notes
Open source →Fixed
- laravel#223 Ensure a model always has fresh data from the database after a write operation, to prevent stale data on cached relationships.
-
v2.2.022 Dec 2022 -
v2.1.104 Apr 2022Release notes
Open source →Fixed
- Pass sparse field sets to the
JsonApiBuilderclass, ensuring that they are present on any generated page objects. Previously this omission meant that page URLs were missing any fields sent by the client.
- Pass sparse field sets to the
-
v2.1.020 Feb 2022Release notes
Open source →Added
- The
Numberfield can now be configured to accept numeric strings by calling theacceptStrings()method on the field.
Fixed
- The
JsonApiBuilderclass was previously converting anulldecoded id to an empty string when querting for a resource id. This has been fixed to passnullto the query builder instead of the empty string, as this was most likely the cause of failures in Postgres.
- The
-
v2.0.009 Feb 2022Release notes
Open source →Added
- Added support for PHP 8.1.
- Added support for Laravel 9.
Changed
- Added return types for internal methods, to remove deprecation warnings on PHP 8.1.
- #20 BREAKING To support PHP 8.1 we needed to rename the
ReadOnlycontract and trait. This is because PHP 8.1 introducedreadonlyas a reserved word. The following changes were made:LaravelJsonApi\Eloquent\Contracts\ReadOnlyis nowIsReadOnly.LaravelJsonApi\Eloquent\Fields\Concerns\ReadOnlyis nowIsReadOnly.
-
v1.0.108 Dec 2021Release notes
Open source →Changed
- The maximum PHP version is now 8.0. This is because this package does not work in its current form with PHP 8.1. The next major version of this package will support PHP 8.1.
Fixed
- laravel#139 Fix the
WhereHasandWhereDoesntHavefilters that have been broken since1.0.0. Previously they have been iterating over filters on the schema to which the relationship belongs - which is incorrect. They now correctly iterate over the filters on the schema on the other side of the relationship (this inverse filter).
-
v1.0.031 Jul 2021Release notes
Open source →Added
- #16 New filter classes that allow you to filter via a
relationship's filters:
HasWhereHasWhereDoesntHave
- #18 Extracted some filter code to the
HasColumnandHasOperatortraits. - Extracted logic to apply sort and filter parameters to an Eloquent query builder into separate classes:
FilterApplicatorandSortApplicator.
Changed
- BREAKING Countable relationships are now not countable by default. This change has been made as the countable feature is not considered production ready as we plan to make breaking changes to the implementation. By changing the default setting to off, you now have to opt-in to this experimental feature.
- Update the
SoftDeleteDriverto useclass_uses_recursiveto check if the model support soft-deleting. - #15 Change the
Scope::make()method to usestaticinstead ofself. - Moved the following into the
QueryBuildernamespace. This change should not affect consuming applications as these classes are meant for internal package use:JsonApiBuilderclass.ModelLoaderclass.Aggregatesnamespace.EagerLoadingnamespace.
Fixed
- #14 Allow a
nullvalue in the filterHasDelimitertrait. - When detecting if a query needs a deterministic order, the page paginator will now also correctly match the qualified primary key of the model. Previously only the unqualified column name was matched. In MySql this led to the deterministic order overriding an existing descending sort for the primary key.
Removed
- The cursor pagination implementation has been moved to a separate package:
laravel-json-api/cursor-pagination. This is so that we can
add support for Laravel's new cursor implementation within this Eloquent package. To migrate, install the new package
and then change your import statements from
LaravelJsonApi\Eloquent\Pagination\CursorPaginationtoLaravelJsonApi\CursorPagination\CursorPagination.
- #16 New filter classes that allow you to filter via a
relationship's filters:
-
v1.0.0-beta.610 Jul 2021 pre-releaseRelease notes
Open source →Added
- Developers can now fully control the extraction of attribute values from a model by providing a closure to the
extractUsing()method on attributes. This callback receives the model, the column name, and the serialized value. Resource classes are still the recommended way of fully customising serialization of models to JSON:API resource objects. However, theextractUsing()method is useful where a developer only needs to customise one or two attribute values on a resource.
Fixed
- #13 The default order by column in the page paginator now has the table name added. This fixes problems with pagination on relationships or other joins.
- Developers can now fully control the extraction of attribute values from a model by providing a closure to the
-
v1.0.0-beta.502 Jun 2021 pre-releaseRelease notes
Open source →Changed
- Updated the
Pagination\ProxyPage::withQuery()method to remove iterable type-hint that has been removed from the page interface. The class was also madefinal, as it is not intended to be extended. Although these changes are technically breaking, they are unlikely to affect consuming applications.
Fixed
- The
JsonApiBuilderwas incorrectly castingnullto an include paths object. On pages, this would incorrectly result in pagination links having aninclude=(empty) parameter. This has been fixed, so include paths will only be set on the pagination links if include paths were actually specified.
- Updated the
-
v1.0.0-beta.426 Apr 2021 pre-releaseRelease notes
Open source →Added
- Schemas now support additional sort field classes, that define how to sort models using sort fields that are not
attributes. Sort field classes must implement the new
SortFieldcontract. Three initial sort classes are available:SortColumn,SortCountableandSortWithCount. - Default sort order for resources can now be defined on the Eloquent schema using the
$defaultSortproperty.
- Schemas now support additional sort field classes, that define how to sort models using sort fields that are not
attributes. Sort field classes must implement the new
-
v1.0.0-beta.322 Apr 2021 pre-releaseRelease notes
Open source →Added
- #10 The
HasManyfield can now handle detaching models from the relationship in three ways. Either it will set the inverse relationship tonull(the default behaviour), or it can delete the related models using either theModel::delete()orModel::forceDelete()methods. The default behaviour matches the behaviour in previous versions, so this change is non-breaking. The behaviour can be configured via thekeepDetachedModels(),deleteDetachedModels()andforceDeleteDetachedModels()methods. - The
HasOnefield can now handle detaching a related model from the relationship in three ways. Either it will set the inverse relationship columns tonull(the default behaviour), or it can delete the related model using eitherModel::delete()orModel::forceDelete(). The default behaviour matches the behaviour in previous versions, so this change is non-breaking. The behaviour can be configured via thekeepDetachedModel(),deleteDetachedModel()andforceDeleteDetachedModel()methods.
- #10 The
-
v1.0.0-beta.220 Apr 2021 pre-releaseRelease notes
Open source →Added
- When using the
Attribute::fillUsing()method to customise filling an attribute value into a model, the closure now receives the entire validated data as its fourth argument. This allows the closure to use other attributes when calculating the value to fill into the model. - Attribute fields now support the columns being on related models, allowing resources to serialize related models as
attributes rather than relationships. This is primarily intended for use with Eloquent
belongsTo,hasOne,hasOneThroughandmorphOnerelations that can have default related models. As part of this feature, the model hydrator will now iterate through loaded relations on the model and save any models that are dirty. - Schemas that have attribute fields with values derived from related models will automatically eager load the relationship by adding the relationship to the default eager load paths for the schema.
Changed
- BREAKING The
Contracts\Fillable::fill()method now expects the entire validated data as its third argument. - BREAKING The
Contracts\Fillableinterface now has amustExist()method. This allows an attribute to indicate that the primary model being filled must exist in the database before the attribute is filled. This is intended for use by attributes that fill related models. - BREAKING The
Contracts\FillableToOneandFillableToManyinterfaces now no longer extend theFillableinterface. This is so that thefill()methods can correctly type-hint the related identifier(s) that are expected when filling a relationship. Effectively theFillablecontract is now intended for use by theidfield and attribute fields.
- When using the
-
v1.0.0-beta.130 Mar 2021 pre-releaseRelease notes
Open source →Added
- To-many relationships are now countable. This allows a client to specify, via a query parameter, which relationships
it wants to be counted. These are used by the implementation to load counts on the Eloquent model, so that the count
values can be added to the relationship's
metamember. Refer to documentation for implementation details. - Package now supports encoding of resource IDs. Resource IDs are correctly decoded when querying the database for matching models.
- To support ID encoding, the following filters have been added specifically for filtering by resource ids:
WhereIdInWhereIdNotIn
Changed
- Made improvements to the eager loading implementation. All classes in the
EagerLoadingnamespace are now marked as internal, as they are not intended for use outside of this package. The public API isJsonApiBuilder::with(),ModelLoader::load()andModelLoader::loadMissing(). - Refactored the Eloquent Schema
loader()method toloaderFor($modelOrModels). - The
JsonApiBuilderclass now expects the schema container as its first argument. To construct a newJsonApiBuilderinstance, theSchema::newQuery()andRelation::newQuery()methods should be used.
Removed
- BREAKING Deleted the
Pagination\Concerns\HasPageMetatrait as the trait is now in thelaravel-json-api/corepackage asLaravelJsonApi\Core\Pagination\Concerns\HasPageMeta.
- To-many relationships are now countable. This allows a client to specify, via a query parameter, which relationships
it wants to be counted. These are used by the implementation to load counts on the Eloquent model, so that the count
values can be added to the relationship's
-
v1.0.0-alpha.512 Mar 2021 pre-releaseRelease notes
Open source →Added
- #6 Package now fully supports soft-deleting resources. If a
model allows soft deleting, but no changes are made to a schema, then deleting the resource will soft-delete it and
that resource will no longer appear in the API. However, if soft-delete capability is to be exposed to the client, a
schema should apply the
SoftDeletestrait from this package and add aFields\SoftDeletefield to their list of fields. Refer to documentation for full list of capabilities. - Added the
WithTrashedandOnlyTrashedfilter classes. - The package now supports multi-resource models. This feature allows a model to be represented as more than one JSON: API resource class and works by having proxy classes for each additional representation of a model. Refer to documentation for examples and details of how to implement multi-resource models.
- #7 Added a new
MorphToManyJSON:API relation field. This wraps several sub-relation fields and presents them as a single polymorphic relationship. The relationship value works both as thedatamember of the relationship object and as a relationship end-point. The relationship is modifiable when every sub-relation is writeable (implements theFillableToManyrelation) and each resource type that can be in the relationship maps to a single sub-relation. Include paths also work, with the include paths only being applied to the sub-relations for which they are valid.
Changed
- BREAKING Deleting a model now uses
Model::deleteinstead ofModel::forceDelete. This change was required when adding full support for soft-deleting resources. - BREAKING Repositories are now injected with a driver which defines the database interactions for the repository. This allows database interactions to be modified, without having to rewrite the repository class - and is used as to implement the soft-deletes feature.
- BREAKING The
sync,attachanddetachmethods on theFillableToManyinterface now type-hintiterableas their return type. Previously they type-hinted the Eloquent collection class. - BREAKING The eager load implementation has been modified to support the new polymorphic to-many relation.
Generally this should not cause any breaking changes, because the eager loading classes were effectively used
internally to handle eager loading. Changes include removing the
skipMissingFieldsmethods (that existed in multiple locations) and rewriting theEagerLoadPathclass.
Removed
- BREAKING Remove the following methods from the
Schemaclass. These were originally added as convenience methods if writing custom controller actions - however, their use is now not suitable as all database querying should be executed via the repository class to ensure Eloquent query builders are created according to the database driver that is in use. The methods are:Schema::newQuery()Schema::query()
- #6 Package now fully supports soft-deleting resources. If a
model allows soft deleting, but no changes are made to a schema, then deleting the resource will soft-delete it and
that resource will no longer appear in the API. However, if soft-delete capability is to be exposed to the client, a
schema should apply the
-
v1.0.0-alpha.427 Feb 2021 pre-releaseRelease notes
Open source →Added
- The Eloquent schema now has
indexQueryandrelatableQuerymethods. These allow filtering for authorization purposes when a list of resources is being retrieved. For instance, it could filter those queries so that only models belonging to the authenticated user are returned. - Can now determine whether multiple filters should return zero-to-one resource using the
Schema::isSingular()method.
Changed
- BREAKING The query builder classes have been updated for changes to the interfaces they implement. This adds
the
withRequest()method and renamesusing()towithQuery(). - #2 BREAKING The
Fillablecontract now type-hints the request class in its read-only method signatures, and allows it to benull. TheReadOnlytrait has been updated, so this is unlikely to affect field classes if the trait has been used. - BREAKING If no request class is provided to the
ModelHydratorclass via its newwithRequest()method, it is now assumed the hydration is occurring outside of a HTTP request. I.e. that the developer is manually triggering the hydration. Without the HTTP request, fields will not be checked for their read-only state and will be filled if the provided data has a value for the field. Implementing libraries must ensure thatwithRequest()is called when filling values provided by a HTTP client. - BREAKING Renamed the
Builderclass toJsonApiBuilder. This change was made as it was confusing what aBuilderreferred to, because Laravel uses this class name for Eloquent builders. - The
Relation::type()method should now be used to set the inverse resource type on a relationship field.
Fixed
- The
Builder::filters()method now correctly yields both the schema's filter and the filters from a relationship, if one is set. Previously the filters were not yielded correctly if there was a relationship. - the
QueryToOneandQueryToManybuilders now correctly use the model's relation name instead of the JSON:API field name when retrieving the relationship object from the model. Previously this would have failed with an error if the model relationship name was not the same as the JSON:API field name.
Deprecated
- The
Relation::inverseType()method is deprecated and will be removed in1.0-stable. UseRelation::type()instead.
- The Eloquent schema now has
-
v1.0.0-alpha.309 Feb 2021 pre-releaseRelease notes
Open source →Added
- Relationship fields now implement the new
isValidated()method, indicating whether the field value should be merged with client provided values for an update request. By default, theBelongsToandMorphTorelations are validated, whereas all other fields are not. This is a sensible default, as theBelongsTo/MorphToidentifiers are stored on the model so are likely to be required for validation. The defaults can be overidden on the fields using themustValidate()ornotValidated()methods. - Eager loading now supports schemas having default eager load paths. This is set via the
$withproperty on the schema, which is returned by the publicwith()method.
Changed
- Moved the existing
EagerLoader,EagerLoadMorphsandEagerLoadPathto theEagerLoadingnamespace.
Fixed
- The
BelongsToManyfield now correctly yields both its own filters and filters from its pivot fields. Previously the filters were not yielded correctly if both the field and pivot had filters.
- Relationship fields now implement the new
-
v1.0.0-alpha.202 Feb 2021 pre-releaseRelease notes
Open source →Added
- #1 Eloquent fields now support serializing models to JSON values. This means that resource classes now become optional: because in the absence of a resource class, the implementation can fall-back on serializing resources using the Eloquent schema.
- BREAKING Split the
Arrfield class into two:ArrayListandArrayHash. This was required because now that the fields are also serializing values, the handling of empty values is different depending on whether it is a list (empty array) or a hash (empty array converted tonull). - Can now set the URI field name for a relationship on the schema's relationship field, using the
withUriFieldName()method. Alternatively, theretainFieldName()method can be used to retain the field name as-is.
-
v1.0.0-alpha.125 Jan 2021 pre-release