RecordMapper - viames/pair GitHub Wiki
Pair framework: RecordMapper
Pair\Data\RecordMapper converts persistence records into explicit Pair v4 read models.
It is intentionally strict: the target class must exist, implement ReadModel, and implement MapsFromRecord.
Basic mapping
use Pair\Data\RecordMapper;
$customer = new Customer(7);
$readModel = RecordMapper::map($customer, CustomerReadModel::class);
return new \Pair\Http\JsonResponse($readModel);
JsonResponse will call toArray() because the mapped object implements ReadModel.
Read model used by the mapper
use Pair\Data\ArraySerializableData;
use Pair\Data\MapsFromRecord;
use Pair\Data\ReadModel;
use Pair\Orm\ActiveRecord;
/**
* Public account payload used by API responses.
*/
final readonly class AccountReadModel implements ReadModel, MapsFromRecord {
use ArraySerializableData;
/**
* Build the account payload.
*/
public function __construct(
public int $id,
public string $name,
public bool $active
) {}
/**
* Build the account payload from the persistence model.
*/
public static function fromRecord(ActiveRecord $record): static {
return new self(
(int)$record->id,
(string)$record->name,
(bool)$record->active
);
}
/**
* Export the public account payload.
*
* @return array<string, mixed>
*/
public function toArray(): array {
return [
'id' => $this->id,
'name' => $this->name,
'active' => $this->active,
];
}
}
In a collection
use Pair\Data\RecordMapper;
$rows = [];
foreach (Account::query()->where('active', 1)->get() as $account) {
$rows[] = RecordMapper::map($account, AccountReadModel::class)->toArray();
}
return \Pair\Api\ApiResponse::jsonResponse(['data' => $rows]);
For CRUD resources, CrudController runs this mapping internally when readModel is configured.
Validation behavior
RecordMapper::map() throws InvalidArgumentException when:
- the read-model class does not exist
- the class does not implement
Pair\Data\ReadModel - the class does not implement
Pair\Data\MapsFromRecord
This keeps bad API configuration visible during development instead of silently falling back to persistence serialization.
See also: ReadModel, MapsFromRecord, Payload, CrudController, SearchIndexableReadModel.