fractal

If you are building APIs in PHP you might use Fractal. This package makes working with Fractal even easier!

René Kulik on 10.02.2019

Fractal is a package to handle complex data outputs and was created by The League of Extraordinary Packages.

Fractal provides a presentation and transformation layer for complex data output, the like found in RESTful APIs, and works really well with JSON. Think of this as a view layer for your JSON/YAML/etc.

When building an API it is common for people to just grab stuff from the database and pass it to json_encode(). This might be passable for “trivial” APIs but if they are in use by the public, or used by mobile applications then this will quickly lead to inconsistent output.

To make using Fractal even easier, I wrote a convenience wrapper which will be introduced in this post.

Requirements

This package requires PHP 7.2 or higher.

Install

Via composer:

$ composer require rkulik/fractal

Usage

As this package wraps Fractal, the general usage is pretty much the same. The examples listed below demonstrate the basic workflow. For further information please refer to the Fractal documentation.

Item examples

In the following examples an item gets transformed and returned as an array. The transformation is done using either a callback or a class.

Callback for transformer

<?php

require 'vendor/autoload.php';

$fractal = new \Rkulik\Fractal\Fractal(new \League\Fractal\Manager());

$product = [
    'id' => '123',
    'name' => 'T-shirt',
    'price' => '1290',
    'brand_name' => 'Nike',
    'gender' => 'm',
];

$transformer = function (array $product): array {
    return [
        'id' => (int)$product['id'],
        'name' => $product['name'],
        'price' => (int)$product['price'],
        'brand' => $product['brand_name'],
        'gender' => $product['gender'] === 'm' ? 'male' : 'female',
    ];
};

$item = $fractal->item($product, $transformer)->toArray();

Class for transformer

Using classes for transformation is the recommended way to do so, as those transformers are easily reusable.

<?php

require 'vendor/autoload.php';

class Transformer extends \League\Fractal\TransformerAbstract {
    public function transform(array $product): array
    {
        return [
            'id' => (int)$product['id'],
            'name' => $product['name'],
            'price' => (int)$product['price'],
            'brand' => $product['brand_name'],
            'gender' => $product['gender'] === 'm' ? 'male' : 'female',
        ];
    }
}

$fractal = new \Rkulik\Fractal\Fractal(new \League\Fractal\Manager());

$product = [
    'id' => '123',
    'name' => 'T-shirt',
    'price' => '1290',
    'brand_name' => 'Nike',
    'gender' => 'm',
];

$item = $fractal->item($product, new Transformer())->toArray();

Collection example

Transforming and paginating a collection using a cursor can be achieved as follows:

<?php

require 'vendor/autoload.php';

$fractal = new \Rkulik\Fractal\Fractal(new \League\Fractal\Manager());

$products = [
    [
        'id' => '123',
        'name' => 'T-shirt',
        'price' => '1290',
        'brand_name' => 'Nike',
        'gender' => 'm',
    ],
    [
        'id' => '456',
        'name' => 'Jacket',
        'price' => '19900',
        'brand_name' => 'Carhartt',
        'gender' => 'f',
    ],
    [
        'id' => '789',
        'name' => 'Trousers',
        'price' => '3990',
        'brand_name' => 'Only & Sons',
        'gender' => 'f',
    ],
];

$transformer = function (array $product) {
    return [
        'id' => (int)$product['id'],
        'name' => $product['name'],
        'price' => (int)$product['price'],
        'brand' => $product['brand_name'],
        'gender' => $product['gender'] === 'm' ? 'male' : 'female',
    ];
};

$cursor = new \League\Fractal\Pagination\Cursor(null, null, 2, 3);

$collection = $fractal->collection([
    $products[0],
    $products[1],
], $transformer)->setCursor($cursor)->toArray();

Testing

This package has a 100% code coverage.

Code Coverage

You can run the tests using following:

$ composer test

Conclusion

Convenience wrapper for Fractal which simplifies providing complex data output. The package can be found on GitHub.