diff --git a/core/dto.md b/core/dto.md
index d9040ddfbf1..b3c353b7870 100644
--- a/core/dto.md
+++ b/core/dto.md
@@ -1,6 +1,6 @@
# Using Data Transfer Objects (DTOs)
-
Watch the Custom Resources screencast
+
Watch the Custom Resources screencast
As stated in [the general design considerations](design.md), in most cases [the DTO pattern](https://en.wikipedia.org/wiki/Data_transfer_object) should be implemented using an API Resource class representing the public data model exposed through the API and [a custom State Provider](state-providers.md). In such cases, the class marked with `#[ApiResource]` will act as a DTO.
diff --git a/core/extending.md b/core/extending.md
index 9a1332c1c4d..9bf25614d43 100644
--- a/core/extending.md
+++ b/core/extending.md
@@ -14,10 +14,10 @@ The following tables summarizes which extension point to use depending on what y
| [Laravel Policies](../laravel/security.md#policies) | custom authorization logic |
| [Validation constraints](validation.md) | custom validation logic |
| [State Processors](state-processors) | custom business logic and computations to trigger before or after persistence (ex: mail, call to an external API...) |
-| [Normalizers](serialization.md#decorating-a-serializer-and-adding-extra-data) | customize the resource sent to the client (add fields in JSON documents, encode codes, dates...) |
+| [Normalizers](serialization.md#changing-the-serialization-context-dynamically) | customize the resource sent to the client (add fields in JSON documents, encode codes, dates...) |
| [Filters](filters.md) | create filters for collections and automatically document them (OpenAPI, GraphQL, Hydra) |
| [Serializer Context Builders](serialization.md#changing-the-serialization-context-dynamically) | change the Serialization context (e.g. groups) dynamically |
-| [Messenger Handlers](../symfony/messenger.md) | create 100% custom, RPC, async, service-oriented endpoints (should be used in place of custom controllers because the messenger integration is compatible with both REST and GraphQL, while custom controllers only work with REST) |
+| [Messenger Handlers](../symfony/messenger.md) | create 100% custom, RPC, async, service-oriented endpoints (should be used in place of custom controllers because the messenger integration is compatible with both REST and GraphQL, while custom controllers only work with REST) |
| [DTOs](dto.md) | use a specific class to represent the input or output data structure related to an operation |
| [Kernel Events](events.md) | customize the HTTP request or response (REST only, other extension points must be preferred when possible) |
diff --git a/core/serialization.md b/core/serialization.md
index 2701a43f936..400c0ce0d11 100644
--- a/core/serialization.md
+++ b/core/serialization.md
@@ -192,7 +192,7 @@ documentation generator.
## Using Serialization Groups per Operation
-
Watch the Relations screencast
+
Watch the Relations screencast
By default, the serializer provided with API Platform represents relations between objects using [dereferenceable IRIs](https://en.wikipedia.org/wiki/Internationalized_Resource_Identifier).
They allow you to retrieve details for related objects by issuing extra HTTP requests. However, for performance reasons,
@@ -239,6 +239,7 @@ App\ApiResource\Book:
normalizationContext:
groups: ['get']
operations:
+ ApiPlatform\Metadata\Get: ~
ApiPlatform\Metadata\Get: ~
ApiPlatform\Metadata\Patch:
normalizationContext:
diff --git a/outline.yaml b/outline.yaml
index d06d9052727..2ab6b4879ea 100644
--- a/outline.yaml
+++ b/outline.yaml
@@ -9,14 +9,14 @@ chapters:
- testing
- debugging
- caddy
- - migrate-from-fosrestbundle
- - fosuser-bundle
- - nelmio-api-doc
- - user
- jwt
+ - messenger
+ - user
- file-upload
- controllers
- - messenger
+ - nelmio-api-doc
+ - migrate-from-fosrestbundle
+ - fosuser-bundle
- title: "API Platform for Laravel"
path: laravel
items:
diff --git a/symfony/index.md b/symfony/index.md
index b2e379bcdcb..0073627a427 100644
--- a/symfony/index.md
+++ b/symfony/index.md
@@ -19,8 +19,8 @@ API Platform is shipped with **[Docker](../deployment/docker-compose.md)** and *
The easiest and most powerful way to get started is [to download the API Platform distribution](https://github.com/api-platform/api-platform/releases). It contains:
- the API skeleton, including [the Core library](../core/index.md), [the Symfony framework](https://symfony.com/) ([optional](../core/bootstrap.md)) and [the Doctrine ORM](https://www.doctrine-project.org/projects/orm.html) ([optional](../core/extending.md))
-- [the client scaffolding tool](../create-client/) to generate [Next.js](../create-client/) web applications from the API documentation ([Nuxt](https://nuxt.com/), [Vue](https://vuejs.org/), [Create React App](https://reactjs.org), [React Native](https://reactnative.dev/), [Quasar](https://quasar.dev/) and [Vuetify](https://vuetifyjs.com/) are also supported)
-- [a beautiful admin interface](../admin/), built on top of React Admin, dynamically created by parsing the API documentation
+- [the client scaffolding tool](../create-client/index.md) to generate [Next.js](../create-client/index.md) web applications from the API documentation ([Nuxt](https://nuxt.com/), [Vue](https://vuejs.org/), [Create React App](https://reactjs.org), [React Native](https://reactnative.dev/), [Quasar](https://quasar.dev/) and [Vuetify](https://vuetifyjs.com/) are also supported)
+- [a beautiful admin interface](../admin/index.md), built on top of React Admin, dynamically created by parsing the API documentation
- all you need to [create real-time and async APIs using the Mercure protocol](../core/mercure.md)
- a [Docker](../deployment/docker-compose.md) definition to start a working development environment in a single command, providing containers for the API and the Next.js web application
- a [Helm](https://helm.sh/) chart to deploy the API in any [Kubernetes](../deployment/kubernetes.md) cluster
diff --git a/symfony/jwt.md b/symfony/jwt.md
index 460da9b417a..fbf241a28f2 100644
--- a/symfony/jwt.md
+++ b/symfony/jwt.md
@@ -5,7 +5,7 @@
> **we recommend adopting open standards such as [OpenID Connect (OIDC)](https://openid.net/connect/)** for robust, scalable,
> and interoperable authentication.
-
Watch the LexikJWTAuthenticationBundle screencast
+
Watch the LexikJWTAuthenticationBundle screencast
## Installing LexikJWTAuthenticationBundle
diff --git a/symfony/security.md b/symfony/security.md
index a8848cdff9d..e2e97988025 100644
--- a/symfony/security.md
+++ b/symfony/security.md
@@ -110,8 +110,8 @@ Available variables are:
- `previous_object`: (`securityPostDenormalize` only) a clone of `object`, before modifications were made - this is `null` for create operations
- `request` (only at the resource level): the current request
-Access control checks in the `security` attribute are always executed before the [denormalization step](serialization.md).
-It means that for `PUT` or `PATCH` requests, `object` doesn't contain the value submitted by the user, but values currently stored in [the persistence layer](state-processors.md).
+Access control checks in the `security` attribute are always executed before the [denormalization step](../core/serialization.md).
+It means that for `PUT` or `PATCH` requests, `object` doesn't contain the value submitted by the user, but values currently stored in [the persistence layer](../core/state-processors.md).
## Executing Access Control Rules After Denormalization
@@ -337,17 +337,17 @@ resources:
## Filtering Collection According to the Current User Permissions
-Filtering collections according to the role or permissions of the current user must be done directly at [the state provider](state-providers.md) level. For instance, when using the built-in adapters for Doctrine ORM, MongoDB and ElasticSearch, removing entries from a collection should be done using [extensions](extensions.md).
+Filtering collections according to the role or permissions of the current user must be done directly at [the state provider](../core/state-providers.md) level. For instance, when using the built-in adapters for Doctrine ORM, MongoDB and ElasticSearch, removing entries from a collection should be done using [extensions](../core/extensions.md).
Extensions allow to customize the generated DQL/Mongo/Elastic/... query used to retrieve the collection (e.g. add `WHERE` clauses depending of the currently connected user) instead of using access control expressions.
As extensions are services, you can [inject the Symfony `Security` class](https://symfony.com/doc/current/security.html#b-fetching-the-user-from-a-service) into them to access to current user's roles and permissions.
-If you use [custom state providers](state-providers.md), you'll have to implement the filtering logic according to the persistence layer you rely on.
+If you use [custom state providers](../core/state-providers.md), you'll have to implement the filtering logic according to the persistence layer you rely on.
## Disabling Operations
-To completely disable some operations from your application, refer to the [disabling operations](operations.md#enabling-and-disabling-operations)
+To completely disable some operations from your application, refer to the [disabling operations](../core/operations.md#enabling-and-disabling-operations)
section.
## Changing Serialization Groups Depending of the Current User
-See [how to dynamically change](serialization.md#changing-the-serialization-context-dynamically) the current Serializer context according to the current logged in user.
+See [how to dynamically change](../core/serialization.md#changing-the-serialization-context-dynamically) the current Serializer context according to the current logged-in user.
diff --git a/symfony/testing.md b/symfony/testing.md
index 4f9cb3b810b..2b658bf4edc 100644
--- a/symfony/testing.md
+++ b/symfony/testing.md
@@ -377,7 +377,7 @@ If you would like to verify that your stack (including services such as the DBMS
works, you need [end-to-end testing](https://wiki.c2.com/?EndToEndPrinciple). To do so, we recommend using [Playwright](https://playwright.dev) if you use have PWA/JavaScript-heavy app, or [Symfony Panther](https://github.com/symfony/panther) if you mostly use Twig.
Usually, end-to-end testing should be done with a production-like setup. For your convenience, you may [run our Docker Compose setup
-for production locally](../deployment/docker-compose.md#running-the-docker-compose-setup-for-production-locally).
+for production locally](../deployment/docker-compose.md#deploying-with-docker-compose).
## Testing Utilities for Symfony
diff --git a/symfony/validation.md b/symfony/validation.md
index ec7eaa6dfd7..49cbc1ff99c 100644
--- a/symfony/validation.md
+++ b/symfony/validation.md
@@ -104,7 +104,7 @@ error will look like the following if the requested format is JSON-LD (the defau
}
```
-Take a look at the [Errors Handling guide](errors.md) to learn how API Platform converts PHP exceptions like validation
+Take a look at the [Errors Handling guide](../core/errors.md) to learn how API Platform converts PHP exceptions like validation
errors to HTTP errors.
## Using Validation Groups
@@ -136,7 +136,7 @@ class Book
With the previous configuration, the validation groups `a` and `b` will be used when validation is performed.
-Like for [serialization groups](serialization.md#using-different-serialization-groups-per-operation),
+Like for [serialization groups](../core/serialization.md#using-serialization-groups-per-operation),
you can specify validation groups globally or on a per-operation basis.
Of course, you can use XML or YAML configuration format instead of attributes if you prefer.
@@ -146,7 +146,7 @@ the array of group names.
## Using Validation Groups on Operations
-You can have different validation for each [operation](operations.md) related to your resource.
+You can have different validation for each [operation](../core/operations.md) related to your resource.
```php
getValues()`. Then, define your validation on the getter instead of the property.
For example: