Data providers are the main entry point for every document that you may want to add in MeiliSearch. Data providers aims to allow you to submit data when you cannot use annotations.
The main role of a data provider is to return an array that contain the data stored as a document in MeiliSearch.
This bundle defines 2 type of data provider:
Each data provider comes with a dedicated behaviour.
In order to see how to use it, let's use a data provider which receive data from an external REST API, let's admit that the API return a body similar to this one:
{
"id": 1,
"title": "random title",
"tags": ["foo", "title"]
}
In this example, we use Symfony/HttpClient
but feel free to use the one which fit your needs
<?php
use MeiliSearchBundle\DataProvider\DocumentDataProviderInterface;
// ...
final class PostDataProvider implements DocumentDataProviderInterface
{
private $httpClient;
// ... constructor
public function support() : string
{
return 'foo';
}
public function getDocument() : array
{
$response = $this->httpClient->request('GET', 'https://api.com/posts');
if (empty($response->toArray())) {
return [];
}
return $response->toArray();
}
}
Keep in mind that a provider can return data from any source, as long as the array is valid, you're good to go.
Once defined, the data provider is automatically configured and injected both in the DIC and the related command.
In order to see how to use it, let's use an embedded data provider which defines hardcoded data:
<?php
use MeiliSearchBundle\DataProvider\EmbeddedDocumentDataProviderInterface;
final class PostDataProvider implements EmbeddedDocumentDataProviderInterface
{
public function support() : string
{
return 'foo';
}
public function getDocument() : array
{
return [
[
'id' => 1,
'title' => 'random title',
'tags' => ['foo', 'title'],
],
[
'id' => 2,
'title' => 'second random title',
'tags' => ['foo', 'second', 'title'],
],
];
}
}
Note: This type of data provider SHOULD define the returned model (if desired) IN the document body:
<?php
use MeiliSearchBundle\DataProvider\EmbeddedDocumentDataProviderInterface;
final class PostDataProvider implements EmbeddedDocumentDataProviderInterface
{
public function support() : string
{
return 'foo';
}
public function getDocument() : array
{
return [
[
'id' => 1,
'title' => 'random title',
'tags' => ['foo', 'title'],
'model' => \stdClass::class,
],
[
'id' => 2,
'title' => 'second random title',
'tags' => ['foo', 'second', 'title'],
'model' => \stdClass::class,
],
];
}
}
As you may need to use a different primary key from the default id
one, this bundle defines a PrimaryKeyOverrideDataProviderInterface
which allows you to define the key to use:
<?php
use MeiliSearchBundle\DataProvider\DocumentDataProviderInterface;
use MeiliSearchBundle\DataProvider\PrimaryKeyOverrideDataProviderInterface;
// ...
final class PostDataProvider implements DocumentDataProviderInterface, PrimaryKeyOverrideDataProviderInterface
{
private $postRepository;
// ... constructor
public function support() : string
{
return 'foo';
}
public function getPrimaryKey() : string
{
return 'key';
}
public function getDocument() : array
{
$posts = $this->postRepository->findAll();
if (0 === \count($posts)) {
return [];
}
$collection = [];
array_walk($posts, function (Post $post) use (&$collection): void {
$collection[] = [
'id' => $post->getId(),
'title' => $post->getTitle(),
'tags' => $post->getTagsAsArray(),
];
});
return $collection;
}
}
Setting a model (related to DTO/Value Object)
When loading a document, you may need to define a model used to obtain an objet when fetching the document.
This bundle provides a ModelDataProviderInterface
which allows you to set the model thanks to getModel()
:
<?php
use MeiliSearchBundle\DataProvider\DocumentDataProviderInterface;
use MeiliSearchBundle\DataProvider\ModelDataProviderInterface;
// ...
final class PostDataProvider implements DocumentDataProviderInterface, ModelDataProviderInterface
{
private $postRepository;
// ... constructor
public function support(): string
{
return 'foo';
}
public function getModel(): string
{
return Foo::class;
}
public function getDocument(): array
{
$posts = $this->postRepository->findAll();
if (0 === \count($posts)) {
return [];
}
$collection = [];
array_walk($posts, function (Post $post) use (&$collection): void {
$collection[] = [
'id' => $post->getId(),
'title' => $post->getTitle(),
'tags' => $post->getTagsAsArray(),
];
});
return $collection;
}
}
Sometimes, a provider must be loader before another one, this bundle provides a PriorityDataProviderInterface that allows to define a priority individually, during the loading process, the DocumentLoader takes this integer and compare every provider in order to load in the desired order.