About


Define some endpoints and get your app running!

Version: 1.0.1

Author: Andrés Zorro <zorrodg@gmail.com>

GitHub: http://github.com/zorrodg/php_apihandler

Due to web technologies in constant change, and the growing popular use of Front End technologies such as Backbone, Ember and AngujarJS, the need for server side MVC frameworks that render HTML templates has become increasingly obsolete, and API endpoints to get data from has become a major need.

Just to think about installing CodeIgniter, Laravel, even Slim to deal with simple database calls and no HTML display, made me think about a better solution. I know that there are services that deal with APIs, but my needs (and for many other developers I suppouse) require full control over the data I am sending and storing. That's why I developed PHP API Handler.

The idea behind API Handler is to make it simple to develop API endpoints throught PHP. You define some Getters, Posters, Deleters and that's it. API Handler does all the heavylifting (Database queries, identify resources, encode to json or xml and output).

Currently API Handler works with MySQL and outputs to JSON and XML formats. It's intended to support more database engines and more output formats. Coming soon...

 

There's still a lot to do!


If you want to help developing this code, there's a lot of room for improvement. Just make a pull request and work on one of the following items:

  • Improve API security overall
  • Add support for OAuth 2.0 server authentication
  • Add support for other Database Engines. Currently supporting MySQL only :(
  • Add support for other Outputs. Currently supporting JSON and XML

Enjoy!


If you want to thank me, I won't mind accepting a beer. :)

Getting Started

Follow this guide to get your API up and running.


Installation

In five simple steps.


  1. Download

    Download PHP API Handler or clone it from GitHub repo. http://github.com/zorrodg/php_apihandler

  2. Composer
    Install dependencies

    For OAuth 1.0a signature server support to work, PHP API Handler uses oauth-php library from Marc Worrell. http://github.com/zorrodg/php_apihandler.

    You can automatically install all dependencies using Composer.

    Go to the api folder in Terminal and run:

    composer update

    new Bash Update

    If you're a bash user (unix shell), you can download this shell file to the root of your composer project and after composer update run the update automation process:

    bash apiupdate.sh -d /path/to/your/api/

  3. Move to your server

    Move api folder to where you want your API to be.

    Make sure the server you use support PHP 5.4> and Apache mod_rewrite is enabled. Also check that you give 0777 (full access) permissions to api/cache folder, for PHP API Handler to create cache files.

  4. Configure API Handler

    Locate apihandler/api/api.config.php and modify your configuration for your server:

    DB Configuration:
    Define your database name, database username and password, database table prefix (optional) and hostname.
    Database Engine:
    Currently suporting mysql. Other engines coming soon.
    Cache:
    Set to TRUE in order to cache API calls. When TRUE, default GET calls are cached and POST and DELETE calls are not. You can configure each call separatedely. Also define the name of the folder that will store your cached files, and the time in seconds that the cached file will be valid (default 60s).
    Output:
    json and xml supported. Other outputs coming soon.
    Security:
    Set to oauth1.0a to use OAuth 1.0a security for your endpoints. Default GET calls are unsecured and POST and DELETE calls are secured.
    Environment:
    Set error display for API calls: (dev, stage or prod).
  5. Test installation:

    Go to your API installation URL. If everything went right, you should see a message encoded in your default output with this message:

    No endpoint.

Setup

Now that you have your API up, it's time to make some endpoints.


  1. Locate

    Locate apihandler/api/registered_endpoints/ folder inside your API directory.

    There's an example file called myAPI.endpoints.php that you can use for reference. Every file named with this convention will be added to API Handler: YOUR_FILE_NAME.endpoints.php

  2. Declare

    Create your first API endpoint. It's as easy as declaring a new class:

    new Getter("users");

    There are three classes that you can declare, each corresponds to its HTTP counterpart:

    new Getter()
    -> Declares a new GET endpoint.
    new Poster()
    -> Declares a new POST endpoint.
    new Deleter()
    -> Declares a new DELETE endpoint.

    The first parameter that class accept is the endpoint name. Endpoint name has a special notation, passed as a string, as follows:

    {name}/{verb}/{arg_name}

    name
    Required
    -> The endpoint name. It refers to the database table name from which data will be retrieved.
    verb
    Optional
    -> The action that will be performed to the database. *
    arg_name
    Optional
    -> Can be one or several arguments separated by slashes "/". If preceded by a colon ":", indicates that the argument is a variable

    * - PHP API Handler is designed to "guess" action to be made on database based on common used verbs. i.e: users/create, "create" verb will be translated as INSERT in a MySQL statement. Of course, there will be verbs that are not included on the list. If you need a verb to be added, please let me know. ;)

  3. Specify

    You can pass options to your endpoint, in form of an array:

    new Getter("users/:id", array(
    												"description" => "Get users by id.",
    												"show" => array("first_name", "last_name"),
    												"cacheable" => TRUE
    ));

    Full options documentation is available here.

  4. Secure

    There's a third parameter that you can pass to your API endpoint and it refers to security. You can control for each endpoint if you grant public access to it or user will need to authenticate in order to access data.

    new Poster("users/create", array(<options here>), TRUE);

    GET endpoints are by default unsecured (FALSE) while POST and DELETE endpoints are secured (TRUE).

