paginationViaCursor
was removed from GraphQl operations as it had no behaviorLink::toProperty
(#5352)genId: false
to disable BC_api_exception_to_status
leftovers (#4992)ResourceAccessChecker::__construct()
(#4905)Resources/config/api_resources
to config/api_resources
(#4853)src/ApiResource/
is the recommended place for API models (#4874)Various cleanup in services and removal of backward compatibility layer.
api_jsonld_context
route format (#4844)ApiPlatform\OpenApi\Model\Parameter
BCVarious cleanup, removed Core
namespace leftovers and todos.
ApiPlatform\Symfony\Security\ExpressionLanguage
has been removed in favor of Symfony\Component\Security\Core\Authorization\ExpressionLanguage
.Breaking changes:
string $operationName
got removed in favor of ApiPlatform\Metadata\Operation $operation
. (#4779)ContextAware
interfaces were merged with their child interfaces you can safely remove them (#4779)Core
namespace got removed (#4805)Stringable
skip_null_values
now defaults to true
Patch
is added to the automatic CRUD@final
annotation from filters and mark them as final
array
cast for RDF types in ApiResource
& ApiProperty
constructors (#5000)false
(#4880)$exceptionOnNoToken
parameter in ResourceAccessChecker::__construct()
(#4900)Various cs fixes and PHPDoc to help upgrading to 3.0.
previous_data
to the context (#4776)BC
Doctrine: new interfaces for Filters and Extensions ready, switch to the ApiPlatform\Doctrine
namespace after fixing your deprecations: (#4779)
ApiPlatform\Core\Bridge\Doctrine\Orm\Extension
interfaces have an Operation
instead of the $operationName
, the new namespace is ApiPlatform\Doctrine\Orm\Extension
ApiPlatform\Core\Bridge\Doctrine\MongoDbOdm\Extension
interfaces have an Operation
instead of the $operationName
, the new namespace is ApiPlatform\Doctrine\Odm\Extension
iri: false
(#4731)getIriFromResource
and getResourceFromIri
(#4734)ApiPlatform\Metadata\Operation
instead of operationName
(#4712)CollectionOperationInterface
instead of the collection
flag (#4712)DeleteOperationInterface
instead of the delete
flag (#4712)compositeIdentifier
flag only lives under the uriVariables
property (#4712)provider
or processor
property is specified within the Operation
and we removed the chain pattern (#4712)usePkceWithAuthorizationCodeGrant
to Swagger UI initOAuth (#4649)mapping.paths
in configuration should override bundles configuration (#4465)ApiProperty
security
attribute expression being passed a class string for the object
variable on updates/creates - null is now passed instead if the object is not available (#4184)ApiProperty
now supports a security_post_denormalize
attribute, which provides access to the object
variable for the object being updated/created and previous_object
for the object before it was updated (#4184)make:data-provider
and make :data-persister
commands to generate a data provider / persister (#3850)api_platform.listener.request.add_format
priority from 7 to 28 to execute it before firewall (priority 8) (#3599)@final
annotation in ORM filters (#4109)exception_to_status
per operation (#3519)nulls_always_first
and nulls_always_last
to nulls_comparison
in order filter (#4103)order_nulls_comparison
configuration (#3117)date_immutable
support (#3940)TraversablePaginator
(#3783)swagger_ui_extra_configuration
to Swagger / OpenAPI configuration (#3731)$data
thanks to an argument resolver (#3263)ApiProperty
security (#4143)item_query
security is no longer used. ApiProperty
security can now be used to secure collection (or any other) properties. (#4143)allow_plain_identifiers
option (#4167)_format
resolving (#4292)ApiPlatform\Metadata
instead of ApiPlatform\Core\Metadata
, for example ApiPlatform\Metadata\ApiResource
(#4351)ApiPlatform\Core\Annotation
(#4351)ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface
is deprecated in favor of ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface
(#4351)ApiPlatform\Core\Api\OperationType
class (#4351)ApiPlatform\Metadata\GraphQl
follow the same metadata conventions (a Subscription operation is available and isn’t hidden behind an update Mutation anymore), interfaces got simplified (being @experimental) (#4351)ApiPlatform\Bridge\Symfony\Routing\IriConverter
that adds an operationName, same for ApiPlatform\Api\IdentifiersExtractor
(#4351)ApiPlatform\State\ProviderInterface
that replaces DataProviders (#4351)ApiPlatform\State\ProcessorInterface
that replaces DataPersisters (#4351)metadata_backward_compatibility_layer
(defaults to false) (#4351)security_post_validation
attributeClient::loginUser()
(#4588)ApiPlatform\Core\HttpCache\PurgerInterface
is deprecated in favor of ApiPlatform\HttpCache\PurgerInterface
, new purger that uses PURGE (#4695)SplFileInfo
class as a binary type (#4332)collectionKeyType
for building JSON Schema (#4385)REMOTE_ADDR
support in ApiTestCase
(#4446)asset_package
for all assets (#4470)@context
property possible types (#4223)to the
hydra:view` schema properties (#4310)response
without content
in the openapi_context
(#4210)SchemaFactory::buildSchema()
is now immutable as it no longer modifies the passed $schema
)FieldsBuilder
not fully unwrapping nested types before deciding if a resolver is needed (#4251)BAN
regex performance (#4231)withOptions()
to our HttpClient implementation (#4282)response
support via the openapi_context
(#4116)Link->requestBody
default value (#4116)defaults.order
as collection.order
(#4178)pagination_use_output_walkers
and pagination_fetch_join_collection
for operations (#3311)psr/cache
version 2 and 3 (#4117)POST
operations even if no identifier is defined (#4052)hydra:next
property (#4015)NullToken
when using the new authenticator manager in the resource access checker (#4067)isActive
and method isActive
) (#4064)$ref
when no type
is used in context (#4076)ALLOW_EXTRA_ATTRIBUTE=false
as it is a BC break and will be done in 3.0 instead see #3881 (#4007)requestBody
and parameters
via the openapi_context
(#4001), make openapi_context
work on subresources (#4004), sort paths (#4013)max_header_length
configuration (#2865)stale-while-revalidate
and stale-if-error
cache control headers (#3439)ApiPlatform\Core\DataTransformer\DataTransformerInitializerInterface
to pre-hydrate inputs (#3701)previous_data
to the context passed to persisters when available (#3752)ResumableDataPersisterInterface
that allows to call multiple persisters (#3912)asset_package
configurable (#3764)Paginator
class constructor now receives the denormalization context to support denormalizing documents using serialization groups. This change may cause potential BC breaks for existing applications as denormalization was previously done without serialization groups.order: [{foo: 'asc'}, {bar: 'desc'}]
(#3468)operation
is now operationName
to follow the standard (#3568)paginationType
is now pagination_type
(#3614)iri_only
attribute to simplify documents structure (useful when using Vulcain) (#3275)ApiPlatform\Core\Exception\ErrorCodeSerializableInterface
(#2922)normalization_context
option in mercure
attribute (#3772)InheritedPropertyMetadataFactory
(#3273)@Ignore
annotation (#3820)id
as default identifier if none provided (#3874)allowDiskUse
(#3144)[a-zA-Z0-9\.\-_]
to .
in definition names to be compliant with OpenAPI 3.0 (#3669)url_generation_strategy
(#3198)ApiResource
attribute (#3436)resourceClass
can now be defined as a container parameter in XML and YAML definitionsItemNormalizer
without Symfony SecurityBundle (#3801)getCookieJar
test.api_platform.client
service when the FrameworkBundle
bundle is registered after the ApiPlatformBundle
bundle (#3928)exception_to_status
to fallback to 400 if needed (#3808)ApiPlatform\Core\Validator\ValidationGroupsGeneratorInterface
ApiPlatform\Core\Bridge\Symfony\Validator\ValidationGroupsGeneratorInterface
(#3346)ExceptionInterface
now extends \Throwable
(#3217)hydra:next
when the item total is strictly greater than the number of items per page (#3967)AbstractPaginator
class (#3827)additionalProp1
from showing in example values (#3888)hydra:mapping
properties as nullable (#3877)@type
from collection using output DTOs (#3699)PurgeHttpCacheListener
performances (#3743)VarnishPurger
max header length (#3843)SwaggerCommand
(#3802)RegexFilter
(#3755)For compatibility reasons with Symfony 5.2 and PHP 8, we do not test anymore the integration with these legacy packages:
Cache-Control
HTTP header can be private (#3543)ManagerRegistry
class (#3684)setParameter
of the SearchFilter (#3331)\Traversable
resources (#3463)hydra:writable
=> hydra:writeable
(#3481)hydra:next
only when it’s available (#3457)ValidationException
instead of Symfony’s (#3414)before
or after
(#3360)ResourceClassResolver::getResourceClass()
SearchFilter
hasNextPage
when offset > itemsPerPage
ApiResource::$paginationPartial
AbstractItemNormalizer::normalizeRelation
SerializerContextBuilder
@ApiFilter
annotation404
HTTP status code instead of 500
whe the identifier is invalid (e.g.: invalid UUID)@ApiResource
annotation’s attributes to improve DXfilter
query parameterbody
parameter if it already existsoauth2-redirect
configurationSecurityBundle
was not installedfetch
access_control
item_query
and collection_query
typesMyTypeItem
and MyTypeCollection
) only if serialization groups are different for item_query
and collection_query
(#3083)maximum_items_per_page
attribute consistent with other attributes controlling paginationmerge-patch+json
format to enable PATCH support. This will be the default behavior in API Platform 3.api:json-schema:generate
(#2996)ApiPlatform\Core\JsonSchema\SchemaFactoryInterface
(#2983)access_control
by security
and adds a security_post_denormalize
attribute (#2992)exists[property]
, old syntax still supported see #2243, fixes its behavior on GraphQL (also related #2640).cacheHeaders
attributes of a resource (#2758)swagger.versions
and deprecates the enable_swagger
configuration option (#2998)asc
/desc
as enum (#2971)query
resource operation attribute into item_query
and collection_query
operations so user can use different security and serialization groups for them (#2944, #3015)api:graphql:export > schema.graphql
(#2600)serialize
PHP function (#2576)TypeConverter
to manage custom types, SerializerContextBuilder
to modify the (de)serialization context dynamically, etc.) (#2772)Notes:
Please read #2825 if you have issues with the behavior of Readable/Writable Link
remove
methodPagination
EntityManagerInterface
is used in data providersprevious_data
Content-Type
is sentWriteListener
trying to generate IRI for non-resourcesprevious_data
request attribute, and allow to access it in security expressions using the previous_object
variable (useful for PUT and PATCH requests)AbstractItemNormalizer
introduced in 2.4Doctrine: allow autowiring of filter classes
Doctrine: don’t use fetchJoinCollection
on Paginator
when not needed
Doctrine: fix a BC break in OrderFilter
GraphQL: input objects aren’t nullable anymore (compliance with the Relay spec)
Cache: Remove some useless purges
Mercure: publish to Mercure using the default response format
Mercure: use the Serializer context
OpenAPI: fix documentation of the PropertyFilter
OpenAPI: fix generation of the servers
block (also fixes the compatibility with Postman)
OpenAPI: skip not readable and not writable properties from the spec
OpenAPI: add the id
path parameter for POST item operation
Serializer: add support for Symfony Serializer’s @SerializedName
metadata
Metadata: ApiResource
’s attributes
property now defaults to null
, as expected
Metadata: Fix identifier support when using an interface as resource class
Metadata: the HTTP method is now always uppercased
Allow to disable listeners per operation (fix handling of empty request content)
Previously, empty request content was allowed for any POST
and PUT
operations. This was an unsafe assumption which caused other problems.
If you wish to allow empty request content, please add "deserialize"=false
to the operation’s attributes. For example:
<?php
// api/src/Entity/Book.php
use ApiPlatform\Core\Annotation\ApiResource;
use App\Controller\PublishBookAction;
/**
* @ApiResource(
* itemOperations={
* "put_publish"={
* "method"="PUT",
* "path"="/books/{id}/publish",
* "controller"=PublishBookAction::class,
* "deserialize"=false,
* },
* },
* )
*/
class Book
{
You may also need to add "validate"=false
if the controller result is null
(possibly because you don’t need to persist the resource).
Return the 204
HTTP status code when the output class is set to null
Be more resilient when normalizing non-resource objects
Replace the data
request attribute by the return of the data persister
Fix error message in identifiers extractor
Improve the bundle’s default configuration when using symfony/symfony
is required
Fix the use of MetadataAwareNameConverter
when available (configuring name_converter: serializer.name_converter.metadata_aware
will now result in a circular reference error)
FilterEagerLoadingExtension
NoOpScalarNormalizer
handling scalar valuesapi_platform.metadata_cache
parameterSearchFilter
webonyx/graphql-php
is not installedDISTINCT
is not used when there are no joinselasticsearch
attribute can be disabled resource-wise or per-operationmessenger
attribute can now take the input
string as a value (messenger="input"
). This will use a default transformer so that the given input
is directly sent to the messenger handler.messenger
attribute can be declared per-operationkernel.terminate
, so the Mercure and the Messenger integration can be used together<0
) for improved compatibility with Symfony’s autoconfiguration feature. If you have custom extensions we recommend to use positive priorities.Service name | Old priority | New priority | Class |
---|---|---|---|
api_platform.doctrine.orm.query_extension.eager_loading (collection) | -8 | ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\EagerLoadingExtension | |
api_platform.doctrine.orm.query_extension.eager_loading (item) | -8 | ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\EagerLoadingExtension | |
api_platform.doctrine.orm.query_extension.filter | 32 | -16 | ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterExtension |
api_platform.doctrine.orm.query_extension.filter_eager_loading | -17 | ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterEagerLoadingExtension | |
api_platform.doctrine.orm.query_extension.order | 16 | -32 | ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\OrderExtension |
api_platform.doctrine.orm.query_extension.pagination | 8 | -64 | ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\PaginationExtension |
endCursor
behavior was wrong)clientMutationId
nullable and return mutation payload as an object)_api_respond
request attribute in the SerializeListener< 0
). If you have custom normalizer we recommend to use positive priorities.Service name | Old priority | New priority | Class |
---|---|---|---|
api_platform.hydra.normalizer.constraint_violation_list | 64 | -780 | ApiPlatform\Core\Hydra\Serializer\ConstraintViolationListNormalizer |
api_platform.jsonapi.normalizer.constraint_violation_list | -780 | ApiPlatform\Core\JsonApi\Serializer\ConstraintViolationListNormalizer | |
api_platform.problem.normalizer.constraint_violation_list | -780 | ApiPlatform\Core\Problem\Serializer\ConstraintViolationListNormalizer | |
api_platform.swagger.normalizer.api_gateway | 17 | -780 | ApiPlatform\Core\Swagger\Serializer\ApiGatewayNormalizer |
api_platform.hal.normalizer.collection | -790 | ApiPlatform\Core\Hal\Serializer\CollectionNormalizer | |
api_platform.hydra.normalizer.collection_filters | 0 | -790 | ApiPlatform\Core\Hydra\Serializer\CollectionFiltersNormalizer |
api_platform.jsonapi.normalizer.collection | -790 | ApiPlatform\Core\JsonApi\Serializer\CollectionNormalizer | |
api_platform.jsonapi.normalizer.error | -790 | ApiPlatform\Core\JsonApi\Serializer\ErrorNormalizer | |
api_platform.hal.normalizer.entrypoint | -800 | ApiPlatform\Core\Hal\Serializer\EntrypointNormalizer | |
api_platform.hydra.normalizer.documentation | 32 | -800 | ApiPlatform\Core\Hydra\Serializer\DocumentationNormalizer |
api_platform.hydra.normalizer.entrypoint | 32 | -800 | ApiPlatform\Core\Hydra\Serializer\EntrypointNormalizer |
api_platform.hydra.normalizer.error | 32 | -800 | ApiPlatform\Core\Hydra\Serializer\ErrorNormalizer |
api_platform.jsonapi.normalizer.entrypoint | -800 | ApiPlatform\Core\JsonApi\Serializer\EntrypointNormalizer | |
api_platform.problem.normalizer.error | -810 | ApiPlatform\Core\Problem\Serializer\ErrorNormalizer | |
serializer.normalizer.json_serializable | -900 | -900 | Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer |
serializer.normalizer.datetime | -910 | -910 | Symfony\Component\Serializer\Normalizer\DateTimeNormalizer |
serializer.normalizer.constraint_violation_list | -915 | Symfony\Component\Serializer\Normalizer\ConstraintViolationListNormalizer | |
serializer.normalizer.dateinterval | -915 | -915 | Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer |
serializer.normalizer.data_uri | -920 | -920 | Symfony\Component\Serializer\Normalizer\DataUriNormalizer |
api_platform.graphql.normalizer.item | 8 | -922 | ApiPlatform\Core\GraphQl\Serializer\ItemNormalizer |
api_platform.hal.normalizer.item | -922 | ApiPlatform\Core\Hal\Serializer\ItemNormalizer | |
api_platform.jsonapi.normalizer.item | -922 | ApiPlatform\Core\JsonApi\Serializer\ItemNormalizer | |
api_platform.jsonld.normalizer.item | 8 | -922 | ApiPlatform\Core\JsonLd\Serializer\ItemNormalizer |
api_platform.serializer.normalizer.item | 0 | -923 | ApiPlatform\Core\Serializer\ItemNormalizer |
serializer.normalizer.object | -1000 | -1000 | Symfony\Component\Serializer\Normalizer\ObjectNormalizer |
name
and iri
if needed)falsy
boolean to disable the input/output0
limit in the paginationinput_class
and output_class
attributesinput_class
and output_class
to falsecache_headers
attributestatus
attributeSunset
HTTP header using the sunset
attributeContent-Location
and Location
headers when appropriate for better RFC7231 conformanceapi_persist
request attribute to enable or disable the WriteListener
OptimisticLockException
is thrownRequestAttributesExtractor
is not internal anymore and can be used in userland codeshow_webby
configuration option to hide the spider in API docswebonyx/graphql-php
0.13properties[]
as a collection parameterproperties[]
filterItemNormalizer
when $context['resource_class']
is not definedDEFERRED_EXPLICIT
change tracking policyInvalidArgumentException
when trying to get an item from a collection routeroute_prefix
attribute in subresourcesNumericFilter
ReadListener
by adding the previous exception_id
when id
is not part of the requested fieldsOrderFilter
when applied on nested entities@ApiResource
and @ApiProperty
annotationsaccess_control_message
attribute--output
option to the api:swagger:export
commandCacheableSupportsMethodInterface
introduced in Symfony 4.1 in all (de)normalizers (improves the performance dramatically)totalCount
field in GraphQL paginated collectionsExistsFilter
for inverse side of OneToOne associationFilterEagerLoadingExtension
now accepts joins with class name as join valueApiPlatform\Core\EventListener\EventPriorities
’s PRE_SERIALIZE
and POST_SERIALIZE
constantsenable_max_depth
if definedExistFilter
to work properly with GraphQLChainSubresourceDataProvider
to take into account RestrictedDataProviderInterface
POST
request to have an empty bodyIriConverter
Link
HTTP header pointing to the Hydra documentation if docs are disabledOrderFilter
to trigger faulty deprecation noticesfetchEager=false
directive on an association in the EagerLoadingExtension
ItemNormalizer
ConstraintViolationListNormalizer
CachedRouteNameResolver
and CachedSubresourceOperationFactory
by adding a local memory cache layerisResourceClass
when possibletry/catch
in the CachedTrait
IriConverter
ChainSubresourceDataProvider
class to take into account RestrictedDataProviderInterface
FilterEagerLoadingExtension
with manual joins@ApiFilter
annotations on the same classSubresourceDataProviderInterface
DateTimeImmutable
support in the date filterDocumentationAction
impacting NelmioApiDoc@ApiFilter
annotation to directly configure filters from resource classesCOUNT()
SQL queriesallow_plain_identifiers
option to allow using plain IDs as identifier instead of IRIsAbstractCollectionNormalizer
to help supporting custom formatsApiPlatform\Core\Bridge\Doctrine\EventListener\WriteListener
class in favor of the new ApiPlatform\Core\EventListener\WriteListener
class.api_platform.doctrine.listener.view.write
event listener service.ApiPlatform\Core\DataPersister\DataPersisterInterface
interface.access_control_message
attributePOST
HTTP request0
items per page in collectionsHost
from the Symfony RouterPaginator::getLastPage()
now always returns a float
owl:allValuesFrom
in the API documentationnull
PriorityTaggedServiceTrait
provided by Symfony instead of a custom implementation/posts/1/comments
or /posts/1/comments/2
RequestAttributesExtractor
FilterCollection
classpagination
and itemPerPage
parameters in the Swagger/Open API documentationResource-md5($groups)
=> Resource-groupa_groupb
) - see https://github.com/api-platform/core/pull/1207hydra_context
option take precedence over operation metadataItemNormalizer
(raw JSON, XML)#
ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter::extractProperties
now always return an arrayLEFT JOIN
clause for filter associations\Traversable
valuesdeclare(strict_types=1)
and improve coding standardsConstraintViolationList
each()
(deprecated since PHP 7.2)EagerLoadingExtension
ItemDataproviderInterface
: fetchData
is now in the context parameterer. getItemFromIri
is now context aware 7f82fd7start
and word_start
strategies to the Doctrine Search filter/apidoc
(was /vocab
)Dunglas\ApiBundle\Exception\ExceptionInterface
api_
getId()
was always used)Dunglas\ApiBundle\Doctrine\Orm\DataProvider
allowing to customize Doctrine paginator and performance optimization when using typical queriesDunglas\ApiBundle\JsonLd\Event\Events::CONTEXT_BUILDER
event allowing to modify the JSON-LD context202
to 200
for PUT
requestsDoctrine\Orm\Filter\OrderFilter
instanceMade with love by
Les-Tilleuls.coop can help you design and develop your APIs and web projects, and train your teams in API Platform, Symfony, Next.js, Kubernetes and a wide range of other technologies.
Learn more