# Data Providers To retrieve data exposed by the API, API Platform uses classes called **data providers**. A data provider using [Doctrine ORM](https://www.doctrine-project.org/projects/orm.html) to retrieve data from a database, a data provider using [Doctrine MongoDB ODM](https://www.doctrine-project.org/projects/mongodb-odm.html) to retrieve data from a document database, and a data provider using [Elasticsearch-PHP](https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html) to retrieve data from an Elasticsearch cluster are included with the library. The first one is enabled by default. These data providers natively support paged collections and filters. They can be used as-is and are perfectly suited to common uses. However, you sometimes want to retrieve data from other sources such as another persistence layer or a webservice. Custom data providers can be used to do so. A project can include as many data providers as needed. The first able to retrieve data for a given resource will be used. For a given resource, you can implement two kinds of interface: * the [`CollectionDataProviderInterface`](https://github.com/api-platform/core/blob/main/src/DataProvider/CollectionDataProviderInterface.php) is used when fetching a collection. * the [`ItemDataProviderInterface`](https://github.com/api-platform/core/blob/main/src/DataProvider/ItemDataProviderInterface.php) is used when fetching items. Both implementations can also implement a third, optional, interface called ['RestrictedDataProviderInterface'](https://github.com/api-platform/core/blob/main/src/DataProvider/RestrictedDataProviderInterface.php) if you want to limit their effects to a single resource or operation. In the following examples we will create custom data providers for an entity class called `App\Entity\BlogPost`. Note, that if your entity is not Doctrine-related, you need to flag the identifier property by using `@ApiProperty(identifier=true)` for things to work properly (see also [Entity Identifier Case](serialization.md#entity-identifier-case)). ## Custom Collection Data Provider First, your `BlogPostCollectionDataProvider` has to implement the [`CollectionDataProviderInterface`](https://github.com/api-platform/core/blob/main/src/DataProvider/CollectionDataProviderInterface.php): The `getCollection` method must return an `array`, a `Traversable` or a [`ApiPlatform\Core\DataProvider\PaginatorInterface`](https://github.com/api-platform/core/blob/main/src/DataProvider/PaginatorInterface.php) instance. If no data is available, you should return an empty array. ```php getSerializer()->deserialize($data, BlogPost::class, 'custom'); } } ``` ## Injecting Extensions (Pagination, Filter, EagerLoading etc.) API Platform provides a few extensions that you can reuse in your custom DataProvider. Note that there are a few kinds of extensions which are detailed in [their own chapter of the documentation](extensions.md). Because extensions are tagged services, you can use the [injection of tagged services](https://symfony.com/blog/new-in-symfony-3-4-simpler-injection-of-tagged-services): ```yaml services: 'App\DataProvider\BlogPostItemDataProvider': arguments: $itemExtensions: !tagged api_platform.doctrine.orm.query_extension.item ``` ```xml ``` Your data provider will now have access to the core extensions, here is an example on how to use them: ```php managerRegistry = $managerRegistry; $this->itemExtensions = $itemExtensions; } public function supports(string $resourceClass, string $operationName = null, array $context = []): bool { return BlogPost::class === $resourceClass; } public function getItem(string $resourceClass, $id, string $operationName = null, array $context = []): ?BlogPost { $manager = $this->managerRegistry->getManagerForClass($resourceClass); $repository = $manager->getRepository($resourceClass); $queryBuilder = $repository->createQueryBuilder('o'); $queryNameGenerator = new QueryNameGenerator(); $identifiers = ['id' => $id]; foreach ($this->itemExtensions as $extension) { $extension->applyToItem($queryBuilder, $queryNameGenerator, $resourceClass, $identifiers, $operationName, $context); if ($extension instanceof QueryResultItemExtensionInterface && $extension->supportsResult($resourceClass, $operationName, $context)) { return $extension->getResult($queryBuilder, $resourceClass, $operationName, $context); } } return $queryBuilder->getQuery()->getOneOrNullResult(); } } ``` ## Community Data Providers If you don't want to use the built-in Doctrine system, alternative approaches which offer an integration with API Platform exist. * [Pomm Data Provider](https://github.com/pomm-project/pomm-api-platform): ([Pomm](http://www.pomm-project.org/) is a database access framework dedicated to PostgreSQL database.