MapsFromRecord - viames/pair GitHub Wiki
Pair framework: MapsFromRecord
Pair\Data\MapsFromRecord is the companion contract for read models that can be built from a Pair ActiveRecord.
RecordMapper requires both:
ReadModelMapsFromRecord
Contract
use Pair\Data\MapsFromRecord;
use Pair\Data\ReadModel;
use Pair\Orm\ActiveRecord;
/**
* Minimal read model that can be mapped from a persistence record.
*/
final readonly class UserBadgeReadModel implements ReadModel, MapsFromRecord {
/**
* Build the badge state.
*/
public function __construct(
public int $id,
public string $label
) {}
/**
* Build the badge state from a user record.
*/
public static function fromRecord(ActiveRecord $record): static {
return new self(
(int)$record->id,
(string)$record->name
);
}
/**
* Export the public badge payload.
*
* @return array<string, mixed>
*/
public function toArray(): array {
return [
'id' => $this->id,
'label' => $this->label,
];
}
/**
* Reuse the public array representation for JSON encoding.
*
* @return array<string, mixed>
*/
public function jsonSerialize(): array {
return $this->toArray();
}
}
With the reusable JSON trait
use Pair\Data\ArraySerializableData;
use Pair\Data\MapsFromRecord;
use Pair\Data\ReadModel;
use Pair\Orm\ActiveRecord;
/**
* Compact API representation for a project.
*/
final readonly class ProjectReadModel implements ReadModel, MapsFromRecord {
use ArraySerializableData;
/**
* Build the project read model.
*/
public function __construct(
public int $id,
public string $title
) {}
/**
* Build the project read model from persistence.
*/
public static function fromRecord(ActiveRecord $record): static {
return new self((int)$record->id, (string)$record->title);
}
/**
* Export the public project payload.
*
* @return array<string, mixed>
*/
public function toArray(): array {
return [
'id' => $this->id,
'title' => $this->title,
];
}
}
Notes
fromRecord()receivesPair\Orm\ActiveRecord, so application code can accept specific subclasses internally after checking or casting.- Keep relation loading deliberate; avoid hidden database work in large collection mappings unless a preloader has already prepared the relation data.
- For CRUD includes, pair
includeReadModelswithCrudIncludePreloaderwhen relations would otherwise cause repeated queries.
See also: ReadModel, RecordMapper, CrudController, CrudIncludePreloader.