|
1 | 1 | # Upgrade Guide
|
2 | 2 |
|
3 |
| -## API Platform 2.7/3.0 |
| 3 | +## API Platform 3.1/3.2 |
4 | 4 |
|
5 |
| -### I Want to Try the New Metadata System |
| 5 | +This is the recommended configuration for API Platform 3.2. We review each of these changes in this document. |
6 | 6 |
|
7 |
| -Note that if you want to use the **new metadata system**, you need to set: |
8 |
| - |
9 |
| -```yaml |
10 |
| -# api/config/packages/api_platform.yaml |
11 |
| -api_platform: |
12 |
| - metadata_backward_compatibility_layer: false |
13 |
| -``` |
14 |
| -
|
15 |
| -This will be the default value in 3.0, in 2.7 it's left to `true` so that nothing breaks by updating. |
16 |
| -By doing so you won't get access to legacy services and this will probably break things on code using `api-platform/core:2.6`. |
17 |
| - |
18 |
| -In 3.0, in conformance with the JSON Merge Patch RFC, the default value of the `skip_null_values` property is `true` which means that from now on `null` values are omitted during serialization. |
19 | 7 | ```yaml
|
20 | 8 | api_platform:
|
21 |
| - defaults: |
22 |
| - normalization_context: |
23 |
| - skip_null_values: true |
24 |
| -``` |
25 |
| - |
26 |
| -### I'm Migrating From 2.6 and Want to Prepare For 3.0 |
27 |
| - |
28 |
| -1. Update the code to 2.7: `composer require api-platform/core:^2.7` |
29 |
| -2. Take care of the deprecations and update your code to the new interfaces, documented on this page |
30 |
| -3. Switch the `metadata_backward_compatibility_layer` flag to `false` |
31 |
| -4. Use the [`api:upgrade-resource` command](#the-upgrade-command) |
32 |
| - |
33 |
| -Read more about the `metadata_backward_compatibility_layer` flag [here](#the-metadata_backward_compatibility_layer-flag). |
34 |
| - |
35 |
| -## Changes |
36 |
| - |
37 |
| -### Summary of the Changes Between 2.6 And 2.7/3.0 |
38 |
| - |
39 |
| -- New Resource metadata allowing to declare multiple Resources on a class: `ApiPlatform\Metadata\ApiResource` |
40 |
| -- Clarification of some properties within the ApiResource declaration |
41 |
| -- Removal of item and collection differences on operation declaration |
42 |
| -- `ApiPlatform\Core\DataProvider\...DataProviderInterface` has a new |
43 |
| -interface `ApiPlatform\State\ProviderInterface` |
44 |
| -- `ApiPlatform\Core\DataPersister\...DataPersisterInterface` has a new |
45 |
| -interface `ApiPlatform\State\ProcessorInterface` |
46 |
| -- New ApiProperty metadata `ApiPlatform\Metadata\ApiProperty` |
47 |
| -- Configuration flag `metadata_backward_compatibility_layer` that allows the use of legacy metadata layers |
48 |
| -- `ApiPlatform\Core\DataTransformer\DataTransformerInterface` is deprecated and will be removed in 3.0 |
49 |
| -- Subresources are now additional resources marked with an `#[ApiResource]` attribute (see [the new subresource documentation](./subresources.md)) |
50 |
| - |
51 |
| -The detailed changes are present in the [CHANGELOG](https://github.com/api-platform/core/blob/main/CHANGELOG.md). |
52 |
| - |
53 |
| -### ApiResource Metadata |
54 |
| - |
55 |
| -The `ApiResource` annotation has a new namespace: |
56 |
| -`ApiPlatform\Metadata\ApiResource` instead of `ApiPlatform\Core\Annotation\ApiResource`. |
57 |
| - |
58 |
| -For example, the Book resource in 2.6: |
59 |
| - |
60 |
| -```php |
61 |
| -<?php |
62 |
| -// api/src/Entity/Book.php |
63 |
| -namespace App\Entity; |
64 |
| -
|
65 |
| -use ApiPlatform\Core\Annotation\ApiResource; |
66 |
| -
|
67 |
| -#[ApiResource( |
68 |
| - iri: 'https://schema.org/Book', |
69 |
| - itemOperations: [ |
70 |
| - 'get', |
71 |
| - 'post_publication' => [ |
72 |
| - 'method' => 'POST', |
73 |
| - 'path' => '/books/{id}/publication', |
74 |
| - ], |
75 |
| - ]) |
76 |
| -] |
77 |
| -class Book |
78 |
| -{ |
79 |
| - // ... |
80 |
| -} |
81 |
| -``` |
82 |
| - |
83 |
| -Becomes in 2.7: |
84 |
| - |
85 |
| -```php |
86 |
| -<?php |
87 |
| -// api/src/Entity/Book.php |
88 |
| -namespace App\Entity; |
89 |
| -
|
90 |
| -use ApiPlatform\Metadata\ApiResource; |
91 |
| -use ApiPlatform\Metadata\Get; |
92 |
| -use ApiPlatform\Metadata\Post; |
93 |
| -use App\Controller\CreateBookPublication; |
94 |
| -
|
95 |
| -#[ApiResource(types: ['https://schema.org/Book'], operations: [ |
96 |
| - new Get(), |
97 |
| - new Post(name: 'publication', uriTemplate: '/books/{id}/publication') |
98 |
| -])] |
99 |
| -class Book |
100 |
| -{ |
101 |
| - // ... |
102 |
| -} |
| 9 | + title: Hello API Platform |
| 10 | + version: 1.0.0 |
| 11 | + formats: |
| 12 | + jsonld: ['application/ld+json'] |
| 13 | + docs_formats: |
| 14 | + jsonld: ['application/ld+json'] |
| 15 | + jsonopenapi: ['application/vnd.openapi+json'] |
| 16 | + html: ['text/html'] |
| 17 | + defaults: |
| 18 | + stateless: true |
| 19 | + cache_headers: |
| 20 | + vary: ['Content-Type', 'Authorization', 'Origin'] |
| 21 | + extra_properties: |
| 22 | + standard_put: true |
| 23 | + rfc_7807_compliant_errors: true |
| 24 | + event_listeners_backward_compatibility_layer: false |
| 25 | + keep_legacy_inflector: false |
103 | 26 | ```
|
104 | 27 |
|
105 |
| -You can use the `api:upgrade-resource` command to upgrade |
106 |
| -your resources automatically, [see instructions here](#the-upgrade-command). |
| 28 | +### Formats |
107 | 29 |
|
108 |
| -### Removal of Item/Collection Operations |
| 30 | +We noticed that API Platform was enabling `json` by default because of our OpenAPI support. We introduced the new `application/vnd.openapi+json`. Therefore if you want `json` you need to explicitly handle it: |
109 | 31 |
|
110 |
| -We removed the notion of item and collection. |
111 |
| -Instead, use HTTP verbs matching the operation you want to declare. |
112 |
| -There is also a `collection` flag instructing whether the |
113 |
| -operation returns an array or an object. |
114 |
| -The default `ApiResource` attribute still declares a CRUD: |
115 |
| - |
116 |
| -```php |
117 |
| -#[ApiResource] |
118 |
| -``` |
119 |
| - |
120 |
| -is the same as: |
121 |
| - |
122 |
| -```php |
123 |
| -#[ApiResource(operations: [ |
124 |
| - new Get(), |
125 |
| - new Put(), |
126 |
| - new Patch(), |
127 |
| - new Delete(), |
128 |
| - new GetCollection(), |
129 |
| - new Post(), |
130 |
| -])] |
| 32 | +```yaml |
| 33 | +formats: |
| 34 | + json: ['application/json'] |
131 | 35 | ```
|
132 | 36 |
|
133 |
| -### Metadata Changes |
134 |
| - |
135 |
| -#### #[ApiResource] |
136 |
| - |
137 |
| -`ApiPlatform\Metadata\ApiResource` instead of `ApiPlatform\Core\Annotation\ApiResource` |
138 |
| - |
139 |
| -|Before|After| |
140 |
| -|---|---| |
141 |
| -|`iri: 'https://schema.org/Book'`|`types: ['https://schema.org/Book']`| |
142 |
| -|`path: '/books/{id}/publication'`|`uriTemplate: '/books/{id}/publication'`| |
143 |
| -|`identifiers: []`|`uriVariables: []`| |
144 |
| -|`attributes: []`|`extraProperties: []`| |
145 |
| -|`attributes: ['validation_groups' => ['a', 'b']]`|`validationContext: ['groups' => ['a', 'b']]`| |
146 |
| - |
147 |
| -#### #[ApiProperty] |
148 |
| - |
149 |
| -`ApiPlatform\Metadata\ApiProperty` instead of `ApiPlatform\Core\Annotation\ApiProperty` |
| 37 | +You can also remove documentations you're not using via the new `docs_formats`. |
150 | 38 |
|
151 |
| -|Before|After| |
152 |
| -|---|---| |
153 |
| -|`iri: 'https://schema.org/Book'`|`types: ['https://schema.org/Book']`| |
154 |
| -|`type: 'string'`|`builtinTypes: ['string']`| |
| 39 | +A new option `error_formats` is also used for content negotiation. |
155 | 40 |
|
156 |
| -Note that `builtinTypes` are computed automatically from PHP types. |
| 41 | +### Event listeners |
157 | 42 |
|
158 |
| -For example: |
| 43 | +For new users we recommend to use |
159 | 44 |
|
160 |
| -```php |
161 |
| -class Book |
162 |
| -{ |
163 |
| - public string|Isbn $isbn; |
164 |
| -} |
| 45 | +```yaml |
| 46 | +event_listeners_backward_compatibility_layer: false |
165 | 47 | ```
|
166 | 48 |
|
167 |
| -Will compute: `builtinTypes: ['string', Isbn::class]` |
168 |
| - |
169 |
| -### The `metadata_backward_compatibility_layer` Flag |
170 |
| - |
171 |
| -In 2.7 the `metadata_backward_compatibility_layer` flag is set to `true`. |
172 |
| -This means that all the legacy services will still work just as they used |
173 |
| -to work in 2.6 (for example `PropertyMetadataFactoryInterface` or |
174 |
| -`ResourceMetadataFactoryInterface`). |
175 |
| -When updating we advise to first resolve the deprecations then to set this |
176 |
| -flag to `false` to use the new metadata system. |
177 |
| - |
178 |
| -When `metadata_backward_compatibility_layer` is set to `false`: |
179 |
| -- there's still a bridge with the legacy `ApiPlatform\Core\Annotation\ApiResource` and old metadata will still work |
180 |
| -- the deprecated Symfony services will have their interface changed (for example `ApiPlatform\Core\Api\IriConverterInterface` |
181 |
| -will be `ApiPlatform\Api\IriConverterInterface`) and it may break your dependency injection. |
182 |
| -- the new metadata system is available `ApiPlatform\Metadata\ApiResource` |
183 |
| - |
184 |
| -### SearchFilter |
| 49 | +This allows API Platform to not use http kernel event listeners. It also allows you to force options like `read: true` or `validate: true`. This simplifies use cases like [validating a delete operation](/docs/v3.2/guides/delete-operation-with-validation/) |
| 50 | +Event listeners will not get removed and are not deprecated, they'll use our providers and processors in a future version. |
185 | 51 |
|
186 |
| -If you want to use the new namespaces for the search filter |
187 |
| -(`ApiPlatform\Doctrine\Orm\Filter\SearchFilter` instead of`ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter` or |
188 |
| -`ApiPlatform\Doctrine\Odm\Filter\SearchFilter` instead of`ApiPlatform\Core\Bridge\Doctrine\Odm\Filter\SearchFilter`) you |
189 |
| -need to set the `metadata_backward_compatibility_layer` to `false` as this filter relies on the implementation |
190 |
| -of the new `ApiPlatform\Api\IriConverterInterface`. |
191 |
| - |
192 |
| -In 3.0 this flag will default to `false` and the legacy code will be removed. |
193 |
| - |
194 |
| -## The Upgrade Command |
195 |
| - |
196 |
| -The upgrade command will automatically upgrade the old `ApiPlatform\Core\Annotation\ApiResource` to `ApiPlatform\Metadata\ApiResource`. |
197 |
| -By default, this does a dry run and shows a diff: |
198 |
| - |
199 |
| -```bash |
200 |
| -php bin/console api:upgrade-resource |
201 |
| -``` |
| 52 | +### Inflector |
202 | 53 |
|
203 |
| -To write in-place use the `force` option: |
| 54 | +We're switching to `symfony/string` [inflector](https://symfony.com/doc/current/components/string.html#inflector), to keep using `doctrine/inflector` use: |
204 | 55 |
|
205 |
| -```bash |
206 |
| -php bin/console api:upgrade-resource -f |
| 56 | +```yaml |
| 57 | +keep_legacy_inflector: false |
207 | 58 | ```
|
208 | 59 |
|
209 |
| -## Providers/Processors |
210 |
| - |
211 |
| -Providers and Processors are replacing DataProviders and DataPersisters. |
212 |
| -We reduced their interface to only one method and the class used by your operation can be specified directly within the metadata. |
213 |
| -Using Doctrine, a default resource would use these: |
214 |
| - |
215 |
| -```php |
| 60 | +We strongly recommend that you use your own inflector anyways with a [PathSegmentNameGenerator](https://github.com/api-platform/core/blob/f776f11fd23e5397a65c1355a9ebcbb20afac9c2/src/Metadata/Operation/UnderscorePathSegmentNameGenerator.php). |
216 | 61 |
|
217 |
| -<?php |
| 62 | +### Errors |
218 | 63 |
|
219 |
| -use ApiPlatform\Metadata\Get; |
220 |
| -use ApiPlatform\Metadata\GetCollection; |
221 |
| -use ApiPlatform\Metadata\Delete; |
222 |
| -use ApiPlatform\Metadata\Post; |
223 |
| -use ApiPlatform\Metadata\Put; |
224 |
| -
|
225 |
| -#[Put(processor: ApiPlatform\Doctrine\Common\State\PersistProcessor::class, provider: ApiPlatform\Doctrine\Orm\State\ItemProvider::class)] |
226 |
| -#[Post(processor: ApiPlatform\Doctrine\Common\State\PersistProcessor::class)] |
227 |
| -#[Delete(processor: ApiPlatform\Doctrine\Common\State\RemoveProcessor::class)] |
228 |
| -#[Get(provider: ApiPlatform\Doctrine\Orm\State\ItemProvider::class)] |
229 |
| -#[GetCollection(provider: ApiPlatform\Doctrine\Orm\State\CollectionProvider::class)] |
230 |
| -class Book {} |
| 64 | +```yaml |
| 65 | +defaults: |
| 66 | + extra_properties: |
| 67 | + rfc_7807_compliant_errors: true |
231 | 68 | ```
|
232 | 69 |
|
233 |
| -See also the respective documentation: |
234 |
| - |
235 |
| -- [State Processor](./state-processors.md) |
236 |
| -- [State Provider](./state-providers.md) |
237 |
| - |
238 |
| -## DataTransformers and DTO Support |
239 |
| - |
240 |
| -Data transformers have been deprecated, instead you can still document the `output` or the `input` DTO. |
241 |
| -Then, just handle the `input` in a custom [State Processor](./state-processors.md) or return another `output` in a custom [State Provider](./state-providers.md). |
242 |
| - |
243 |
| -The [dto documentation](./dto.md) has been adapted accordingly. |
| 70 | +As this is an `extraProperties` it's configurable per resource/operation. This is improving the compatibility of Hydra errors with JSON problem. It also enables new extension points on [Errors](https://api-platform.com/docs/v3.2/core/errors/) such as [Error provider](https://api-platform.com/docs/v3.2/guides/error-provider/) and [Error Resource](https://api-platform.com/docs/v3.2/guides/error-resource/). |
0 commit comments