Test

Time to test if everything went right.


When you finish your endpoint setup, you can test if everything went right by any of these methods:

  1. Going directly to your API endpoint URL, typed in this format:

    http://{YOUR_API_LOCATION}/{YOUR_ENDPOINT_NAME}.{YOUR_FORMAT}

    You can specify format in YOUR_FORMAT part, regardless of the default format you specified in config.

    i.e.: http://localhost/apihandler/api/users.json

  2. If you use Google Chrome Browser, there's an excellent tool called POSTMAN to test API endpoints. Use the same url notation.

  3. There's an example folder included in the repository, which contains a basic API test tool. It's coded using Abraham Williams' OAuth1 PHP Library, as an example, but you can use any other OAuth1.0a library in your project. Remember to composer update on this folder too, to get latest library.

OAuth reference

Find out more about authentication processes if you are securing your API.


OAuth 1.0a

Authentication process used by sites like Twitter.


PHP API Handler makes use of OAuth 1.0a protocol, and specifically, 3-Legged OAuth process in order to make signed requests. The steps to authenticate your endpoint calls via OAuth 1.0a are the same that are used ins sites like Twitter.

There's an example of the complete OAuth flow in the example folder of this repository.

Each one of PHP API Handler endpoint calls will return URL encoded data.

The flow is as follows:

  1. Register a consumer

    In order for an app to make use of your API, they must be registered consumers, that you authorize. You define how your consumers must access your API (i.e. registering in your site as developers). You must provide a form for developers to register their applications in order to make use of your API.

    PHP API Handler provides an OAuth registry endpoint by default that you can access like this:

    http://{YOUR_API_LOCATION}/oauth/1.0a/register

    This endpoint expects the following POST parameters in order to register a new consumer:

    Parameter Description
    user_id The ID from the user associated to the consumer
    user_name The name from the user associated to the consumer
    user_email The email from the user associated to the consumer
    app_uri The URI from where the developer's app will call your API
    app_callback The URI to where the developer's app will redirect your user to
    api_uri The API URI. You should fill this one out, since the developer will be consulting your own API, and none other.

    This endpoint should return an OAuth Consumer Key and an OAuth Consumer Secret to your developer for them to authenticate their calls.

  2. Request token

    Note: From this point on, developers need to send signed requests to the endpoint in order to work. I recommend using a library for automatic sign requests, (i.e. Abraham Williams' OAuth1 PHP Library). Read more about OAuth signed request here.

    Once a developer is registered in your API as a consumer, he could ask for a request token, to the following endpoint:

    http://{YOUR_API_LOCATION}/oauth/1.0a/request

    This endpoint must be signed using OAuth Consumer Key and OAuth Consumer Secret obtained from App registration. This endpoint should return temporary credentials, in form of Request Token and Request Token Secret

  3. Authorization from user

    Developer should drive users to an authorization window where logged in users authorize application to make use of your API. The user must be presented the choice to decline authorization. From this window, developer should send a signed request to this endpoint:

    http://{YOUR_API_LOCATION}/oauth/1.0a/authorize

    This endpoint expects the following REQUEST parameters in order to return data:

    Parameter Description
    user_id The ID from the user who authorizes data usage
    user_approve Response from user, whether he authorizes the developer's app or not

    This endpoint must be signed using OAuth Consumer Key and OAuth Consumer Secret obtained from App registration. This endpoint should return to the defined App Callback with an OAuth Verifier query parameter that will be used on the next step.

  4. Exchange Request Token for an Access Token

    Once developer has obtained Request Token, Request Token Secret and OAuth Verifier, he must exchange this token for an Access Token that will be needed to make signed request to your API endpoints.

    Developer should send a signed request with OAuth Consumer Key, OAuth Consumer Secret, Request Token, Request Token Secret and OAuth Verifier to this endpoint:

    http://{YOUR_API_LOCATION}/oauth/1.0a/access

    This endpoint should return an Access token and an Access Token Secret that in combination with OAuth Consumer Key and OAuth Consumer Secret are needed in order to make signed queries to your API.

 

Making a signed request


If one of your API endpoints is signed, developer should sign his call with Access Token, Access Token Secret, OAuth Consumer Key and OAuth Consumer Secret, obtained from previous flow, in order to successfully fetch your API data.

OAuth 2.0


Coming soon...

Options Reference

Here's a list of all options that could be set to each endpoint, with explained examples.


This options refer to the array of options that could be passed to each defined endpoint. Here's an example on where this options should be:

new Getter("users", array(<options here>), TRUE);


new!
after (function)

Set a custom callback fuction that executes after data retrieval. It has one parameter that is data retrieved (response).

Example:
"after" => function($response){
		foreach($response as $key => $val){
			//.. Do something with the response
		}
	}

new!
before (function)

Set a custom callback fuction that executes before query fetch. It has one parameter that is query string to be send.

Example:
"before" => function($query){
		//.. Do something with the query string
	}

cacheable (bool)

Set whether the endpoint results will be cached or not. Default FALSE.

Example:
"cacheable" => TRUE

col_prefix (string)

Add a column prefix to the columns. If you define one, instead of looking at col_name column, it will look for {prefix}col_name.

Example:
"col_prefix" => "aph_"

columns (array)

Define table columns in which endpoint operates. This is an array of strings. Each string has an special notation, separated by | (pipe) character.

Depending on the HTTP call, columns will define parameters for your query, i.e. you can call your endpoint with a filter: GET http://{YOUR_ENDPOINT_LOCATION}/users.json?last_name=zorro

Note: If you set create_new_table or modify_existing_table to TRUE, columns will modify database to fit this columns.

Special Notation: {column_name}|{var_type}|{var_length}|{unique}

Parameter Default Value Description
column_name
Required
The name of the column.
var_type "string" Database column data type. Values supported int (INT), char (CHAR), string (VARCHAR), text (TEXT), bigint (BIGINT), date, (DATETIME)
var_length "200" The length of the data accepted. (Only for int, char, bigint and string)
unique "" Set column key to unique.

Example:
"columns" => array(
	"first_name|string|200|unique", 
	"last_name|string|200", 
	"group_id|int"
)

create_new_table (bool)

Creates a new table in database with given endpoint name, if not exists. This option will not create a table if it exists.

Note: If you set create_new_table or modify_existing_table to TRUE, PHP API Handler automatically will create two aditional columns without prefix called id (int) and updated (timestamp).

Example:
"create_new_table" => TRUE

description (string)

Endpoint description. Not really useful, in fact. But it could become handy whenever you want to make your API documentation ;)

