When building an API it is common for people to just grab stuff from the database and pass it to json_encode(). The problem with this approach is that it can quickly lead to inconsistent output - for example when a database table schema changes.

A data transformer acts as the middle-man between the data fetched and what is output to ensure consistency. Think of it as a view layer for your data. Below is a transformer class and example that you can extend to write your own transformers.

<?php
abstract class Transformer
{
    /**
     * @var mixed
     */
    protected $data;

    /**
     * Constructor.
     *
     * @param mixed $data
     */
    public function __construct($data)
    {
        $this->setData($data);
    }

    /**
     * Set the data.
     *
     * @param mixed $data
     */
    public function setData($data)
    {
        $this->data = $data;
    }

    /**
     * Get the data.
     *
     * @return mixed
     */
    public function getData()
    {
        return $this->data;
    }

    /**
     * Transform the data into an array.
     *
     * @return array
     */
    abstract public function transform();

    /**
     * Return the transformed data as a JSON string.
     *
     * @param int $options
     *
     * @return string
     */
    public function json($options = 0)
    {
        $data = json_encode($this->transform(), $options);

        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new \InvalidArgumentException(json_last_error_msg());
        }

        return $data;
    }
}

Now let's create a specific transformer for outputting a user's data.

<?php
class UserTransformer extends Transformer
{
    /**
     * {@inheritdoc}
     */
    public function transform()
    {
        $data = $this->getData();

        return [
            'userID' => (int) $data['id'],
            'userName' => $data['first_name'].' '.$data['last_name'],
            'userCreated' => date('Y-m-d H:i:s', $data['created']),
        ];
    }
}

And finally we call the user transformer from our controller, passing in the user's data and outputting as JSON.

<?php
class UserController
{
    /**
     * An example controller that find's a user and outputs JSON
     */
    public function find($id)
    {
        $data = $this->user->find($id); // this might come from a database somewhere
        $transform = new UserTransformer($data);

        header('Content-Type: application/json');
        echo $transform->json();
    }
}

Response method

If you use Laravel or Lumen an extra method that I use in my Transformer class is response:

<?php
/**
 * Return the transformed data as a JSON response.
 *
 * @param int   $status
 * @param array $headers
 * @param int   $options
 *
 * @return \Illuminate\Http\JsonResponse
 */
public function response($status = 200, array $headers = [], $options = 0)
{
    return response()->json($this->transform(), $status, $headers, $options);
}

Then in my controller I can just return $transform->response(201); to get a JSON response with a 201 status code for example.