Skip to content

Resource

Viames Marino edited this page Feb 23, 2026 · 2 revisions

Pair framework: Resource

Pair\Api\Resource is the base transformer for API output.

It decouples domain/ActiveRecord objects from JSON response format.

Core methods

__construct(mixed $data)

Stores the underlying object/data instance.

toArray(): array (abstract)

Must be implemented in each resource class.

jsonSerialize(): array

Returns toArray() so resources are directly serializable with json_encode().

Resource::collection(iterable $items): array

Transforms many items into an array of resource arrays.

Implementation example

<?php

namespace App\Api\Resources;

use Pair\Api\Resource;

class UserResource extends Resource {

    public function toArray(): array
    {
        $u = $this->data;

        return [
            'id' => (int)$u->id,
            'name' => (string)$u->name,
            'email' => (string)$u->email,
            'active' => (bool)$u->active,
        ];
    }

}

Usage examples

Single item:

$data = (new UserResource($user))->toArray();
ApiResponse::respond($data);

Collection:

$data = UserResource::collection($users);
ApiResponse::respond($data);

With CrudController

In model API config:

'resource' => App\Api\Resources\UserResource::class,

Then CrudController automatically uses your transformer.

Frequent usage recipes

Include nested relation data

class UserResource extends \Pair\Api\Resource {

    public function toArray(): array
    {
        $u = $this->data;

        return [
            'id' => (int)$u->id,
            'email' => (string)$u->email,
            'group' => $u->groupId ? [
                'id' => (int)$u->groupId
            ] : null,
        ];
    }
}

Stable API formatting (dates, booleans, nullable fields)

class OrderResource extends \Pair\Api\Resource {

    public function toArray(): array
    {
        $o = $this->data;

        return [
            'id' => (int)$o->id,
            'total' => (float)$o->total,
            'paid' => (bool)$o->paid,
            'createdAt' => $o->formatDateTime('createdAt', 'Y-m-d H:i:s'),
            'note' => $o->note ? (string)$o->note : null,
        ];
    }
}

Use collection transformation in custom actions

$orders = \App\Orm\Order::latest()->limit(50)->get();
$data = \App\Api\Resources\OrderResource::collection($orders);

\Pair\Api\ApiResponse::respond($data);

Common pitfalls

  • Leaking internal model fields by returning raw toArray() everywhere.
  • Inconsistent types across endpoints (string vs int/bool).
  • Heavy N+1 relation calls inside toArray() without caching strategy.

See also: CrudController, ApiExposable, ApiResponse.

Clone this wiki locally