# Extensions

[Extensions](https://jsonapi.org/format/1.1/#extensions) allow your API to support additional functionality that is not part of the base specification.

## Defining Extensions

Extensions can be defined by extending the `Tobyz\JsonApiServer\Extension\Extension` class and implementing two methods: `uri` and `process`.

You must return your extension's unique URI from `uri`. 

For every request that includes your extension in the media type, the `handle` method will be called. If your extension is able to handle the request, it should return a PSR-7 response. Otherwise, return null to let the normal handling of the request take place.

```php
use Tobyz\JsonApiServer\Extension\Extension;
use Psr\Http\Message\ResponseInterface;

use function Tobyz\JsonApiServer\json_api_response;

class MyExtension extends Extension
{
    public function uri(): string
    {
        return 'https://example.org/my-extension';
    }

    public function handle(Context $context): ?ResponseInterface;
    {
        if ($context->getPath() === '/my-extension') {
            return json_api_response([
                'my-extension:greeting' => 'Hello world!'
            ]);
        }
        
        return null;
    }
}
```

::: warning
The current implementation of extensions has no support for augmentation of standard API responses. This API may change dramatically in the future. Please [create an issue](https://github.com/tobyzerner/json-api-server/issues/new) if you have a specific use-case you want to achieve.
:::

## Registering Extensions

Extensions can be registered on your `JsonApi` instance using the `extension` method:

```php
use Tobyz\JsonApiServer\JsonApi;

$api = new JsonApi('/api');

$api->extension(new MyExtension());
```

The `JsonApi` class will automatically perform appropriate [content negotiation](https://jsonapi.org/format/1.1/#content-negotiation-servers) and activate the specified extensions on each request.

## Atomic Operations

An implementation of the [Atomic Operations](https://jsonapi.org/ext/atomic/) extension is available at `Tobyz\JsonApi\Extension\Atomic`.

When using this extension, you are responsible for wrapping the `$api->handle` call in a transaction to ensure any database (or other) operations performed are actually atomic in nature. For example, in Laravel:

```php
use Illuminate\Support\Facades\DB;
use Tobyz\JsonApiServer\Extension\Atomic;
use Tobyz\JsonApiServer\JsonApi;

$api = new JsonApi('/api');

$api->extension(new Atomic());

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