API Platform Integration
API Platform integration is opt-in. The mere presence of #[AsDataTable(Entity::class)] does not activate any API Platform behavior. You must explicitly enable it with one of the two opt-in mechanisms below.
Opt-in mechanisms
1) Attribute opt-in: #[AsDataTable(..., apiPlatform: true)]
Add apiPlatform: true to the attribute on your DataTable class. This enables:
- Automatic Ajax URL resolution from API Platform collection metadata
- Auto-detection of columns from API Platform property metadata
use Pentiminax\UX\DataTables\Attribute\AsDataTable;
use Pentiminax\UX\DataTables\Model\AbstractDataTable;
#[AsDataTable(entityClass: Book::class, apiPlatform: true)]
class BookDataTable extends AbstractDataTable
{
}
2) Imperative opt-in: DataTable::apiPlatform(true) in configureDataTable()
Use this mode when you need to point to an explicit Ajax URL (e.g. a custom endpoint) while still using the API Platform Hydra adapter on the frontend.
use Pentiminax\UX\DataTables\Model\DataTable;
public function configureDataTable(DataTable $table): DataTable
{
return $table
->ajax('/api/books')
->serverSide(true)
->apiPlatform(true);
}
When apiPlatform(true) is called in configureDataTable() but no explicit ajax() URL is set, the bundle will still attempt to resolve the collection URL automatically from API Platform metadata (provided #[AsDataTable] is present).
Ajax auto-wiring (attribute opt-in only)
When #[AsDataTable(entityClass: Book::class, apiPlatform: true)] is present and no explicit ajax() or data() option has been set, the bundle resolves the API Platform collection URL and configures Ajax automatically.
| Option | Value |
|---|---|
| `ajax.url` | Resolved from API Platform collection metadata (e.g. `/api/books`) |
| `ajax.type` | `GET` |
| `apiPlatform` | `true` |
Auto-wiring is skipped if:
ajax()is already set (explicit URL takes priority)data()is already set (client-side mode)- No collection URL can be resolved from API Platform metadata
Frontend adapter (both opt-ins)
When apiPlatform is enabled, the Stimulus controller activates a Hydra adapter that converts:
| Input | Output |
|---|---|
| DataTables query params | API Platform params (`page`, `itemsPerPage`, `order[field]`, `q`, filters) |
| Hydra response (`hydra:member`, `hydra:totalItems`) | DataTables response shape |
Notes:
- Date formatting is handled by the backend payload. The adapter does not reformat date values on the client.
- When API Platform adapter mode is enabled,
serverSideis enforced so sorting and filtering stay consistent with API queries.
Global search
The DataTables global search box is mapped to the API Platform q query parameter.
use ApiPlatform\Doctrine\Orm\Filter\FreeTextQueryFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrFilter;
use ApiPlatform\Doctrine\Orm\Filter\PartialSearchFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\QueryParameter;
#[ApiResource(operations: [
new GetCollection(parameters: [
'q' => new QueryParameter(
filter: new OrFilter(new FreeTextQueryFilter(new PartialSearchFilter())),
properties: ['email', 'firstName', 'lastName'],
),
]),
])]
final class User
{
}
Column auto-detection
Column auto-detection from API Platform property metadata is also gated behind the opt-in. Without apiPlatform: true, the auto-detector is never called even if API Platform is installed.
#[AsDataTable] supports serialization groups to filter exposed properties:
#[AsDataTable(Book::class, serializationGroups: ['book:list'], apiPlatform: true)]
Frequent pitfalls
- Using
#[AsDataTable(Entity::class)]alone and expecting Ajax or columns to be auto-configured — addapiPlatform: true. - Enabling adapter mode without an Ajax endpoint.
- Expecting auto Ajax wiring when
ajax()ordata()is already set. - Forgetting that non-readable resource properties are skipped in auto-detection.