### Installing json-api-server with Composer (Bash) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/install.md This command installs the `tobyzerner/json-api-server` package using Composer, the PHP dependency manager. It fetches the latest stable version of the library and adds it to your project's dependencies, making it available for use. ```Bash composer require tobyz/json-api-server ``` -------------------------------- ### Example HTTP Request with Sorting (HTTP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This HTTP request example demonstrates how to use the `sort` query parameter to order resources. It shows sorting by `title` in ascending order and `createdAt` in descending order, separated by a comma, with a hyphen indicating descending. ```http GET /posts?sort=title,-createdAt ``` -------------------------------- ### Applying Inline Filters via HTTP Query Parameters (HTTP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md These HTTP examples show how clients can apply the previously defined 'name' filter. The first example filters by a single string value, while the second demonstrates filtering by multiple values using array syntax in the query parameters. This illustrates how the `CustomFilter` handles different input types. ```http GET /posts?filter[name]=Toby GET /posts?filter[name][]=Toby&filter[name][]=Franz ``` -------------------------------- ### Defining Resource Fields (Attributes and Relationships) in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/resources.md This snippet demonstrates how to define attributes and relationships for a resource by implementing the `fields()` method. It shows examples of `Attribute::make` for `title`, `body`, and `createdAt`, and `ToOne` and `ToMany` for relationships. ```php use Tobyz\JsonApiServer\Schema\Field; use Tobyz\JsonApiServer\Schema\Type; class PostsResource extends AbstractResource { // ... public function fields(): array { return [ Field\Attribute::make('title') ->type(Type\Str::make()) ->writable(), Field\Attribute::make('body') ->type(Type\Str::make()) ->writable(), Field\Attribute::make('createdAt') ->type(Type\DateTime::make()) ->default(fn() => new DateTime()), Field\ToOne::make('author') ->type('users') ->includable(), Field\ToMany::make('comments'), ]; } } ``` -------------------------------- ### Implementing Deletable Interface for Resource (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/delete.md This snippet provides a complete example of a resource implementing the `Deletable` interface. It includes the `endpoints` method to enable the `Delete` endpoint, and the `find` and `delete` methods required by the interface for retrieving and deleting the model instance. ```php use App\Models\Post; use Tobyz\JsonApiServer\Resource\Updatable; class PostsResource extends Resource implements Deletable { // ... public function endpoints(): array { return [Endpoint\Delete::make()]; } public function find(string $id, Context $context): ?object; { return Post::find($id); } public function delete(object $model, Context $context): void { $model->delete(); } } ``` -------------------------------- ### Implementing Findable Interface for Show Endpoint - PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/show.md This example shows a complete implementation for the `Show` endpoint, requiring the `Findable` interface. It demonstrates how to implement the `find` method, which is called by the endpoint with the resource ID to retrieve the corresponding model instance, here using `Post::find($id)`. ```php use App\Models\Post; use Tobyz\JsonApiServer\Resource\Findable; class PostsResource extends Resource implements Findable { // ... public function endpoints(): array { return [Endpoint\Show::make()]; } public function find(string $id, Context $context): ?object; { return Post::find($id); } } ``` -------------------------------- ### Implementing Listable Interface for Index Endpoint (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This example illustrates the implementation of the `Listable` interface, which is required by the `Index` endpoint. It defines the `query` method to create a base query object and the `results` method to retrieve the final results from the query, enabling the endpoint to fetch and return resource collections. ```php use App\Models\Post; use Tobyz\JsonApiServer\Context; use Tobyz\JsonApiServer\Resource\{Listable, AbstractResource}; class PostsResource extends AbstractResource implements Listable { // ... public function query(Context $context): object { return Post::query(); } public function results(object $query, Context $context): array { return $query->get(); } } ``` -------------------------------- ### Installing PSR-7 Dependencies for Laravel Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/laravel.md This snippet provides the Composer commands necessary to install the Symfony HTTP Message Bridge and Nyholm PSR-7, which are required for Laravel to handle PSR-7 requests, enabling `json-api-server` integration. ```bash composer require symfony/psr-http-message-bridge composer require nyholm/psr7 ``` -------------------------------- ### Implementing Creatable Interface for Resource Creation in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/create.md This comprehensive example demonstrates implementing the `Creatable` interface for a resource, which is required by the `Create` endpoint. It includes methods like `newModel` for instantiating a new model, `setValue` for assigning field values, `create` for persisting the model, and `saveValue` for post-save operations, detailing the full lifecycle of resource creation. ```php use App\Models\Post; use Tobyz\JsonApiServer\Resource\Creatable; class PostsResource extends Resource implements Creatable { // ... public function endpoints(): array { return [Endpoint\Create::make()]; } public function newModel(Context $context): object { return new Post(); } public function setValue( object $model, Field $field, mixed $value, Context $context, ): void { $model->{$field->property ?: $field->name} = $value; } public function create(object $model, Context $context): object { $post->save(); } public function saveValue( object $model, Field $field, mixed $value, Context $context, ): void { // noop } } ``` -------------------------------- ### Enabling Show Endpoint for a Resource - PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/show.md This snippet demonstrates how to enable the `Show` endpoint for a resource or collection by adding `Show::make()` to the `endpoints` array within a `Resource` class. This allows the resource to handle GET requests for single resource objects. ```php use Tobyz\JsonApiServer\Endpoint\Show; class PostsResource extends Resource { // ... public function endpoints(): array { return [Show::make()]; } } ``` -------------------------------- ### Enabling Index Endpoint for a Resource (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This snippet demonstrates how to enable the `Index` endpoint for a resource by adding an instance of `Index::make()` to the `endpoints` array within a resource class. This allows the resource to handle GET requests to its collection root, returning a JSON:API document. ```php use Tobyz\JsonApiServer\Endpoint\Index; class PostsResource extends Resource { // ... public function endpoints(): array { return [Index::make()]; } } ``` -------------------------------- ### Defining a User Resource and Handling API Requests with Laravel Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/index.md This PHP example demonstrates how to define a `UsersResource` using `EloquentResource` for a Laravel application, specifying resource type, model instantiation, available endpoints (show, index, create, update, delete), and fields (name, address, friends). It also shows how to initialize the `JsonApi` server, register the resource, and handle incoming PSR-7 requests, including basic error handling. ```PHP use App\Models\User; use Tobyz\JsonApiServer\Laravel; use Tobyz\JsonApiServer\Laravel\EloquentResource; use Tobyz\JsonApiServer\Laravel\Filter; use Tobyz\JsonApiServer\Endpoint; use Tobyz\JsonApiServer\Schema\Field; use Tobyz\JsonApiServer\Schema\Type; use Tobyz\JsonApiServer\JsonApi; class UsersResource extends EloquentResource { public function type(): string { return 'users'; } public function newModel(Context $context): object { return new User(); } public function endpoints(): array { return [ Endpoint\Show::make(), Endpoint\Index::make()->paginate(), Endpoint\Create::make()->visible(Laravel\can('create')), Endpoint\Update::make()->visible(Laravel\can('update')), Endpoint\Delete::make()->visible(Laravel\can('delete')), ]; } public function fields(): array { return [ Field\Attribute::make('name') ->type(Type\Str::make()) ->writable() ->required(), Field\ToOne::make('address')->includable(), Field\ToMany::make('friends') ->type('users') ->includable(), ]; } public function filters(): array { return [Filter\Where::make('id'), Filter\Where::make('name')]; } } $api = new JsonApi(); $api->resource(new UsersResource()); /** @var Psr\Http\Message\ServerRequestInterface $request */ /** @var Psr\Http\Message\ResponseInterface $response */ try { $response = $api->handle($request); } catch (Throwable $e) { $response = $api->error($e); } ``` -------------------------------- ### Customizing Resource ID Retrieval in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/resources.md This snippet illustrates how to override the default `getId` method in `AbstractResource` to customize how the `id` for a model is retrieved, for example, by calling `getKey()` on the model. ```php use Tobyz\JsonApiServer\Context; class PostsResource extends AbstractResource { // ... public function getId(object $model, Context $context): string { return $model->getKey(); } } ``` -------------------------------- ### Defining Sort Fields for a Resource (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This snippet shows how to define available sort fields for a resource by adding them to the `sorts` method. Each entry, like `ExampleSort::make('example')`, makes a specific field sortable via the `sort` query parameter in JSON:API requests. ```php class PostsResource extends Resource implements Listable { // ... public function sorts(): array { return [ ExampleSort::make('example'), // [!code ++] ]; } } ``` -------------------------------- ### Defining Filter Fields for a Resource (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This snippet shows how to define available filter fields for a resource by adding them to the `filters` method. Each entry, like `ExampleFilter::make('example')`, makes a specific field filterable via the `filter` query parameter in JSON:API requests. ```php class PostsResource extends Resource implements Listable { // ... public function filters(): array { return [ ExampleFilter::make('example'), // [!code ++] ]; } } ``` -------------------------------- ### Implementing Updatable Interface for Resource Updates in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/update.md This comprehensive example demonstrates a simple implementation of the `Tobyz\JsonApiServer\Resource\Updatable` interface for a PHP resource. It includes the `find` method to retrieve the model, `setValue` for field assignment, `update` for persisting changes, and `saveValue` for post-save operations, fulfilling the requirements for the Update endpoint. ```php use App\Models\Post; use Tobyz\JsonApiServer\Resource\Updatable; class PostsResource extends Resource implements Updatable { // ... public function endpoints(): array { return [Endpoint\Update::make()]; } public function find(string $id, Context $context): ?object; { return Post::find($id); } public function setValue( object $model, Field $field, mixed $value, Context $context, ): void { $model->{$field->property ?: $field->name} = $value; } public function update(object $model, Context $context): object { $post->save(); } public function saveValue( object $model, Field $field, mixed $value, Context $context, ): void { // noop } } ``` -------------------------------- ### Deserializing Attribute Values (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/fields.md This example illustrates how to perform custom conversion on an attribute's data before it undergoes validation and is saved to the model. The `deserialize` method is used here to convert the first letter of the 'firstName' value to uppercase. ```php Attribute::make('firstName')->deserialize( fn($value, Context $context) => ucfirst($value), ); ``` -------------------------------- ### Marking an Attribute as Required (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/fields.md This example demonstrates how to mark a writable field as required. By chaining the `required()` method after `writable()`, the server will enforce that a value for this field must be provided when creating a new resource, preventing its omission. ```php Attribute::make('email') ->writable() ->required(); ``` -------------------------------- ### Configuring a Number Attribute Type in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/attributes.md This example demonstrates how to apply the `Number` type to an attribute. The `Number` type serializes values to floats and validates that incoming data is numeric, making it suitable for fields like 'weight'. ```php use Tobyz\JsonApiServer\Schema\Type\Number; Attribute::make('weight')->type(Number::make()); ``` -------------------------------- ### Implementing Atomic Operations Extension with Laravel in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/extensions.md This example demonstrates how to integrate the `Tobyz\JsonApiServer\Extension\Atomic` extension for atomic operations. It's crucial to wrap the `$api->handle` call within a database transaction (e.g., using Laravel's `DB::transaction`) to ensure that all database operations performed by the API are truly atomic. ```php use Illuminate\Support\Facades\DB; use Tobyz\JsonApiServer\Extension\Atomic; use Tobyz\JsonApiServer\JsonApi; $api = new JsonApi(); $api->extension(new Atomic()); return DB::transaction(fn() => $api->handle($request)); ``` -------------------------------- ### Making an Attribute Writable Only on Create (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/fields.md This example shows how to restrict an attribute's writability to only when a new resource is being created. Using the `writableOnCreate` method ensures that the field can be set during initial creation but cannot be modified during subsequent updates of an existing resource. ```php Attribute::make('email')->writableOnCreate(); ``` -------------------------------- ### Defining Custom Attribute Setters (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/fields.md This example shows how to define custom hydration logic for a specific field using the `set` method. Instead of directly assigning the value, this setter splits a full 'name' value into `first_name` and `last_name` properties on the model. ```php Attribute::make('name')->set(function ($model, $value, Context $context) { $model->first_name = explode(' ', $value)[0]; $model->last_name = explode(' ', $value)[1]; }); ``` -------------------------------- ### Setting Minimum and Maximum Length for String Attributes in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/attributes.md This example demonstrates how to restrict the length of a string attribute using `minLength()` and `maxLength()` methods. The 'name' attribute is constrained to have a length between 3 and 20 characters, inclusive, for validation. ```php Attribute::make('name')->type( Str::make() ->minLength(3) ->maxLength(20) ); ``` -------------------------------- ### Setting Minimum and Maximum for Number Attributes in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/attributes.md This example demonstrates how to define a numeric range for an attribute using the `minimum()` and `maximum()` methods on a `Number` type. It restricts the 'number' attribute to values between 1 and 20, inclusive, ensuring data integrity. ```php use Tobyz\JsonApiServer\Schema\Type\Number; Attribute::make('number')->type( Number::make() ->minimum(1) ->maximum(20) ); ``` -------------------------------- ### Defining Custom Field Getter Logic in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/fields.md This snippet demonstrates how to define custom retrieval logic for a specific field using the `get` method. This method accepts a closure that will be used to retrieve the field's value from the model, overriding the default `getValue` method. ```php Attribute::make('firstName')->get( fn($model, Context $context) => $model->getFirstName(), ); ``` -------------------------------- ### Setting Format Hint for String Attributes in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/attributes.md This snippet shows how to add a format hint to a string attribute using the `format()` method, which is primarily for OpenAPI definition purposes. For example, marking 'email' with 'email' format provides metadata but does not add built-in validation or serialization behavior; custom implementation is required for that. ```php Attribute::make('email')->type(Str::make()->format('email')); ``` -------------------------------- ### Configuring a Boolean Attribute Type in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/attributes.md This example shows how to assign a `Boolean` type to an attribute. The `Boolean` type ensures that values are serialized to booleans and validates incoming data to confirm they are boolean types, suitable for fields like 'active' status. ```php use Tobyz\JsonApiServer\Schema\Type\Boolean; Attribute::make('active')->type(Boolean::make()); ``` -------------------------------- ### Controlling Filter Visibility (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This PHP snippet shows how to restrict the visibility of a filter using the `visible` method. It accepts a closure that returns a boolean, determining if the filter is accessible. In this example, the filter is only visible if the request attribute 'isAdmin' is true, allowing for role-based access control. ```php WhereIn::make('example')->visible( fn(Context $context) => $context->request->getAttribute('isAdmin'), ); ``` -------------------------------- ### Setting Pattern Constraint for String Attributes in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/attributes.md This example demonstrates how to validate a string attribute against a regular expression using the `pattern()` method. The 'ssn' attribute is constrained to match a specific SSN format (e.g., 'XXX-XX-XXXX'), ensuring data adheres to a defined pattern. Note that delimiters should not be included in the pattern string. ```php Attribute::make('ssn')->type(Str::make()->pattern('^\d{3}-\d{2}-\d{4}$')); ``` -------------------------------- ### Setting MultipleOf Constraint for Integer Attributes in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/attributes.md This example demonstrates how to enforce that an integer attribute must be a multiple of a specific number using the `multipleOf()` method. Here, the 'number' attribute is constrained to be a multiple of 10, ensuring values like 10, 20, 30, etc., are valid. ```php use Tobyz\JsonApiServer\Schema\Type\Integer; Attribute::make('number')->type(Integer::make()->multipleOf(10)); ``` -------------------------------- ### Accessing User Attribute from Request Context in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/requests.md This snippet demonstrates how to retrieve the authenticated user attribute from the request within a resource definition callback, specifically using the `Context` object. It shows a practical example where an attribute's visibility is determined by comparing the model's ID with the authenticated user's ID, ensuring data security based on user context. ```PHP use Tobyz\JsonApiServer\Context; Attribute::make('email')->visible( fn($model, Context $context) => $model->id === $context->request->getAttribute('user')->id, ); ``` -------------------------------- ### Using BooleanDateTime Special Attribute in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/attributes.md This example demonstrates the `BooleanDateTime` attribute, which maps a boolean API representation to a timestamp in the model. When `true` is received, it sets the model's `deleted_at` property to the current date; when `false`, it sets it to `null`. This is useful for fields like 'isDeleted' that are internally stored as timestamps but exposed as booleans. ```php use Tobyz\JsonApiServer\Schema\Field\BooleanDateTime; BooleanDateTime::make('isDeleted') ->property('deleted_at') ->writable(); ``` -------------------------------- ### Registering a Resource with JsonApi Server in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/resources.md This snippet shows how to register an instance of a defined resource class with the `JsonApi` server using the `resource()` method, making it available via the API. ```php $api = new JsonApi(); $api->resource(new PostsResource()); ``` -------------------------------- ### Creating Custom Collection and Resource Actions in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/resources.md This snippet illustrates how to define custom 'action' endpoints for collections and individual resources. It shows the instantiation of `Endpoint\CollectionAction` and `Endpoint\ResourceAction` with an action name and a handler function that receives the context and can optionally return a PSR-7 response. ```php use Tobyz\JsonApiServer\Context; use Psr\Http\Message\ResponseInterface; Endpoint\CollectionAction::make('test', function ( Context $context, ): ?ResponseInterface { // ... }); Endpoint\ResourceAction::make('test', function ( Context $context, ): ?ResponseInterface { // ... }); ``` -------------------------------- ### Handling PSR-7 Requests and Errors with JsonApi in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/requests.md This snippet demonstrates how to instantiate the `JsonApi` class with a base path and use its `handle` method to process a PSR-7 request. It also shows how to catch any `Throwable` exceptions during request processing and use the `error` method to generate a JSON:API error response, ensuring robust error handling. ```PHP use Tobyz\JsonApiServer\JsonApi; $api = new JsonApi('/api'); /** @var Psr\Http\Message\ServerRequestInterface $request */ /** @var Psr\Http\Message\ResponseInterface $response */ try { $response = $api->handle($request); } catch (Throwable $e) { $response = $api->error($e); } ``` -------------------------------- ### Enabling Create Endpoint in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/create.md This snippet demonstrates how to enable the `Create` endpoint for a resource by adding `Create::make()` to the `endpoints` array within a `Resource` class. This allows the resource to handle POST requests for creating new instances. ```php use Tobyz\JsonApiServer\Endpoint\Create; class PostsResource extends Resource { // ... public function endpoints(): array { return [Create::make()]; } } ``` -------------------------------- ### Defining a JSON:API Resource with Eloquent in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/README.md This PHP code defines a `UsersResource` class extending `EloquentResource` to expose a `User` model as a JSON:API resource. It specifies the resource type, model instantiation, available endpoints (show, index, create, update, delete), and defines resource fields (attributes and relationships). It also demonstrates how to initialize the `JsonApi` server and handle incoming PSR-7 requests and responses, including basic error handling. ```PHP use App\Models\User; use Tobyz\JsonApiServer\Laravel; use Tobyz\JsonApiServer\Laravel\EloquentResource; use Tobyz\JsonApiServer\Laravel\Filter; use Tobyz\JsonApiServer\Endpoint; use Tobyz\JsonApiServer\Schema\Field; use Tobyz\JsonApiServer\Schema\Type; use Tobyz\JsonApiServer\JsonApi; class UsersResource extends EloquentResource { public function type(): string { return 'users'; } public function newModel(Context $context): object { return new User(); } public function endpoints(): array { return [ Endpoint\Show::make(), Endpoint\Index::make()->paginate(), Endpoint\Create::make()->visible(Laravel\can('create')), Endpoint\Update::make()->visible(Laravel\can('update')), Endpoint\Delete::make()->visible(Laravel\can('delete')), ]; } public function fields(): array { return [ Field\Attribute::make('name') ->type(Type\Str::make()) ->writable() ->required(), Field\ToOne::make('address')->includable(), Field\ToMany::make('friends') ->type('users') ->includable(), ]; } public function filters(): array { return [Filter\Where::make('id'), Filter\Where::make('name')]; } } $api = new JsonApi(); $api->resource(new UsersResource()); /** @var Psr\Http\Message\ServerRequestInterface $request */ /** @var Psr\Http\Message\ResponseInterface $response */ try { $response = $api->handle($request); } catch (Throwable $e) { $response = $api->error($e); } ``` -------------------------------- ### Defining an Eloquent Resource for JSON:API in Laravel Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/laravel.md This PHP snippet illustrates how to define an Eloquent-backed resource by extending `EloquentResource`. It specifies the resource type, how to create a new model instance, the supported API endpoints (Show, Index, Create, Update, Delete), and the fields exposed (title, author). ```php use Tobyz\JsonApiServer\Laravel\EloquentResource; class PostsResource extends EloquentResource { public function type(): string { return 'posts'; } public function newModel(Context $context): object { return new Post(); } public function endpoints(): array { return [ Endpoint\Show::make(), Endpoint\Index::make(), Endpoint\Create::make(), Endpoint\Update::make(), Endpoint\Delete::make(), ]; } public function fields(): array { return [ Field\Attribute::make('title'), Field\ToOne::make('author')->type('users'), ]; } } ``` -------------------------------- ### Implementing Offset Pagination on a Resource (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This PHP snippet demonstrates how to implement the `Paginatable` interface on a resource class (`PostsResource`) to apply offset pagination to the underlying query. The `paginate` method receives the query object and an `OffsetPagination` instance, using its `offset` and `limit` properties to modify the query. This is essential for the server to apply the pagination parameters. ```php use Tobyz\JsonApiServer\Context; use Tobyz\JsonApiServer\Pagination\OffsetPagination; use Tobyz\JsonApiServer\Resource\{Listable, Paginatable, AbstractResource}; class PostsResource extends AbstractResource implements Listable, Paginatable { // ... public function paginate(object $query, OffsetPagination $pagination): void { $query->offset($pagination->offset)->limit($pagination->limit); } } ``` -------------------------------- ### Defining a Resource Type in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/resources.md This snippet demonstrates how to define a new resource type by extending `AbstractResource` and implementing the `type()` method. The returned string will be used as the resource type name and its collection path. ```php use Tobyz\JsonApiServer\Resource\AbstractResource; class PostsResource extends AbstractResource { public function type(): string { return 'posts'; } } ``` -------------------------------- ### Defining Standard JSON:API Endpoints in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/resources.md This snippet demonstrates how to implement the `endpoints()` method within a resource class to expose standard JSON:API operations like listing, creating, reading, updating, and deleting. It returns an array of `Endpoint` objects, each corresponding to a specific RESTful action. ```php use Tobyz\JsonApiServer\Endpoint; class UsersResource extends AbstractResource { // ... public function endpoints(): array { return [ Endpoint\Index::make(), Endpoint\Create::make(), Endpoint\Show::make(), Endpoint\Update::make(), Endpoint\Delete::make(), ]; } } ``` -------------------------------- ### Enabling Default Offset Pagination (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This PHP snippet demonstrates how to enable offset pagination for a resource listing by calling the `paginate()` method on the `Index` endpoint. By default, this sets a page limit of 20 and a maximum client-requested limit of 50, providing basic pagination functionality. ```php Index::make()->paginate(); ``` -------------------------------- ### Enabling Delete Endpoint for Resource (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/delete.md This snippet demonstrates how to enable the `Delete` endpoint for a resource by adding `Delete::make()` to the `endpoints` array within a `Resource` class. This allows the resource to respond to DELETE requests. ```php use Tobyz\JsonApiServer\Endpoint\Delete; class PostsResource extends Resource { // ... public function endpoints(): array { return [Delete::make()]; } } ``` -------------------------------- ### Generating OpenAPI Definition in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/openapi.md This snippet demonstrates how to generate an OpenAPI 3.1.0 definition for a `JsonApi` instance. It requires the `Tobyz\JsonApiServer\JsonApi` and `Tobyz\JsonApiServer\OpenApi\OpenApiGenerator` classes. An instance of `JsonApi` is created, and then passed to the `generate` method of a new `OpenApiGenerator` instance to produce the OpenAPI definition. ```php use Tobyz\JsonApiServer\JsonApi; use Tobyz\JsonApiServer\OpenApi\OpenApiGenerator; $api = new JsonApi(); $definition = (new OpenApiGenerator())->generate($api); ``` -------------------------------- ### Registering a Heterogeneous Collection with JsonApi Server in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/collections.md This PHP snippet demonstrates how to register an instance of a custom heterogeneous collection, `ActivityCollection`, with the `JsonApi` server. This makes the collection available for use in the API, enabling its defined resources and endpoints. ```php $api = new JsonApi(); $api->collection(new ActivityCollection()); ``` -------------------------------- ### Defining Custom JSON:API Extension in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/extensions.md This snippet demonstrates how to create a custom JSON:API extension by extending the `Tobyz\JsonApiServer\Extension\Extension` class. It requires implementing the `uri()` method to return the extension's unique URI and the `handle()` method to process requests, returning a PSR-7 response if the extension can handle it, or `null` otherwise. ```php use Psr\Http\Message\ResponseInterface; use Tobyz\JsonApiServer\Context\Context; use Tobyz\JsonApiServer\Extension\Extension; 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->path() === 'my-extension') { return json_api_response([ 'my-extension:greeting' => 'Hello world!', ]); } return null; } } ``` -------------------------------- ### Implementing Resource Countability for Pagination (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This PHP snippet shows how to implement the `Countable` interface on a resource (`PostsResource`) to enable the inclusion of a `last` link and total resource count in pagination metadata. The `count` method is responsible for returning the total number of resources based on the provided query, allowing the server to provide complete pagination links and meta information. ```php use Tobyz\JsonApiServer\Context; use Tobyz\JsonApiServer\Pagination\OffsetPagination; use Tobyz\JsonApiServer\Resource\{ Countable, Listable, Paginatable, AbstractResource, }; class PostsResource extends AbstractResource implements Listable, Paginatable, Countable { // ... public function count(object $query, Context $context): int { return $query->count(); } } ``` -------------------------------- ### Creating a Custom Filter Class (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This PHP snippet demonstrates how to create a reusable custom filter by extending the `Tobyz\JsonApiServer\Schema\Filter` class. The `apply` method is implemented to apply a `whereIn` clause to the query, using the filter's name and value. This approach promotes reusability and better organization for complex filtering logic. ```php use Tobyz\JsonApiServer\Context; use Tobyz\JsonApiServer\Schema\Filter; class WhereIn extends Filter { public function apply( object $query, string|array $value, Context $context, ): void { $query->whereIn($this->name, $value); } } ``` -------------------------------- ### Routing JSON:API Requests in Laravel Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/laravel.md This PHP snippet demonstrates how to define a catch-all route in Laravel to handle JSON:API requests. It type-hints `Psr\Http\Message\ServerRequestInterface` to receive PSR-7 requests, initializes `JsonApi` with resources, and handles the request, including error handling. ```php use App\Http\Api\Resources; use Psr\Http\Message\ServerRequestInterface; Route::get('/api/{uri}', function (ServerRequestInterface $request) { $api = new JsonApi('/api'); $api->resource(new Resources\PostsResource()); $api->resource(new Resources\UsersResource()); try { return $api->handle($request); } catch (Throwable $e) { return $api->error($e); } })->where('uri', '.*'); ``` -------------------------------- ### Customizing HTTP Method for JSON:API Actions in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/resources.md This snippet demonstrates how to change the default HTTP POST method for custom collection or resource actions to a different method, such as PUT, using the `method()` fluent interface. ```php Endpoint\CollectionAction::make(...)->method('PUT'); ``` -------------------------------- ### Defining Heterogeneous Collections in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/collections.md This PHP class defines a heterogeneous collection named 'activity' that can contain 'posts', 'comments', and 'likes' resources. It implements the `Tobyz\JsonApiServer\Resource\Collection` interface, mapping models to their respective resource types and specifying allowed resources within the collection. ```php use Tobyz\JsonApiServer\Resource\Collection; class ActivityCollection implements Collection { /** * Get the collection name. */ public function name(): string { return 'activity'; } /** * Get the resources contained within this collection. */ public function resources(): array { return ['posts', 'comments', 'likes']; } /** * Get the name of the resource that represents the given model. */ public function resource(object $model, Context $context): ?string { return match (true) { $model instanceof Post => 'posts', $model instanceof Comment => 'comments', $model instanceof Like => 'likes', default => null, }; } /** * The collection's endpoints. */ public function endpoints(): array { return []; } } ``` -------------------------------- ### Defining Resource Fields in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/fields.md This snippet demonstrates how to define attributes and relationships for a `PostsResource` using the `fields` method. It shows how to create `Attribute` fields with types and writability, and `ToOne` and `ToMany` relationships, specifying their types and includability. ```php use Tobyz\JsonApiServer\Schema\Field; use Tobyz\JsonApiServer\Schema\Type; class PostsResource extends Resource { // ... public function fields(): array { return [ Field\Attribute::make('title') ->type(Type\Str::make()) ->writable(), Field\Attribute::make('body') ->type(Type\Str::make()) ->writable(), Field\Attribute::make('createdAt') ->type(Type\DateTime::make()) ->default(fn() => new DateTime()), Field\ToOne::make('author') ->type('users') ->includable(), Field\ToMany::make('comments'), ]; } } ``` -------------------------------- ### Registering JSON:API Extension in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/extensions.md This code snippet illustrates how to register a custom or built-in extension with your JSON:API server instance. By calling the `extension()` method on the `JsonApi` object, the server will automatically handle content negotiation and activate the specified extensions for incoming requests. ```php use Tobyz\JsonApiServer\JsonApi; $api = new JsonApi(); $api->extension(new MyExtension()); ``` -------------------------------- ### Creating a Custom Sort Field Class (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This snippet illustrates how to create a custom sort field by extending the `TobyzJsonApiServerSchemaSort` class. The `apply` method must be implemented to define the specific logic for applying the sort to the query object, using the sort field's name and direction. ```php use Tobyz\JsonApiServer\Context; use Tobyz\JsonApiServer\Schema\Sort; class SortColumn extends Sort { public function apply( object $query, string $direction, Context $context, ): void { $query->orderBy($this->name, $direction); } } ``` -------------------------------- ### Setting Default Values for Attributes (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/fields.md This snippet illustrates how to provide default values for attributes when no value is supplied in the request during resource creation. It shows setting a literal string default for 'name' and a dynamic `DateTime` object default for 'joinedAt' using a closure that receives the current request context. ```php use Tobyz\JsonApiServer\Schema\Field\Attribute; use Tobyz\JsonApiServer\Schema\Type; Attribute::make('name')->default('Anonymous'); Attribute::make('joinedAt') ->type(Type\DateTime::make()) ->default(fn(Context $context) => new \DateTime()); ``` -------------------------------- ### Authorizing Create Endpoint Visibility in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/create.md This code shows how to restrict access to the `Create` endpoint using the `visible` method. It accepts a closure that returns a boolean, typically based on request attributes like user roles, to determine if resource creation is allowed. ```php Create::make()->visible( fn(Context $context) => $context->request->getAttribute('isAdmin'), ); ``` -------------------------------- ### Implementing Custom JSON:API ErrorProvider Interface (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/errors.md This PHP class `ImATeapotException` implements the `Tobyz\JsonApiServer\Exception\ErrorProvider` interface. It defines custom logic for `getJsonApiErrors()` to return specific JSON:API error objects and `getJsonApiStatus()` to set the HTTP status code, allowing for tailored error responses. ```php use JsonApiPhp\JsonApi\Error; use Tobyz\JsonApiServer\Exception\ErrorProvider; class ImATeapotException implements ErrorProvider { public function getJsonApiErrors(): array { return [ [ 'title' => "I'm a teapot", 'status' => $this->getJsonApiStatus(), ], ]; } public function getJsonApiStatus(): string { return '418'; } } ``` -------------------------------- ### Restricting Index Endpoint Visibility (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This code shows how to restrict access to the `Index` endpoint using the `visible` method. It accepts a closure that returns a boolean, determining if the current context (e.g., `isAdmin` attribute) allows the resource collection to be listed. ```php Index::make()->visible( fn(Context $context) => $context->request->getAttribute('isAdmin'), ); ``` -------------------------------- ### Customizing Offset Pagination Limits (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This PHP snippet shows how to customize the default and maximum page limits for offset pagination. By passing arguments to the `paginate()` method, the default limit is set to 10 and the maximum client-requested limit is set to 100, overriding the default values. ```php Index::make()->paginate(10, 100); ``` -------------------------------- ### Applying Basic Validation Rules (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/laravel.md This snippet shows how to use the `rules` helper to apply Laravel's Validation component to a field. It takes a string or array of validation rules to be applied to the field's value. ```php use function Tobyz\JsonApiServer\Laravel\rules; Attribute::make('password')->validate(rules(['password'])); ``` -------------------------------- ### Using Can Helper for Authorization (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/laravel.md This snippet illustrates the `can` helper, which integrates with Laravel's Gate component for authorization checks. It returns a closure that verifies if a given ability is allowed, passing the model if in context. ```php use function Tobyz\JsonApiServer\Laravel\can; Update::make()->visible(can('update')); ``` -------------------------------- ### Defining a Basic Attribute in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/attributes.md This snippet demonstrates how to define a simple attribute field on a resource using the `Attribute::make()` method from the `Tobyz\JsonApiServer\Schema\Field\Attribute` class. It creates an attribute named 'title' without any specific type configuration, allowing for basic data representation. ```php use Tobyz\JsonApiServer\Schema\Field\Attribute; Attribute::make('title'); ``` -------------------------------- ### Creating a Basic SortColumn (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/laravel.md This snippet shows how to define a `SortColumn` for sorting resources based on a database column. The `make` method takes the JSON:API sort field name, which is automatically mapped to its underscored database column name (e.g., 'createdAt' to 'created_at'). ```php use Tobyz\JsonApiServer\Laravel\Sort\SortColumn; SortColumn::make('createdAt'); ``` -------------------------------- ### Deferring Relationship Loading in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/deferred.md This snippet demonstrates how to defer the loading of relationship values in a JSON:API resource using a closure. By buffering models and fields, it allows for batch loading of relationships, mitigating the N+1 problem. The `Buffer` class, which handles the actual buffering and loading, is an abstract concept here, requiring custom implementation. ```PHP use Tobyz\JsonApiServer\Schema\Field\Relationship; class PostsResource extends Resource { // ... public function getValue( object $model, Field $field, Context $context, ): mixed { if ($field instanceof Relationship) { Buffer::add($model, $field); return fn() => Buffer::load($model, $field, $context); } return parent::getValue($model, $field, $context); } } ``` -------------------------------- ### Handling Exceptions with JSON:API Error Responses (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/errors.md This snippet demonstrates how to catch any `Throwable` exception and convert it into a JSON:API error response using the `$api->error()` method. This ensures that all unhandled exceptions are presented in a standardized JSON:API error format. ```php try { $response = $api->handle($request); } catch (Throwable $e) { $response = $api->error($e); } ``` -------------------------------- ### Setting Default Sort for Index Endpoint (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This snippet demonstrates how to set a default sort order for the `Index` endpoint using the `defaultSort` method. The string argument specifies the default sort fields and their directions, which will be applied if no sort parameter is provided in the client request. ```php Index::make()->defaultSort('-createdAt,title'); ``` -------------------------------- ### Implementing Custom Attribute Savers (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/fields.md This snippet demonstrates how to gain complete control over how a field is persisted using the `save` method. The provided closure runs after the model has been saved, allowing for custom persistence logic, such as updating a related 'locale' preference in a separate table, bypassing the default `setValue` method. ```php Attribute::attribute('locale')->save(function ( $model, $value, Context $context, ) { $model ->preferences() ->where('key', 'locale') ->update(['value' => $value]); }); ``` -------------------------------- ### Attaching Authenticated User to PSR-7 Request in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/requests.md This snippet illustrates how to attach an authenticated user object to a PSR-7 `ServerRequestInterface` object using the `withAttribute` method. This allows user-specific information to be passed along with the request, making it accessible later in the request handling lifecycle, particularly within resource definitions. ```PHP $request = $request->withAttribute('user', $user); ``` -------------------------------- ### Applying Custom Serialization Logic to a Field in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/fields.md This snippet shows how to apply custom conversion logic to a field's value before it is serialized into JSON output. The `serialize` method takes a closure that receives the retrieved value and context, allowing for transformations like `ucfirst`. ```php Attribute::make('firstName')->serialize( fn($value, Context $context) => ucfirst($value), ); ``` -------------------------------- ### Defining Inline Filters with CustomFilter (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This PHP snippet demonstrates how to define an inline filter using `CustomFilter::make()`. It accepts a filter parameter name ('name') and a callback function. The callback applies a `whereIn` clause to the query, handling both string and array values for the filter. This allows filtering resources based on the 'name' attribute. ```php use Tobyz\JsonApiServer\Schema\CustomFilter; CustomFilter::make('name', function ( $query, string|array $value, Context $context, ) { $query->whereIn('name', (array) $value); }); ``` -------------------------------- ### Authorizing Show Endpoint Visibility - PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/show.md This code snippet illustrates how to restrict access to a resource using the `visible` method on the `Show` endpoint. It accepts a closure that determines visibility based on the model's properties, such as `is_public`, returning a boolean value. ```php Show::make()->visible(fn($model, Context $context) => $model->is_public); ``` -------------------------------- ### Enabling Update Endpoint in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/update.md This snippet demonstrates how to enable the Update endpoint for a resource by adding `Update::make()` to the `endpoints` array within a PHP resource class. This allows the resource to handle PATCH requests for updates. ```php use Tobyz\JsonApiServer\Endpoint\Update; class PostsResource extends Resource { // ... public function endpoints(): array { return [Update::make()]; } } ``` -------------------------------- ### Defining ToOne and ToMany Relationships in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/relationships.md This snippet demonstrates how to define `ToOne` and `ToMany` relationship fields on a resource using the `make` method. `ToOne::make('user')` creates a one-to-one relationship to a 'user' resource, and `ToMany::make('comments')` creates a one-to-many relationship to 'comments' resources. These relationships, by default, map to pluralized resource types. ```php use Tobyz\JsonApiServer\Schema\Field\{ToMany, ToOne}; ToOne::make('user'); ToMany::make('comments'); ``` -------------------------------- ### Defining Inline Custom Sort Field (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/list.md This code demonstrates how to define an inline custom sort field using `CustomSort::make`. It takes the sort field name and a callback function that applies the sorting logic to the query object based on the specified direction and context. ```php use Tobyz\JsonApiServer\Schema\CustomSort; CustomSort::make('example', function ( $query, string $direction, Context $context, ) { $query->orderBy('example', $direction); }); ``` -------------------------------- ### Configuring Sparse Fieldset for an Attribute in PHP Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/fields.md This snippet demonstrates how to mark an attribute as 'sparse' using the `sparse` method. When a field is marked sparse, it will be excluded from the default fieldset and must be explicitly requested by the client to be included in the JSON:API response. ```php Attribute::make('firstName')->sparse(); ``` -------------------------------- ### Authorizing Delete Endpoint Access (PHP) Source: https://github.com/tobyzerner/json-api-server/blob/main/docs/delete.md This snippet shows how to restrict deletion of a resource using the `visible` method on the `Delete` endpoint. It takes a closure that returns a boolean, determining if the resource can be deleted based on the model and context. ```php Delete::make()->visible(fn($model, Context $context) => $model->is_wiki); ```