kachnitel/datasource-contracts

Interfaces and value objects defining the DataSource contract for admin-style list views

Maintainers

Package info

github.com/kachnitel/datasource-contracts

pkg:composer/kachnitel/datasource-contracts

Statistics

Installs: 6

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

dev-master 2026-03-14 08:41 UTC

This package is auto-updated.

Last update: 2026-03-14 19:24:51 UTC


README

Interfaces and value objects defining the DataSource contract for admin-style list views. Zero framework dependencies — pure PHP.

Installation

composer require kachnitel/datasource-contracts

Implementing a custom data source

use Kachnitel\DataSourceContracts\ColumnMetadata;
use Kachnitel\DataSourceContracts\DataSourceInterface;
use Kachnitel\DataSourceContracts\FilterMetadata;
use Kachnitel\DataSourceContracts\FlatColumnGroupsTrait;
use Kachnitel\DataSourceContracts\PaginatedResult;

class ApiProductDataSource implements DataSourceInterface
{
    use FlatColumnGroupsTrait; // satisfies getColumnGroups() for non-grouped sources

    public function getIdentifier(): string { return 'api-products'; }
    public function getLabel(): string { return 'API Products'; }
    public function getIcon(): ?string { return 'cloud'; }

    public function getColumns(): array
    {
        return [
            'id'     => ColumnMetadata::create('id', 'ID', 'integer'),
            'name'   => ColumnMetadata::create('name'),
            'status' => ColumnMetadata::create('status'),
        ];
    }

    public function getFilters(): array
    {
        return [
            'name'   => FilterMetadata::text('name', 'Name'),
            'status' => FilterMetadata::enum('status', ['active', 'inactive']),
        ];
    }

    public function getDefaultSortBy(): string { return 'id'; }
    public function getDefaultSortDirection(): string { return 'DESC'; }
    public function getDefaultItemsPerPage(): int { return 25; }

    public function query(
        string $search, array $filters,
        string $sortBy, string $sortDirection,
        int $page, int $itemsPerPage,
    ): PaginatedResult {
        // call your API or DB ...
        return new PaginatedResult(items: $results, totalItems: $total, currentPage: $page, itemsPerPage: $itemsPerPage);
    }

    public function supportsAction(string $action): bool
    {
        return in_array($action, ['index', 'show'], true);
    }

    public function find(string|int $id): ?object { /* ... */ }
    public function getIdField(): string { return 'id'; }
    public function getItemId(object $item): string|int { return $item->id; }
    public function getItemValue(object $item, string $field): mixed { return $item->{$field} ?? null; }
}

Composite columns

use Kachnitel\DataSourceContracts\ColumnGroup;

public function getColumnGroups(): array
{
    return [
        'id',
        new ColumnGroup(
            id: 'name',
            label: 'Full Name',
            columns: [
                'firstName' => ColumnMetadata::create('firstName', 'First'),
                'lastName'  => ColumnMetadata::create('lastName', 'Last'),
            ],
            subLabels: ColumnGroup::SUB_LABELS_ICON,
            header: ColumnGroup::HEADER_COLLAPSIBLE,
        ),
    ];
}

Available value objects

Class Purpose
ColumnMetadata Describes a column (name, label, type, sortable, template, group)
ColumnGroup Groups columns into a composite table cell
FilterMetadata Describes a filter widget with factory methods per type
FilterEnumOptions Enum/select filter options (values list or enum class)
PaginatedResult Query result container with pagination helpers
PaginationInfo Slim pagination state for display templates

Interfaces

Interface Purpose
DataSourceInterface Main contract for any tabular data source
DataSourceProviderInterface Yields multiple data sources from one service
SearchAwareDataSourceInterface Optional: advertise which columns are globally searched

Requirements

  • PHP 8.1+
  • No other dependencies