PHPackages                             james-harper/data-contracts - 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. [PSR &amp; Standards](/categories/psr-standards)
4. /
5. james-harper/data-contracts

ActiveLibrary[PSR &amp; Standards](/categories/psr-standards)

james-harper/data-contracts
===========================

Creating shareable data contracts based on JSON schema

1.0(5y ago)010PHPPHP ^7.4|^8.0

Since Mar 21Pushed 5y ago1 watchersCompare

[ Source](https://github.com/james-harper/data-contracts)[ Packagist](https://packagist.org/packages/james-harper/data-contracts)[ RSS](/packages/james-harper-data-contracts/feed)WikiDiscussions main Synced today

READMEChangelog (1)Dependencies (12)Versions (2)Used By (0)

Data Contracts
==============

[](#data-contracts)

Data contracts defined here can be shared between multiple services.

This was originally designed for use with Laravel projects in mind, so there are some Laravel-specific convenience methods - dealing with validation rules or automatically converting to API resources, for example.

`Todo` and `User` data contracts have been included as examples. The following commands can be run to remove all traces of them.

```
php cli delete:contract Todo
php cli delete:contract User
```

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

[](#installation)

This can be included in other packages via composer.

```
composer require james-harper/data-contracts:^1.0
```

For any serious use, it is recommended to fork this repository and add data contracts that are appropriate to the domain you are working on. And then use the forked version via `composer`.

Defining Contracts
------------------

[](#defining-contracts)

A data contract is defined in a JSON file which follows the [JSON Schema](https://json-schema.org/) specification.

```
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Person",
  "description": "A Person",
  "type": "object",
  "properties": {
    "id": {
      "type": "integer"
    },
    "name": {
      "type": "string"
    }
  },
  "required": [
    "id",
    "name"
  ]
}
```

The schema definition can be validated against the specification using the following command:

```
php cli validate:schema {name}
```

The id field of the resource (which will be `id` by default) will not be returned from the `describe()` method. If a resource is using something different as its identifier - for example `guid` - the contract's `protected static $id` property can be updated to reflect this.

```
use DataContracts\DataContract;

class User extends DataContract
{
  protected $schema = 'path/to/file.json';
  protected static $id = 'guid';
}
```

PHP data contracts can be created by extending `DataContracts\DataContract` and then setting the `$schema` property as a link to the JSON definition. Schema paths should be relative to the project root. A `RuntimeException` will be thrown if no schema is defined.

```
use DataContracts\DataContract;

class User extends DataContract
{
  protected $schema = 'path/to/file.json';
}
```

DataContracts can be generated using the following composer command:

```
./cli make:contract {Name}
```

Usage
-----

[](#usage)

Each DataContract has a static `describe()` method which will return all of the fields on the contract (that are not considered `private`) and an `all()` method that will display everything.

There is also a `validationRules()` method that can be used to get any [validation rules](https://laravel.com/docs/8.x/validation#available-validation-rules) for the contract. These should use Laravel validation rules so that the output can be used directly for Request validation in Laravel projects. Transformers must be applied to get valid Laravel rules from a JSON Schema: these can be found in `src/Rules`.

```
use DataContracts\User as UserContract;

UserContract::describe();
// ['first_name', 'last_name', 'email', 'role']
UserContract::all();
// ['first_name', 'last_name', 'email', 'role']
UserContract::validationRules();
// ['first_name' => ['required']...]
```

Some helpers exist to make working with validation rules easier. `validationRulesOptional()` gets all rules but removes any `required` rules. This is useful for partial updates when not all fields would be expected. And `rulesExcept($rule)` can be used to filter out the chosen rule.

```
UserContract::validationRulesOptional();
// ['account_id' => ['numeric']...]
UserContract::rulesExcept('numeric');
UserContract::rulesExcept(['numeric', 'min'])
```

DataContracts can be used anywhere, but should be defined in this repository for shareability purposes.

### Usage with Laravel Eloquent models

[](#usage-with-laravel-eloquent-models)

A DataContract can be used to filter Eloquent models down to only fields that are on the DataContract

```
$user = new User([
    'id' => 1,
    'name' => 'James',
    'email' => 'james@example.com',
    'extraField' => 123,
]);
UserContract::fromEloquent($user);
// ['id' => 'James', 'name' => 'James', 'email' => 'james@example.com']
```

### Usage with Laravel API Resources

[](#usage-with-laravel-api-resources)

Simarly, DataContracts can be used to filter [Laravel API Resources](https://laravel.com/docs/8.x/eloquent-resources) down to only fields that are on the DataContract

```
use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource {
    public function toArray()
    {
        return UserContract::fromResource($this);
    }
}
```

If any additional transformation needs to be performed, it is a case of simply overwriting the default transformation

```
use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource {
    public function toArray()
    {
        $user = UserContract::fromResource($this);
        $user['name'] = strtoupper($this->name);
        return $user;
    }
}
```

CLI Tool
--------

[](#cli-tool)

A CLI tool has been created to simplify common tasks and encourage the use of consistent patterns. It has been designed in a similar way to Laravel's `artisan` so it should feel familiar to use. It can be run using `./cli` or `php cli`. Running the tool without any additional arguments will show the help screen which lists all available commands.

The following commands can be used:

- Flush cache
    - `php cli flush:cache`
    - `php cli flush`
- Run linting
    - `php cli lint:run`
    - `php cli lint`
    - `php cli lint --fix`
- Generate console command
    - `php cli make:command `
    - `php cli new `
- Generate data contract
    - `php cli make:contract `
    - `php cli schema `
- Delete data contract
    - `php cli delete:contract `
    - `php cli delete `
    - `php cli remove `
- Generate console formatting pattern
    - `php cli make:pattern  `
    - `php cli make:pattern   `
    - `php cli pattern  `
- Generate validation rule
    - `php cli make:rule `
    - `php cli rule `
- Run tests
    - `php cli test:run`
    - `php cli test`
    - Run group(s) of tests
    - `php cli test cache`
    - `php cli test rules,schemas`
    - `php cli test cache,contracts,rules,schemas,validation`
- Update CHANGELOG.md
    - `php cli update:changelog`
    - `php cli changelog`
    - `php cli make:log`
    - `php cli generate:log`
- Validate JSON Schema
    - `php cli validate:schema `
    - `php cli validate `
- Validate all JSON Schemas
    - `php cli validate:all`

For additional help with any command the following command can be run:

- `php cli -h `
- For example:
    - `php cli -h make:command`
    - `php cli -h new`

CLI documentation is stored in markdown files in `console/docs`

Tab completion for the CLI can be enabled by running the following command:

```
source console/scripts/cli_autocompletion.sh
```

Notes
-----

[](#notes)

- Since `DataContracts` do not change until there is an update to this package, they are a good candidate to be cached. There is an in-built caching support. By default `Illuminate\Cache` is used with the `file` driver, but any PSR-16 compliant cache can be set with `DataContract::setCache($cache)`
- It is recommended to alias `DataContracts` to have a `Contract` suffix to avoid them being confused with models. For example: `use DataContracts\User as UserContract`. A statement like `User::all()` would be valid for both an Eloquent model and a DataContract. `UserContract::all()` makes it much easier to tell at a glance.
- In order to avoid autoloading issues, any sub-directories within directories that are configured to use PSR-4 autoloading (`console/`, `src/`, `tests/`) should begin with an uppercase letter. Folders that are not intended to contain any `.php` files (such as `console/scripts`) do not need to follow this rule.
- `composer test` can be used to run the whole test suite or the CLI test command can be used `php cli test cache,contracts,rules,schemas,validation` to run just a specific group of tests.
- JSON Schema dates/times can be quite fiddly at times. Here are some examples of the formats that can be used. `"full-date full-time"` will match `"Y-m-d h:i:s"`. `"date-time"` expects a T between the date and time portions.

```
date-fullyear   = 4DIGIT
date-month      = 2DIGIT  ; 01-12
date-mday       = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on
                            ; month/year
time-hour       = 2DIGIT  ; 00-23
time-minute     = 2DIGIT  ; 00-59
time-second     = 2DIGIT  ; 00-58, 00-59, 00-60 based on leap second
                            ; rules
time-secfrac    = "." 1*DIGIT
time-numoffset  = ("+" / "-") time-hour ":" time-minute
time-offset     = "Z" / time-numoffset

partial-time    = time-hour ":" time-minute ":" time-second
                    [time-secfrac]
full-date       = date-fullyear "-" date-month "-" date-mday
full-time       = partial-time time-offset

date-time       = full-date "T" full-time

```

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity5

Limited adoption so far

Community4

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

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

Unknown

Total

1

Last Release

1875d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2efe37e9a25b9c506f132361f74397e15b8a9973c1e31cf621b48af0adcde987?d=identicon)[james-harper](/maintainers/james-harper)

---

Tags

data-contractsjsonjson-schemalaravelphp

###  Code Quality

TestsPest

Code StylePHP CS Fixer

### Embed Badge

![Health badge](/badges/james-harper-data-contracts/health.svg)

```
[![Health](https://phpackages.com/badges/james-harper-data-contracts/health.svg)](https://phpackages.com/packages/james-harper-data-contracts)
```

###  Alternatives

[laravel/passport

Laravel Passport provides OAuth2 server support to Laravel.

3.4k85.0M529](/packages/laravel-passport)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9682.1M97](/packages/roots-acorn)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k12.1M99](/packages/laravel-pulse)[genealabs/laravel-model-caching

Automatic caching for Eloquent models.

2.4k4.8M26](/packages/genealabs-laravel-model-caching)[laravel-zero/framework

The Laravel Zero Framework.

3371.4M368](/packages/laravel-zero-framework)[tightenco/jigsaw

Simple static sites with Laravel's Blade.

2.2k438.5k29](/packages/tightenco-jigsaw)

PHPackages © 2026

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