letkode/data-provider-bundle

Attribute-driven, namespaced data provider registry and endpoint for Symfony applications

Maintainers

Package info

github.com/letkode/data-provider-bundle

Type:symfony-bundle

pkg:composer/letkode/data-provider-bundle

Transparency log

Statistics

Installs: 6

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.1.0 2026-07-24 04:52 UTC

This package is auto-updated.

Last update: 2026-07-24 04:52:38 UTC


README

Attribute-driven, namespaced data provider registry and endpoint for Symfony applications.

Allows any service to expose named, aliased method sets under a provider group (a namespace such as form-options, search, reports, etc.), which are then discoverable at runtime through a single REST endpoint. It generalizes the "expose a repository method as an option list" pattern so it can be reused for any read-only, alias-driven data access use case — not just form options.

Installation

composer require letkode/data-provider-bundle

Symfony Flex will register the bundle automatically. If not using Flex, add it manually:

// config/bundles.php
return [
    Letkode\DataProviderBundle\DataProviderBundle::class => ['all' => true],
];

Import the routes to expose the endpoint:

# config/routes/letkode_data_provider.yaml
letkode_data_provider:
    resource: '@LetkodeDataProviderBundle/config/routes.yaml'

Usage

1. Mark a service as a provider

use Letkode\DataProviderBundle\Attribute\DataProvider;
use Letkode\DataProviderBundle\Attribute\DataProviderMethod;

#[DataProvider(providerGroup: 'form-options', alias: 'countries')]
final class CountryRepository extends ServiceEntityRepository
{
    #[DataProviderMethod(alias: 'active')]
    public function findActiveAsOptions(): array
    {
        return $this->createQueryBuilder('c')
            ->select('c.uuid, c.code, c.name')
            ->where('c.active = true')
            ->getQuery()
            ->getArrayResult();
    }
}

2. Fetch data via the API

GET /api/providers/form-options/countries/active
[
    { "uuid": "...", "code": "CL", "name": "Chile" },
    { "uuid": "...", "code": "AR", "name": "Argentina" }
]

3. Reuse the same mechanism for other domains

The providerGroup namespaces providers so unrelated features can reuse the same alias without colliding:

#[DataProvider(providerGroup: 'search', alias: 'countries')]
final class CountrySearchService
{
    #[DataProviderMethod(alias: 'by-name')]
    public function searchByName(): array { /* ... */ }
}
GET /api/providers/search/countries/by-name?q=chi

4. Discover providers within a group

GET /api/providers/form-options
[
    { "alias": "countries", "methods": ["active"] },
    { "alias": "roles", "methods": ["list"] }
]

How it works

  • DataProviderBundle::build() calls registerAttributeForAutoconfiguration() so any service annotated with #[DataProvider] is automatically tagged as letkode.data_provider.
  • ProviderRegistry collects all tagged providers via #[AutowireIterator] and indexes them in three levels: providerGroup → classAlias → methodAlias.
  • DataProviderController resolves providerGroup + classAlias + methodAlias and returns the result as JSON. Query parameters, if present, are passed as a single array argument to the resolved method.
  • DataProviderController also exposes GET /api/providers/{providerGroup} to list every provider and its exposed methods within a given group, for runtime discovery.

Requirements

  • PHP ^8.4
  • Symfony ^7.0 || ^8.0

License

MIT — see LICENSE.