API Resources
When building APIs, you often need to transform your data models into a consistent format before sending them to the client. API Resources, implemented through transformers, provide a clean way to convert your entities, arrays, or objects into structured API responses. They help separate your internal data structure from what you expose through your API, making it easier to maintain and evolve your API over time.
Quick Example
The following example shows a common usage pattern for transformers in your application.
<?php
namespace App\Transformers;
use CodeIgniter\API\BaseTransformer;
class UserTransformer extends BaseTransformer
{
public function toArray(mixed $resource): array
{
return [
'id' => $resource['id'],
'name' => $resource['name'],
'email' => $resource['email'],
'created_at' => $resource['created_at'],
];
}
}
// In your controller
$user = model('UserModel')->find(1);
$transformer = new UserTransformer();
return $this->respond($transformer->transform($user));
In this example, the UserTransformer defines which fields from a user entity should be included in the
API response. The transform() method converts a single resource, while transformMany() handles
collections of resources.
Creating a Transformer
To create a transformer, extend the BaseTransformer class and implement the toArray() method to
define your API resource structure. The toArray() method receives the resource being transformed as
a parameter, allowing you to access and transform its data.
Basic Transformer
<?php
namespace App\Transformers;
use CodeIgniter\API\BaseTransformer;
class UserTransformer extends BaseTransformer
{
public function toArray(mixed $resource): array
{
return [
'id' => $resource['id'],
'username' => $resource['name'], // Renaming the field
'email' => $resource['email'],
'member_since' => date('Y-m-d', strtotime($resource['created_at'])), // Formatting
];
}
}
The toArray() method receives the resource (entity, array, or object) as its parameter and defines
the structure of your API response. You can include any fields you want from the resource, and you can
also rename or transform values as needed.
Generating Transformer Files
CodeIgniter provides a CLI command to quickly generate transformer skeleton files:
php spark make:transformer User
This creates a new transformer file at app/Transformers/User.php with the basic structure already in place.
Command Options
The make:transformer command supports several options:
- –suffix
Appends “Transformer” to the class name:
php spark make:transformer User --suffixCreates app/Transformers/UserTransformer.php
- –namespace
Specifies a custom root namespace:
php spark make:transformer User --namespace="MyCompany\\API"- –force
Forces overwriting an existing file:
php spark make:transformer User --force
Subdirectories
You can organize transformers into subdirectories by including the path in the name:
php spark make:transformer api/v1/User
This creates app/Transformers/Api/V1/User.php with the appropriate namespace App\Transformers\Api\V1.
Using Transformers in Controllers
Once you’ve created a transformer, you can use it in your controllers to transform data before returning it to the client.
<?php
namespace App\Controllers;
use App\Transformers\UserTransformer;
use CodeIgniter\API\ResponseTrait;
class Users extends BaseController
{
use ResponseTrait;
public function show($id)
{
$user = model('UserModel')->find($id);
if (! $user) {
return $this->failNotFound('User not found');
}
$transformer = new UserTransformer();
return $this->respond($transformer->transform($user));
}
public function index()
{
$users = model('UserModel')->findAll();
$transformer = new UserTransformer();
return $this->respond($transformer->transformMany($users));
}
}
Field Filtering
The transformer automatically supports field filtering through the fields query parameter of the current URL.
This allows API clients to request only specific fields they need, reducing bandwidth and improving performance.
<?php
namespace App\Transformers;
use CodeIgniter\API\BaseTransformer;
class UserTransformer extends BaseTransformer
{
public function toArray(mixed $resource): array
{
return [
'id' => $resource['id'],
'name' => $resource['name'],
'email' => $resource['email'],
'created_at' => $resource['created_at'],
'updated_at' => $resource['updated_at'],
];
}
}
// Request: GET /users/1?fields=id,name
// Response: {"id": 1, "name": "John Doe"}
A request to /users/1?fields=id,name would return only:
{
"id": 1,
"name": "John Doe"
}
Restricting Available Fields
By default, clients can request any field defined in your toArray() method. You can restrict which
fields are allowed by overriding the getAllowedFields() method:
<?php
namespace App\Transformers;
use CodeIgniter\API\BaseTransformer;
class UserTransformer extends BaseTransformer
{
public function toArray(mixed $resource): array
{
return [
'id' => $resource['id'],
'name' => $resource['name'],
'email' => $resource['email'],
'created_at' => $resource['created_at'],
'updated_at' => $resource['updated_at'],
];
}
protected function getAllowedFields(): ?array
{
// Only these fields can be requested
return ['id', 'name', 'created_at'];
}
}
Now, even if a client requests /users/1?fields=email, an ApiException will be thrown because
email is not in the allowed fields list.
Transforming Collections
The transformMany() method makes it easy to transform arrays of resources:
<?php
namespace App\Controllers;
use App\Transformers\UserTransformer;
use CodeIgniter\API\ResponseTrait;
class Users extends BaseController
{
use ResponseTrait;
public function index()
{
$users = model('UserModel')->findAll();
$transformer = new UserTransformer();
$data = $transformer->transformMany($users);
return $this->respond($data);
}
}
The transformMany() method applies the same transformation logic to each item in the collection,
including any field filtering or includes specified in the request.
Working with Different Data Types
Transformers can handle various data types, not just entities.
Transforming Entities
When you pass an Entity instance to transform(), it automatically calls the entity’s toArray()
method to get the data:
<?php
use App\Entities\User;
use App\Transformers\UserTransformer;
$user = new User([
'id' => 1,
'name' => 'John Doe',
'email' => 'john@example.com',
]);
$transformer = new UserTransformer();
$result = $transformer->transform($user);
Transforming Arrays
You can transform plain arrays as well:
<?php
use App\Transformers\UserTransformer;
$userData = [
'id' => 1,
'name' => 'John Doe',
'email' => 'john@example.com',
];
$transformer = new UserTransformer();
$result = $transformer->transform($userData);
Transforming Objects
Any object can be cast to an array and transformed:
<?php
use App\Transformers\UserTransformer;
$user = new \stdClass();
$user->id = 1;
$user->name = 'John Doe';
$user->email = 'john@example.com';
$transformer = new UserTransformer();
$result = $transformer->transform($user);
Using toArray() Only
If you don’t pass a resource to transform(), it will use the data from your toArray() method:
<?php
namespace App\Transformers;
use CodeIgniter\API\BaseTransformer;
class StaticDataTransformer extends BaseTransformer
{
public function toArray(mixed $resource): array
{
return [
'version' => '1.0',
'status' => 'active',
'message' => 'API is running',
];
}
}
// Usage
$transformer = new StaticDataTransformer();
$result = $transformer->transform(null); // No resource passed
Class Reference
- class CodeIgniter\API\BaseTransformer
- __construct(?IncomingRequest $request = null)
- Parameters:
$request (
IncomingRequest|null) – Optional request instance. If not provided, the global request will be used.
Initializes the transformer and extracts the
fieldsandincludequery parameters from the request.
- toArray(mixed $resource)
- Parameters:
$resource (
mixed) – The resource being transformed (Entity, array, object, or null)
- Returns:
The array representation of the resource
- Return type:
array
This abstract method must be implemented by child classes to define the structure of the API resource. The resource parameter contains the data being transformed. Return an array with the fields you want to include in the API response, accessing data from the
$resourceparameter.<?php namespace App\Transformers; use CodeIgniter\API\BaseTransformer; class ProductTransformer extends BaseTransformer { public function toArray(mixed $resource): array { return [ 'id' => $resource['id'], 'name' => $resource['name'], 'price' => $resource['price'], 'in_stock' => $resource['stock_quantity'] > 0, 'description' => $resource['description'], ]; } }
- transform($resource = null)
- Parameters:
$resource (
mixed) – The resource to transform (Entity, array, object, or null)
- Returns:
The transformed array
- Return type:
array
Transforms the given resource into an array by calling
toArray()with the resource data. If$resourceisnull, passesnulltotoArray(). If it’s an Entity, extracts its array representation first. Otherwise, casts it to an array.The resource is also stored in
$this->resourceso include methods can access it.The method automatically applies field filtering and includes based on query parameters.
<?php use App\Transformers\UserTransformer; $user = model('UserModel')->find(1); $transformer = new UserTransformer(); // Transform an entity $result = $transformer->transform($user); // Transform an array $userData = ['id' => 1, 'name' => 'John Doe']; $result = $transformer->transform($userData); // Use toArray() data $result = $transformer->transform();
- transformMany(array $resources)
- Parameters:
$resources (
array) – The array of resources to transform
- Returns:
Array of transformed resources
- Return type:
array
Transforms a collection of resources by calling
transform()on each item. Field filtering and includes are applied consistently to all items.<?php use App\Transformers\UserTransformer; $users = model('UserModel')->findAll(); $transformer = new UserTransformer(); $results = $transformer->transformMany($users); // $results is an array of transformed user arrays foreach ($results as $user) { // Each $user is the result of calling transform() on an individual user }
- getAllowedFields()
- Returns:
Array of allowed field names, or
nullto allow all fields- Return type:
array|null
Override this method to restrict which fields can be requested via the
fieldsquery parameter. Returnnull(the default) to allow all fields fromtoArray(). Return an array of field names to create a whitelist of allowed fields.<?php namespace App\Transformers; use CodeIgniter\API\BaseTransformer; class UserTransformer extends BaseTransformer { public function toArray(mixed $resource): array { return [ 'id' => $resource['id'], 'name' => $resource['name'], 'email' => $resource['email'], 'created_at' => $resource['created_at'], ]; } protected function getAllowedFields(): ?array { // Clients can only request id, name, and created_at // Attempting to request 'email' will throw an ApiException return ['id', 'name', 'created_at']; } }
- getAllowedIncludes()
- Returns:
Array of allowed include names, or
nullto allow all includes- Return type:
array|null
Override this method to restrict which related resources can be included via the
includequery parameter. Returnnull(the default) to allow all includes that have corresponding methods. Return an array of include names to create a whitelist. Return an empty array to disable all includes.<?php namespace App\Transformers; use CodeIgniter\API\BaseTransformer; class UserTransformer extends BaseTransformer { public function toArray(mixed $resource): array { return [ 'id' => $resource['id'], 'name' => $resource['name'], 'email' => $resource['email'], ]; } protected function getAllowedIncludes(): ?array { // Only 'posts' can be included via ?include=posts // Attempting to include 'orders' will throw an ApiException return ['posts']; } protected function includePosts(): array { $posts = model('PostModel')->where('user_id', $this->resource['id'])->findAll(); return (new PostTransformer())->transformMany($posts); } protected function includeOrders(): array { // This method exists but cannot be called via the API $orders = model('OrderModel')->where('user_id', $this->resource['id'])->findAll(); return (new OrderTransformer())->transformMany($orders); } }
Exception Reference
- class CodeIgniter\API\ApiException
- static forInvalidFields(string $field)
- Parameters:
$field (
string) – The invalid field name(s)
- Returns:
ApiException instance
- Return type:
Thrown when a client requests a field via the
fieldsquery parameter that is not in the allowed fields list.
- static forInvalidIncludes(string $include)
- Parameters:
$include (
string) – The invalid include name(s)
- Returns:
ApiException instance
- Return type:
Thrown when a client requests an include via the
includequery parameter that is not in the allowed includes list.
- static forMissingInclude(string $include)
- Parameters:
$include (
string) – The missing include method name
- Returns:
ApiException instance
- Return type:
Thrown when a client requests an include via the
includequery parameter, but the correspondinginclude*()method does not exist in the transformer class. This validation ensures that all requested includes have proper handler methods defined.