# Introduction

json-api-server is a JSON:API (opens new window) server implementation in PHP.

It allows you to define your API's schema, and then use an adapter to connect it to your application's models and database layer, without having to worry about any of the server boilerplate, routing, query parameters, or JSON:API document formatting.

Based on your schema definition, the package will serve a complete JSON:API that conforms to the spec (opens new window), including support for:

  • Showing individual resources (GET /api/articles/1)
  • Listing resource collections (GET /api/articles)
  • Sorting, filtering, pagination, and sparse fieldsets
  • Compound documents with inclusion of related resources
  • Creating resources (POST /api/articles)
  • Updating resources (PATCH /api/articles/1)
  • Deleting resources (DELETE /api/articles/1)
  • Error handling

The schema definition is extremely powerful and lets you easily apply permissions, transformations, validation, and custom filtering and sorting logic to build a fully functional API in minutes.

# Example

The following example uses Eloquent models in a Laravel application. However, json-api-server can be used with any framework that can deal in PSR-7 Requests and Responses. Custom adapters can be used to support other ORMs and data persistence layers.

use App\Models\{Article, Comment, User};
use Tobyz\JsonApiServer\JsonApi;
use Tobyz\JsonApiServer\Schema\Type;
use Tobyz\JsonApiServer\Laravel\EloquentAdapter;
use Tobyz\JsonApiServer\Laravel;

$api = new JsonApi('http://example.com/api');

$api->resource('articles', new EloquentAdapter(Article::class), function (Type $type) {
    $type->attribute('title')
        ->writable()
        ->validate(Laravel\rules('required'));

    $type->hasOne('author')->type('users')
        ->includable()
        ->filterable();

    $type->hasMany('comments')
        ->includable();
});

$api->resource('comments', new EloquentAdapter(Comment::class), function (Type $type) {
    $type->creatable(Laravel\authenticated());
    $type->updatable(Laravel\can('update-comment'));
    $type->deletable(Laravel\can('delete-comment'));

    $type->attribute('body')
        ->writable()
        ->validate(Laravel\rules('required'));

    $type->hasOne('article')
        ->writable()->once()
        ->validate(Laravel\rules('required'));

    $type->hasOne('author')->type('users')
        ->writable()->once()
        ->validate(Laravel\rules('required'));
});

$api->resource('users', new EloquentAdapter(User::class), function (Type $type) {
    $type->attribute('firstName')->sortable();
    $type->attribute('lastName')->sortable();
});

/** @var Psr\Http\Message\ServerRequestInterface $request */
/** @var Psr\Http\Message\ResponseInterface $response */
try {
    $response = $api->handle($request);
} catch (Exception $e) {
    $response = $api->error($e);
}