Example:
"description" => "Get all users."

join (assoc array)

Set the columns from other tables that will be joined to current query. This associative array has an special notation, with key name and string value, separated by | (pipe) character.

join option will override result from the first query with the result of the second query, returning a complex object.

You can join as many tables as you want, as long as there are columns in common with your current query.

Special Notation: {key} => {first_col}|{second_col}|{cols_to_fetch}

Parameter Default Value Description
key
Required
The name of the table that will be joined.
first_col
Required
Column from the first table (primary table, if you wish) that will be associated.
second_col
Required
Column from the second table that will be associated. The values fomr the first and the second must match.
cols_to_fetch FALSE Columns that will be fetched from the second table, separated by ,. If you don't assign it, It will fetch all columns from second table (similar to show option)

Example:
"join" => array("groups" => "group_id|id",
		"teams" => "team_id|id|team_name,team_desc"
		)

limit (string)

Set a word to use as a parameter on query string to limit results number. i.e. if you set it to count, you could call an endpoint like this: http://{YOUR_ENDPOINT_LOCATION}/users.json?count=5.

Example:
"limit" => "count"

modify_existing_table (bool)

Modifies an existing table, if exists and if it's params change. This option will modify table, if you change table names, change column names, data type or data length. If left TRUE, it will not modify existing tables if there are no changes.

