Cartalyst LLC.
API by Cartalyst
0
48
0
3
0

This package requires a valid subscription. Subscribe for access.

Introduction

Cartalyst's RESTful API package is designed to help you build modular, "API-first" RESTful applications. It makes it easy for you to build API's with support for authentication, rate limiting (coming soon) and versioning.

The application's different components are separated and talk to each other through the same RESTful API externally. Internally, object instances are returned (instead of JSON or arrays) and rate limits are bypassed.

The package follows the FIG standard PSR-0 to ensure a high level of interoperability between shared PHP code.

The package requires PHP 5.3+ and comes bundled with a Laravel 4 Facade and a Service Provider to simplify the optional framework integration.

Have a read through the Installation Guide and on how to Integrate it with Laravel 4.

Installation

Follow the steps below to install the API package in Laravel 4.

Install Sentry 2

On a default installation with Laravel, we use Sentry 2 as the authentication driver for our API package. You will need to install Sentry 2 yourself, or, use another authentication driver. Pull Requests are welcome and we can add new drivers to the default installation. We'll then provide it as a simple config option for our Laravel users.

Installing Sentry 2 in Laravel 4

Composer

Open your composer.json file and add the following lines:

{
    "require": {
        "cartalyst/api": "1.0.*"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.cartalyst.com"
        }
    ],
    "minimum-stability": "dev"
}

