-
Notifications
You must be signed in to change notification settings - Fork 2
ApiExposable
Pair\Api\ApiExposable is a trait for ActiveRecord models used by CrudController.
It defines API behavior such as filtering, sorting, searchable fields, includes, pagination limits, validation rules, and the explicit response contract used by Pair v4 CRUD endpoints.
Use this trait on ActiveRecord models that must be exposed through auto-CRUD endpoints with strict, explicit query and output policies.
Override this in your model to define API configuration.
Returns merged config (apiConfig() + framework defaults) as a legacy-compatible array.
Returns the same merged config as a typed Pair\Api\CrudResourceConfig value object for internal CRUD consumers.
The normalized config is cached per model class through CrudResourceMetadata.
Convenience checks against merged configuration.
The preferred Pair v4 configuration is readModel.
This makes the public API payload explicit and reusable instead of exposing the persistence object shape directly.
Example:
<?php
namespace App\Models;
use Pair\Orm\ActiveRecord;
use Pair\Api\ApiExposable;
use App\Api\ReadModels\FaqReadModel;
class Faq extends ActiveRecord {
use ApiExposable;
public const TABLE_NAME = 'faqs';
/**
* Return the explicit CRUD API policy and response contract.
*
* @return array<string, mixed>
*/
public static function apiConfig(): array
{
return [
'readModel' => FaqReadModel::class,
'searchable' => ['question', 'answer'],
'sortable' => ['createdAt', 'position'],
'filterable' => ['category', 'isPublished'],
'includes' => ['author'],
'includeReadModels' => [
'author' => \App\Api\ReadModels\AuthorReadModel::class,
],
'includePreloader' => \App\Api\Preloaders\FaqIncludePreloader::class,
'perPage' => 20,
'maxPerPage' => 100,
'defaultSort' => '-createdAt',
'rules' => [
'create' => [
'question' => 'required|string|min:3',
'answer' => 'required|string|min:3',
],
'update' => [
'question' => 'string|min:3',
'answer' => 'string|min:3',
],
],
];
}
}resource classes are still supported as a bridge for Pair v3 to v4 migrations.
Use them when the application already owns a stable transformer and you are not ready to introduce a proper readModel yet.
For new Pair v4 code, prefer readModel.
Example request:
GET /api/faqs?search=payment&sort=-createdAt&filter[isPublished]=1&page=2&perPage=20
CrudController + QueryFilter will enforce only declared searchable, sortable, and filterable fields.
Pair v4 normalizes apiConfig() through CrudResourceConfig.
This keeps array configuration source-compatible while centralizing defaults for pagination, validation rules, includes, include preloaders, read models, and legacy resource adapters.
Pair caches normalized model metadata for the current PHP process. If a test, generator, or long-running command changes model API metadata and keeps running in the same process, call:
\Pair\Api\CrudResourceMetadata::clear(\App\Models\Faq::class);- exposing internal fields in
filterableorsortable - forgetting to cap
maxPerPage - keeping the output contract implicit instead of defining
readModel
See also: CrudController, ReadModel, RecordMapper, CrudResourceConfig, CrudResourceMetadata, QueryFilter, Upgrade-to-v4