Note: If you set create_new_table or modify_existing_table to TRUE, PHP API Handler automatically will create two aditional columns without prefix called id (int) and updated (timestamp).

Example:
"modify_existing_table" => TRUE

query (string)

Set a custom query to the database. If set, custom query is used instead of the one API Handler creates.

About kvsprintf: PHP API Handler uses a modified version of vsprintf() PHP native function, that supports associative arrays. It uses a special notation for identifying array keys and values: %{array_key_name}\$k and %{array_key_name}\$v replacing {array_key_name} for coresponding array key name.

When set, query must include table prefixes in order to work. If endpoint has variable arguments, column names must be included manually and with column prefixes.

Example 1: Endpoint -> users
"query" => "SELECT * FROM `api_users` WHERE `%first_name\$k` = '%first_name\$v'"
Example 2: Endpoint -> users/:first_name
"query" => "SELECT * FROM `api_users` WHERE `aph_first_name` = '%first_name\$v'"

Notice on Example 2 column prefix aph_ is included for it to work.


show (array)

Set the columns that will be displayed. Columns not listed will be hidden. If this option is not set, PHP API Handler will bring data from all columns.

Note: If you set create_new_table or modify_existing_table to TRUE, PHP API Handler automatically will create two aditional columns without prefix called id (int) and updated (timestamp). You can show them also.

Example:
"show" => array("first_name", "last_name")

sort (string)

Sets the column to order the results. This string has an special notation, separated by | (pipe) character. Default order is id column.

Special Notation: {column_name}|{order_type}

Parameter Default Value Description
column_name
Required
The name of the column.
var_type "desc" The order to display. Supported values asc (ASC), desc (DESC)

Example:
"sort" => "first_name|asc"

new!
table_alias (string)

Set an alias name for your endpoint. table_alias will hold your table name, while it is aliased on the endpoint.

Example:

Given this endpoint: people.json it will search for users table instead of people table, if option set.

"table_alias" => "users"

Changelog

What's new on PHP API Handler!


Version 1.0.1

Minor fixes. Three new features:

  • Fixed html recursive encode/decode function bug throwing warnings on null data.
  • Added table_alias option, to hide table names from endpoints.
  • Added before and after options. Use them as callbacks before query sent and after data retrieval.

Version 1.0.0

Initial release. It has several features:

  • Define Getter, Poster and Deleter classes to create API endpoints
  • Support for JSON and XML output formats
  • Support for MySQL database engine
  • Support for OAuth 1.0a signed calls (Using mworrell-oauth-php)
  • Predefined OAuth flow endpoints to authorize applications
  • Support for custom database query strings, to handle personalized data handling
  • Support for join replace queries, relationship between tables with fields in common
  • JSON Test application example provided, to test API endpoints

Licence

PHP API Handler is licenced under MIT Licence:


The MIT License (MIT)

Copyright © 2014 zorrodg

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.