Data Sources

DataProvider accepts a map of source identifiers to strings or DataSourceInterface instances. The manager uses these identifiers to resolve repositories.

Built-In Sources

Source Configuration value Requirements
PHP file /path/to/products.php File returns an array
JSON file /path/to/products.json Document decodes to an array using associative decoding
YAML file /path/to/products.yaml Document parses to an array; symfony/yaml is installed
Backed enum enum:App\Enum\Status Class is a string-backed or integer-backed enum

The built-in YAML reader recognizes .yaml. A raw string without the enum: prefix is treated as a file path. File reader selection uses the lowercased extension.

JSON and YAML objects or lists may describe the dataset. For example:

{
    "prod-001": {"name": "Laptop XPS", "price": 1299.99},
    "prod-002": {"name": "Keyboard", "price": 59.90}
}

Pass JSON and YAML paths through DataProvider; the direct Repository constructor treats a string as a PHP file to require.

Row Normalization

The provider converts a non-array entry into a row under nameAttribute, and fills missing identifiers under idAttribute. Defaults are name and id. Both settings must be strings.

use Derafu\Repository\Service\DataProvider;

$provider = new DataProvider(
    sources: ['payment_methods' => '/path/to/payment_methods.php'],
    config: [
        'normalization' => [
            'idAttribute' => 'codigo',
            'nameAttribute' => 'glosa',
        ],
    ],
);

For a PHP file returning [1 => 'Cash', 2 => 'Transfer'], the resulting rows are:

[
    1 => ['codigo' => 1, 'glosa' => 'Cash'],
    2 => ['codigo' => 2, 'glosa' => 'Transfer'],
];

Array rows preserve their fields and existing ID values. Source keys are preserved, including sparse numeric keys. The provider returns the normalized dataset as an ArrayObject and reuses it on subsequent fetch() calls for that identifier.

Enums

use Derafu\Repository\Service\DataProvider;
use Derafu\Repository\Service\RepositoryManager;

enum Status: string
{
    case Active = 'active';
    case Inactive = 'inactive';
}

// A plain identifier selects the manager's generic entity class.
$provider = new DataProvider(['statuses' => 'enum:' . Status::class]);
$repository = (new RepositoryManager($provider))->getRepository('statuses');
$active = $repository->find('active');

The enum source emits case value => case name; the provider then normalizes it. Here the generic entity contains id = 'active' and name = 'Active'.

To return enum cases themselves, configure the enum class as the repository entity, as described in entities and mapping.

Custom Data Sources

Implement DataSourceInterface::read(): array and pass the instance directly. The following example reads a complete catalogue through an application-supplied callback:

use Derafu\Repository\Contract\DataSourceInterface;
use Derafu\Repository\Service\DataProvider;

final class CatalogSource implements DataSourceInterface
{
    /** @param Closure(): array<array-key, mixed> $readCatalog */
    public function __construct(private readonly Closure $readCatalog)
    {
    }

    public function read(): array
    {
        return ($this->readCatalog)();
    }
}

$source = new CatalogSource(fn (): array => ['A' => ['name' => 'Alpha']]);
$provider = new DataProvider(['catalog' => $source]);

A PDO-backed source is possible, but this contract reads the whole dataset before queries run in memory. Use a repository factory when queries should execute directly against the database.

For custom string schemes, implement DataSourceResolverInterface and supply a DataSourceResolverRegistry. Resolver order matters: the built-in file resolver accepts every string, so it must come last. Providing a resolver iterable replaces the default resolver list; registering after the catch-all cannot override it. Implement FileFormatReaderInterface and provide a FileFormatReaderRegistry to support additional file formats.

Caching and Data Lifetime

The optional $cache constructor argument accepts a PSR-16 cache. It stores raw data before normalization. An array, including an empty array, is a hit; a non-array result is treated as a miss and the source is read again. Cache backend exceptions propagate.

Independently of that cache, the provider keeps loaded normalized datasets in memory. Updating a file or the external cache does not refresh a dataset already loaded by that provider instance. There is no refresh API on DataProvider.

Errors

Invalid source definitions, unsupported formats, non-backed enums and invalid normalization settings raise DataProviderException. An unreadable JSON file also raises that exception. PHP file execution, YAML parsing and application-supplied sources can additionally raise their own errors.

On this page

Last updated on 20/10/2026 by Anonymous