Note: The minimum-stability key is needed so that you can use the API (which isn't marked as stable, yet).

Run a composer update from the command line.

php composer.phar update

Service Provider

Add the following to the list of service providers in app/config/app.php.

'Cartalyst\Api\ApiServiceProvider',

Note: If you are using the Sentry authentication driver for the API package (default with Laravel 4), you will need to ensure that the SentryServiceProvider is registered before your ApiServiceProvider. This will ensure Sentry is prepared before the API package uses it.

Alias

Add the following to the to the list of class aliases in app/config/app.php.

'API' => 'Cartalyst\Api\Facades\API',

Override the following aliases to allow the typical use of the Input, Request and Response Facades (not required, but recommended). The examples in our documentation will use these Facades for simplicity.

'Input'    => 'Cartalyst\Api\Facades\Input',
'Request'  => 'Cartalyst\Api\Facades\Request',
'Response' => 'Cartalyst\Api\Facades\Response',

Configuration

After installing, you can publish the package's configuration file into you application by running the following command:

php artisan config:publish cartalyst/api

This will publish the config file to app/config/packages/cartalyst/api/config.php where you can modify the package configuration.

Integration

Laravel 4

The Api package has optional support for Laravel 4 and it comes bundled with a
Service Provider and a Facade for easier integration.

After you have installed the package, just follow the instructions.

Open your Laravel config file app/config/app.php and add the following lines.

In the $providers array add the following service provider for this package.

'Cartalyst\Api\Laravel\ApiServiceProvider',

In the $aliases array add the following facade for this package.

'API'         => 'Cartalyst\Api\Laravel\Facades\API',
'ApiResponse' => 'Cartalyst\Api\Response',

Usage

Generating Responses

Cartalyst's API package allows you to easily create RESTFul API responses. It allows you to register routes with the {api}/<api version> syntax to indicate your application's API calls.

Responses from an API route should be returned using the Cartalyst\Api\Http\Response class (which extends Illuminate\Http\Response). Using this class has a number of advantages over string-based responses:

  • It allows you to pass objects through internal requests. String-based responses must cast the object to a string and then transform it back, so you lose the ability to interact with the responses returned on internal requests.
  • It allows you to utilize special array keys, such as message and errors, which are utilized when creating internal API Exceptions.

Creating responses can be done in two different ways:

  1. Using the Cartalyst\Api\Http\Response class
  2. Using the Response::api() function which acts as a layer on top of the Cartalyst\Api\Http\Response class

With every response an optional HTTP status code can be provided. You can read more about all the different HTTP status codes here.

Note: if you didn't register the Response alias, you must use Api::createResponse() instead of Response::api().

Generating A Response

Creating API responses only requires you to send data through the Response::api() function. This can be a string or an array. Optionally, you can pass along a HTTP status code and your custom headers.

$data = array('result' => 'foo');

$response = Response::api($data, $status, $headers);

The output of this response will result an instance of Cartalyst\Api\Http\Response.

Note: When defining keys in the root of the data array make sure not to use the message or error key. Those keys are reserved by the API package to provide informative messages in your API response.

Registering Response Routes

When creating response routes for your API calls you have to prepend your routes with the {api}/<api version> syntax. The {api} part will allow Cartalyst's API package to intercept these routes when you're performing internal requests. The <api version> allows you to easily create new versions for your API.

Registering a basic route could look like the following example.

Route::get('{api}/v1/foo', function()
{
    return Response::api(array('bar'));
});

Grouping Responses

Grouping response routes by version number will allow you not to add the {api}/<api version> for each route separately.

Route::group(array('prefix' => '{api}/v1'), function()
{
    Route::get('foo', 'ApiV1\FooController@fooFunction');
    Route::get('bar', 'ApiV1\BarController@BarFunction');
});

Route::group(array('prefix' => '{api}/v2'), function()
{
    Route::get('foo', 'ApiV2\FooController@fooFunction');
    Route::get('bar', 'ApiV2\BarController@BarFunction');
});

Creating Error Messages

You can provide error messages by sending a string with the error message through the API response and providing the correct HTTP status code.

Route::get('user/{id}', function($id)
{
    $user = User::find($id);

    if (is_null($user))
    {
        return Response::api("User [$id] was not found.", 404);
    }

    return Response::api(compact('user'));
});

Internal requests will be converted to an Exception which can be caught and interacted with. Read more about catching and handling internal request exceptions here.

Accessing Request Input

If you registered the Input and Request facade aliases you can use them to safely retrieve the request's input.

Route::post('{api}/v1/users', function()
{
    $input = Input::get();

    $user = new User($input);

    // Return with a "201 Created" response.
    return Response::api(compact('user'), 201);
});

Note: If you didn't register Cartalyst's aliases for Laravel's Input and Request facades you must use API::getCurrentRequest()->input() instead. This makes sure to only retrieve the input for the current request.

Returned Responses

As you can see, for the most part, we are not doing anything different to a simple standard API. We are returning objects from our routes. On external requests, these responses are turned into arrays (and then JSON) before being sent to the browser. Internally, the objects you return are accessible.

The API is smart enough to transform any objects which inherit from Illuminate\Support\Contracts\ArrayableInterface into arrays, no matter where they lie in the response array.

You can read more on Laravel 4 responses over at their documentation.

Internal Requests

Cartalyst's API package makes it dead-simple to make internal requests to your API within your application. Each method acts virtually identically and takes the same arguments. This allows for an easy way to integrate API calls directly into your application.

It also allows you to easily work with error exceptions being thrown by your API calls.

Making Internal Requests

Making internal requests to your API is pretty easy. Just execute the a restful request as a method on the API alias. The supported methods for internal requests are GET, POST, HEAD, PUT, PATCH and DELETE.

For example, if you had a API route set up to retrieve all the users for your application, you can make an internal call to that API route by using the get() method.

$response = API::get('v1/users');

The response will return an instance of Cartalyst\Api\Http\Response.

Sending Request Parameters

You can pass along request parameters for your API request by passing along an array of data as the second parameter.

$data = array(
    'name'  => 'John Doe',
    'email' => 'john.doe@example.com'
);

$response = API::post('v1/users', $data);

Providing A Callback

You can provide a callback which is called after the request has been created and before the request is executed by passing along a closure as the third parameter. An instance of Cartalyst\Api\Http\Request (which is an extension of Illuminate\Http\Request) is provided to the callback.

$data = array(
    'name'  => 'John Doe',
    'email' => 'john.doe@example.com'
);

$response = API::get('v1/users', $data, function($request)
{
    // If the request doesn't provide a name input parameter,
    // abort the application with a "Bad request" status code.
    if ( ! $request->has('name'))
    {
        App::abort(400);
    }
});

Catching Exceptions

When making internal requests, you can catch error exceptions thrown by the API package. The exception being thrown by the API package is Cartalyst\Api\Http\ApiHttpException which extends the Symfony\Component\HttpKernel\Exception\HttpException class.

try
{
    $response = API::get('v1/users');
}
catch (Cartalyst\Api\Http\ApiHttpException $e)
{
    // Handle exception.
}

Extending the Symfony\Component\HttpKernel\Exception\HttpException class provides you with a few options to handle exceptions.

  • You can use isClientError() and isServerError() to determine the error source.
  • Using getErrors() will return an array with the errors for the request (as defined by the response generated by the request).
  • Using getMessage() will provide the message passed along to the response.
  • Using getStatusCode() will return the HTTP status code returned by the internal request.

Below is an example of how these functions can be used:

try
{
    $result = API::get('v1/foo');
}
catch (Cartalyst\Api\Http\ApiHttpException $e)
{
    // When something went wrong on the server end,
    // let's abort the application.
    if ($e->isServerError())
    {
        App::abort($e->getStatusCode());
    }

    // Else if the client did something wrong, redirect back to
    // our previous screen with the errors and message that the
    // response returned.
    elseif ($e->isClientError())
    {
        return Redirect::to('bar')
            ->withErrors($e->getErrors())
            ->with('message', $e->getMessage());
    }
}

You wont find fancy lifestyle graphics and marketing bravado here. Just cold... hard... code...

Code Well, Rock On!
Processing Payment...