From d72e58a617173fc6c48dd07bfc74ba7b1d3dbf7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 16 Jun 2016 08:39:58 +0200 Subject: [PATCH] Update the data providers doc --- core/data-providers.md | 106 +++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 58 deletions(-) diff --git a/core/data-providers.md b/core/data-providers.md index 487f9a0f69e..3f5390136fb 100644 --- a/core/data-providers.md +++ b/core/data-providers.md @@ -5,34 +5,26 @@ ORM](http://www.doctrine-project.org/projects/orm.html) to retrieve data from a is enabled by default. This data provider natively supports paged collections and filters. It can be used as is and fits perfectly with common usages. -But sometime, you want to retrieve data from other sources such as a webservice, ElasticSearch, MongoDB or another ORM. -Custom data providers can be used to do so. A project can include as many data providers as it needs. The first able to retrieve data for a given resource will be used. +But sometime, you want to retrieve data from other sources such as another persistence layer, a webservice, ElasticSearch +or MongoDB. +Custom data providers can be used to do so. A project can include as many data providers as it needs. The first able to +retrieve data for a given resource will be used. -For a given resource, you can implement two kind of data providers: -- the [CollectionDataProvider](https://github.com/api-platform/core/blob/master/src/Api/CollectionDataProviderInterface.php) is used when fetching a collection. -- the [ItemDataProvider](https://github.com/api-platform/core/blob/master/src/Api/ItemDataProviderInterface.php) is used when fetching items. +For a given resource, you can implement two kind of interfaces: -In the following examples we will create custom data providers for the class `AppBundle\Model\BlogPost`. +* the [`CollectionDataProviderInterface`](https://github.com/api-platform/core/blob/master/src/Api/CollectionDataProviderInterface.php) + is used when fetching a collection. +* the [`ItemDataProviderInterface`](https://github.com/api-platform/core/blob/master/src/Api/ItemDataProviderInterface.php) + is used when fetching items. -## Custom collection data provider - -First declare a Symfony service, for example: +In the following examples we will create custom data providers for an entity class class called `AppBundle\Entity\BlogPost`. -```yaml -# AppBundle\Resources\config\services.yml - -services: - blog_post.collection_data_provider: - class: 'AppBundle\DataProvider\BlogPostCollectionDataProvider' - # data providers are using decorators (http://symfony.com/doc/master//components/dependency_injection/advanced.html#decorating-services) - decorates: 'api_platform.collection_data_provider' - arguments: - - '@blog_post.collection_data_provider.inner' -``` +## Custom collection data provider -Then, your `BlogPostCollectionDataProvider` has to implement the [`CollectionDataProviderInterface`](https://github.com/api-platform/core/blob/master/src/Api/CollectionDataProviderInterface.php): +First, your `BlogPostCollectionDataProvider` has to implement the [`CollectionDataProviderInterface`](https://github.com/api-platform/core/blob/master/src/Api/CollectionDataProviderInterface.php): -The `getCollection` method must return an `array`, a `\Traversable` or a `PaginatorInterface` instance. If no data is available, you should return an empty array. +The `getCollection` method must return an `array`, a `Traversable` or a `ApiPlatform\Core\Api\PaginatorInterface` instance. +If no data is available, you should return an empty array. ```php @@ -46,45 +38,39 @@ use ApiPlatform\Core\Exception\ResourceClassNotSupportedException; class BlogPostCollectionDataProvider implements CollectionDataProviderInterface { - private $decorated; - - public function __construct(CollectionDataProviderInterface $decorated = null) - { - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ public function getCollection(string $resourceClass, string $operationName = null) { - // tests if the class is supported by this data provider if (BlogPost::class !== $resourceClass) { - throw new ResourceClassNotSupportedException(); + throw new ResourceClassNotSupportedException(); } - return ['foo' => 'bar']; + // Retrieve the blog post collection from somewhere + return [new BlogPost(1), new BlogPost(2)]; } } ``` -## Custom item data provider - -Declare a Symfony service, for example: +Then declare a Symfony service, for example: ```yaml - -# AppBundle\Resources\config\services.yml +# app/config/services.yml services: - blog_post.item_data_provider: - class: 'AppBundle\DataProvider\BlogPostItemDataProvider' - decorates: 'api_platform.item_data_provider' - arguments: - - '@blog_post.item_data_provider.inner' + blog_post.collection_data_provider: + class: 'AppBundle\DataProvider\BlogPostCollectionDataProvider' + tags: + - { name: 'api_platform.collection_data_provider', priority: 2 } ``` -Then, your `BlogPostItemDataProvider` has to implement the [`ItemDataProviderInterface`](https://github.com/api-platform/core/blob/master/src/Api/ItemDataProviderInterface.php): +Tagging the service with the tag `api_platform.collection_data_provider` will enable API Platform Core to automatically +register and use this data provider. The optional attribute `priority` allows to define the order in wich are called the +data providers. The first data provider not throwing a `ApiPlatform\Core\Exception\ResourceClassNotSupportedException` will +be used. + +## Custom item data provider + +The process is similar for item data providers. Create a `BlogPostItemDataProvider` implementing the [`ItemDataProviderInterface`](https://github.com/api-platform/core/blob/master/src/Api/ItemDataProviderInterface.php) +interface: The `getItem` method can return `null` if no result has been found. @@ -100,26 +86,30 @@ use ApiPlatform\Core\Exception\ResourceClassNotSupportedException; class BlogPostItemDataProvider implements ItemDataProviderInterface { - private $decorated; - - public function __construct(ItemDataProviderInterface $decorated = null) - { - $this->decorated = $decorated; - } - - /** - * {@inheritdoc} - */ - public function getCollection(string $resourceClass, string $operationName = null) + public function getItem(string $resourceClass, $id, string $operationName = null, bool $fetchData = false); { if (BlogPost::class !== $resourceClass) { throw new ResourceClassNotSupportedException(); } - return (object) ['foo' => 'bar']; + // Retrieve the blog post item from somewhere + return new BlogPost($id); } } ``` +The tag to use for item data providers is `api_platform.item_data_provider`. As for collection data providers, the `priority` +attribute can be used to order providers. + +```yaml +# app/config/services.yml + +services: + blog_post.collection_data_provider: + class: 'AppBundle\DataProvider\BlogPostCollectionDataProvider' + tags: + - { name: 'api_platform.item_data_provider' } +``` + Previous chapter: [Operations](operations.md)
Next chapter: [Filters](filters.md)