linkorb/primate

Primate: Restful API Library

dev-master 2016-04-30 10:20 UTC

README

687474703a2f2f7777772e6561727468746f7563686e6577732e636f6d2f6d656469612f3338353833362f73637265656e2d73686f742d323031342d30382d32312d61742d3130313234342d616d2d363430783833345f47616c6c6572794c617267652e706e67

Primate is a library that helps creating beautiful REST APIs.

It is heavily inspired by Stormpath's "The Fundamentals of REST API Design"

Using Primate

First you'll need to instantiate Primate, before your app can serve requests:

use Primate\Primate;

$primate = new Primate();
$primate->setBaseUrl('http://primate.example.com/api/v1');
$primate->setProperty('tenant', 'joe');
$primate->setProperty('x', 'y');

You'll notice that the BaseUrl of your API is set on the Primate instance, in order to output correct urls.

Additionally, we're registering some arbitrary properties to define the context of the requests. You can use these properties later in order to fetch resources.

Resources and Collections

In Primate APIs, a client can work with Resources and Collections.

  • A Resource is simply an "object" in your application. For example, a User, a Product, etc.
  • A Collection is simply an array of Resources.

Types

Each Resource is of a specified Type.

In Primate, you'll need to register one or more Types before you can use them. For example:

$repo = new MyContactRepository();
$type = new Type('contacts', $repo);
$primate->registerType($type);

Each Type has a name and a repository. The Repository can be any class that's implementing the Primate\RepositoryInterface.

It's recommended to take your existing application repositories, and make them implement this interface.

For example:

<?php

namespace Example;

use Primate\RepositoryInterface;
use Primate\Resource;
use Primate\Primate;
use RuntimeException;

class PdoContactRepository implements RepositoryInterface
{
    public function __construct($pdo)
    {
        $this->pdo = $pdo;
    }
    
    // Implement your regular repository methods here...
    
    public function loadResourceCollection(Collection $collection, Primate $primate)
    {
        foreach ($this->getAllContacts() as $contact) {
            $resource = new Resource($collection->getType(), $contact->getId());
            $collection->addResource($resource);
        }
    }
    
    public function loadResources($resources, Primate $primate)
    {
        foreach ($resources as $resource) {
            $contact = $this->findById($resource->getId());
            $resource->setProperty('name', $contact->getName());
            $resource->setProperty('gender', $contact->getGender());
            $phoneResource = $primate->createResource('phones', $contact->getPhoneId());
            $resource->setProperty('phone', $phoneResource);
        }
    }
}

Primate will call these methods to load resource data.

Calling Primate

You can make requests to Primate like this:

$data = $primate->getDataByPath($path, $expands);
echo json_encode($data, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);

The path variable is either:

  • /{typeName}: This will return a collection of all resources of that type
  • /{typeName}/{resourceId}: This will return the specific resource

Additionally, you can pass an array of expands.

Sub-resource expansion

When passing keys in the expands parameter, Primate will automatically expand the specified sub-resources.

For example, if your first response looks like this:

{
    "href": "http://primate.example.com/api/v1/contacts/1",
    "name": "Alice",
    "gender": "Female",
    "phone": {
        "href": "http://primate.example.com/api/v1/phones/xyz"
    }
}

You can ask Primate to 'expand the phone property:

{
    "href": "http://primate.example.com/api/v1/contacts/1",
    "name": "Alice",
    "gender": "Female",
    "phone": {
        "href": "http://primate.example.com/api/v1/phones/xyz",
        "number": "+1 987654321",
        "type": "mobile"
    }
}

License

MIT (see LICENSE.md)

Brought to you by the LinkORB Engineering team

687474703a2f2f7777772e6c696e6b6f72622e636f6d2f642f6d6574612f74696572312f696d616765732f6c696e6b6f7262656e67696e656572696e672d6c6f676f2e706e67
Check out our other projects at linkorb.com/engineering.

Btw, we're hiring!