PHPackages                             undabot/json-api-symfony - 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. [API Development](/categories/api)
4. /
5. undabot/json-api-symfony

ActiveSymfony-bundle[API Development](/categories/api)

undabot/json-api-symfony
========================

Allow symfony apps to easy handle JSON API compatible requests and responses

v2.3.7(1y ago)138.3k↓31%2[1 issues](https://github.com/undabot/json-api-symfony/issues)[2 PRs](https://github.com/undabot/json-api-symfony/pulls)1MITPHPPHP ^8

Since Oct 24Pushed 1y ago6 watchersCompare

[ Source](https://github.com/undabot/json-api-symfony)[ Packagist](https://packagist.org/packages/undabot/json-api-symfony)[ RSS](/packages/undabot-json-api-symfony/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (19)Versions (36)Used By (1)

json-api-symfony
================

[](#json-api-symfony)

This library was created with the idea of returning JSON:API compliant responses using Symfony as an application infrastructure provider. Library provides developers with support for having objects inside the application and "attaching" them to the response class. The end result is a response class with JSON:API data structure. The library also provides support for handling request query parameters and parsing JSON:API compliant request body into separate PHP classes.

The library itself is a wrapper around the Symfony framework, and it uses [json-api-core](https://github.com/undabot/json-api-core) library to do the heavy lifting when creating JSON:API compliant requests and responses.

This document covers following sections:

- [Usage](#usage)
    - [How to return the JSON:API compliant response?](#return-response)
    - [Write side](#write-side)
    - [Read side](#read-side)
    - [Responder](#responder)
- [Configuration](#configuration)
- [Development](#development)
- [Glossary](#glossary)
- [Performance](#performance)

Usage
--------------------------------------

[](#usage)

This section covers usage examples and a detailed explanation of library elements. After going through it, you will have more than sufficient knowledge of using the library, without the need for further help.

---

*Before we proceed, here are a few notes:*

- *Namespaces for Article and Comment are just for demo purposes. You can place it wherever you want.*
- *We use `readonly` for properties because we don't want that value assigned during the creation of the object is changed, but you don't need to do this. If using a version of PHP prior 8.1 you can add `@psalm-immutable` (read more about Psalm [here](https://github.com/vimeo/psalm)) annotation on the class to have readonly behaviour for properties.*
- *Final class is used on the class because we don't want to extend read models, but if you need to extend it remove final declaration (although we recommend to have one read model per resource which only implements ApiModel and doesn't extend any other model).*
- *Given examples have a lot of logic inside the controller because of readability. In a real application, we would recommend splitting the logic and move it into separate classes.*
- *Given examples have parameters from query passed into query bus, which should return an array of results. Instead of using the query bus, you can inject the repository and send parameters directly to it or even inject a database connection and make a raw query with the given parameters. Use whatever approach you use when building your applications.*

---

### How to return the JSON:API compliant response?

[](#how-to-return-the-jsonapi-compliant-response)

To return JSON:API compliant response, you have to go through a couple of steps - what you need is read or write side and responder. Both read and write sides logically consist of several classes:

- the controller, an entry point of the request
- the model used to create the entity or return requested information
- the entity that stores the data

Responder serves as a glue, mapping the entities to models.

Before going deeper into the read and write models, responders and controllers, it's a good idea to describe how we distinguish attributes from relations in our models. To recognise which property is attribute and which one is relation we use annotations. Each model should have one "main" annotation that determines its type, a top-level member for any resource object. This annotation is placed just above the class declaration, and it looks like this:

```
/** @ResourceType(type="articles") */
final class ArticleWriteModel implements ApiModel
```

Apart from `@ResourceType` annotation, there are three more - `@Attribute`, `@ToOne` and `@ToMany`.

`@Attribute` annotation says that the property is considered an attribute.

`@ToOne` and `@ToMany` annotations say that the property is a relationship. Relations must consist of name and type value inside ToOne and ToMany annotations, e.g.

```
/**
  * @var array
  * @ToMany(name="article_comments", type="comments")
 */
public readonly array $commentIds,
```

**Name** value is what we want to show in response. For this example, `article_comments` is the name for this relationship that will be returned in the response. If no name is defined in the annotation the relationship will inherit the property name.
**Type** value is the resource type of relation to which we're referring. Here, we're referring to comments, meaning that a model of type comments related to this model is part of the codebase. Keep in mind that the library links only types of the exact name, so if your model is of type `comment`, and you make a mistake and write plural library will throw an error.

Relationships can be nullable, and to add a nullable relationship to the model, you just need to assign a bool value to `nullable` property inside the annotation, like in the following example. Don't forget to null safe type-hint your property in that case, and remember - relationships are not nullable by default.

```
/**
  * @var array
  * @ToOne(name="article_author", type="authors", nullable=true)
 */
public readonly ?string $authorId,
```

With this knowledge, lets dive into the more concrete examples.

### Write side

[](#write-side)

The request and response lifecycle consists of receiving the data from the client and returning the data to the client - write and read side. When receiving data, it must be sent through the request's body as a JSON string compliant with JSON:API. This library allows us to fetch given data, validate it and convert it to PHP class.

#### Create

[](#create)

The write model consists of the annotated properties that build the resource we are about to create. So if we're about to create article with id, title and some related comments this is how the create (write) model would look like.

```
