-
Notifications
You must be signed in to change notification settings - Fork 2
CrudIncludePreloader
Pair\Api\CrudIncludePreloader lets a CRUD resource bulk-load relationship includes before CrudController transforms each record.
Use it when GET /api/{resource}?include=... would otherwise run one relation query per parent record.
namespace Pair\Api;
use Pair\Orm\ActiveRecord;
interface CrudIncludePreloader {
public function preload(array $objects, array $includes, CrudResourceConfig $config): array;
}The returned array must be grouped by include name, then by parent key:
[
'group' => [
7 => $groupRecord,
8 => $anotherGroupRecord,
],
]Parent keys may be:
- the parent record primary key
- the original collection key
spl_object_id($parent)
Relation values may be null, an ActiveRecord, or a Pair\Orm\Collection. CrudController still applies includeReadModels, includeResources, or the related model's own CRUD config before writing the response payload.
$this->crud('users', \App\Orm\User::class, [
'readModel' => \App\Api\ReadModels\UserReadModel::class,
'includes' => ['group'],
'includeReadModels' => [
'group' => \App\Api\ReadModels\GroupReadModel::class,
],
'includePreloader' => \App\Api\Preloaders\UserIncludePreloader::class,
]);includePreloader is optional. If it is not configured, CrudController keeps the legacy per-record include loading behavior.
When configured, the class must exist and implement Pair\Api\CrudIncludePreloader; invalid classes fail explicitly with a LogicException.
- The preloader runs once per collection response, not once per record.
- Return only includes requested in the current response.
- Do not change response shapes in the preloader; it should load relation objects, not serialize them.
- Return
Pair\Orm\Collectionvalues for many-record relations so Pair can keep the same include transformation path. - Keep authorization and tenant filters in the bulk query, exactly as you would in per-record relation methods.
See also: CrudController, CrudResourceConfig, ApiExposable.