Skip to content

Instantly share code, notes, and snippets.

@Nub
Created September 29, 2011 04:28
Show Gist options
  • Select an option

  • Save Nub/1249980 to your computer and use it in GitHub Desktop.

Select an option

Save Nub/1249980 to your computer and use it in GitHub Desktop.
RESTfulish PHP framework
<IfModule mod_rewrite.c>
RewriteEngine On
#for arguments
RewriteRule ^([^/]*)/([^/]*)/([^/]*)$ ZTAPI.php?APIKey=$1&Action=$2&Args=$3 [L]
#for no arguments
RewriteRule ^([^/]*)/([^/]*)$ ZTAPI.php?APIKey=$1&Action=$2 [L]
</IfModule>
<?php
/*
ZTAPI by Zachry Buddy Thayer
A RESTfulish framework
Version 1.0
License: CC BY-SA (Crreative Commons Share Alike)
API GET URL style
Best used with an api subdomain.
http://api.domain.com/APIKey/methodName[/Argument=value;Argument2=value2]
*/
class ZTAPI{
private $methods = array();
private $data = "";
private $apiCall = "";
const APIKEY_KEY = "APIKey";
const METHOD_KEY = "Action";
const DATA_KEY = "Data";
const GET_ARGS_KEY = "Args";
const GET_ARGS_DELIMITER_TOKEN = ";";
const GET_ARGS_ASSIGN_TOKEN = "=";
const ERROR_INVALID_APIKEY = "INVALID_APIKEY";
const ERROR_METHOD_NOT_FOUND = "METHOD_NOT_FOUND";
const ERROR_INVALID_DATA = "INVALID_DATA";
const ERROR_DATA_NOT_FOUND = "DATA_NOT_FOUND";
const ERROR_JSON_ENCODE_FAILED = "JSON_ENCODE_FAILED";
const ERROR_JSON_DECODE_FAILED = "JSON_DECODE_FAILED";
const ERROR_BAD_API_CALL = "BAD_API_CALL";
const ERROR_API_CALL_FAILED = "API_CALL_FAILED";
/*
Append method to array of methods
*/
function addMethod(&$method){
$this->methods[$method->name()] = $method;
}
/*
Checks APIKey returns BOOLEAN
*/
function validAPIKey(){
$APIKey = $this->apiCall[ZTAPI::APIKEY_KEY];
//INSERT VALIDATION CODE
return TRUE;
}
function throwError($error){
$errorObject = Array(
'Error'=>$error,
'APICall'=>$this->apiCall
);
$errorJSON = json_encode($errorObject);
if(!isset($errorJSON)){
die('{"Error":"JSON_ENCODING_FAILED_IN_ERROR_THROW", "APICall":""}');
}
die($errorJSON);
}
private function prepareData(){
if(count($_POST) > 0){
$HTTPBody = @file_get_contents('php://input');
if(!isset($HTTPBody))
$this->throwError(ZTAPI::ERROR_BAD_API_CALL);
$this->apiCall = json_decode($this->apiCall);
if(!isset($this->apiCall))
$this->throwError(ZTAPI::ERROR_JSON_DECODE_FAILED);
}else if(count($_GET) > 0){
//Bust open the arguments
$arguments = split(ZTAPI::GET_ARGS_DELIMITER_TOKEN, $_GET[ZTAPI::GET_ARGS_KEY]);
$data = Array();
if(strlen($arguments[0]))//If we have arguments parse them
foreach($arguments as $i => $value){
$argumentSplit = split(ZTAPI::GET_ARGS_ASSIGN_TOKEN, $value);
$data[$argumentSplit[0]] = $argumentSplit[1];
}
else
$data = null;
print_r($data);
$this->apiCall = Array(
ZTAPI::METHOD_KEY => $_GET[ZTAPI::METHOD_KEY],
ZTAPI::APIKEY_KEY => $_GET[ZTAPI::APIKEY_KEY],
ZTAPI::DATA_KEY => $data,
);
}
}
function run(){
$this->prepareData();
if(!$this->validAPIKey()){
$this->throwError(ZTAPI::ERROR_INVALID_APIKEY);
}
$method = $this->apiCall[ZTAPI::METHOD_KEY];
if(!isset($this->methods[$method]))
$this->throwError(ZTAPI::ERROR_METHOD_NOT_FOUND);
$data = $this->apiCall[ZTAPI::DATA_KEY];
if($this->methods[$method]->requiresData())
if(!isset($data) || empty($data))
$this->throwError(ZTAPI::ERROR_DATA_NOT_FOUND);
// Run API method call
$output = $this->methods[$method]->invoke($data);
if(!isset($output))
$this->throwError(ZTAPI::ERROR_API_CALL_FAILED);
$JSONOutput = json_encode($output);
if(!isset($JSONOutput))
$this->throwError(ZTAPI::ERROR_JSON_ENCODE_FAILED);
print($JSONOutput);
}
}
/*
Class template for implementing RESTfulish API methods
Simply extend this class and fill out __construct to set name and version, and invoke and requiresData to do your bidding
*/
abstract class ZTAPIMethod{
/*
Used to Give the Method its name, and its version
*/
abstract public function __construct();
/*
Method to be called when API needs it
$data: should be a data array/keypair refrence (ZTAPI::DATA_KEY object is passed)
Returns: array/keypair object to be json_encoded
*/
abstract public function invoke($data);
/*
Specifies wether the method requires data or not
Returns: BOOLEAN
*/
abstract public function requiresData();
/*
Method Name
/api/methodName/
*/
protected $_name;
/*
Fetch name
*/
function name(){
return $this->_name;
}
//Below is optional, just extraneous information, but could be useful on large projects
/*
String version of plugin
*/
protected $_version;
/*
Fetch version
*/
function version(){
return $this->_version;
}
function __toString(){
return "Method: ".$this->_name." Version: ".$this->_version;
}
}
/*
Example method that lists the args fed to it.
*/
class ZTAPITestMethod extends ZTAPIMethod{
function invoke($data){
if(is_array($data))
foreach($data as $key => $arg){
$ret .= "[".$arg."]";
}
else
return "TestForNoDataPassed";
return $ret;
}
function requiresData(){
return FALSE;
}
public function __construct(){
$this->_name = "ZTAPITestMethod";
$this->_version = "1.0";
}
}
//Example use
$testMethod = new ZTAPITestMethod();
$myAPI = new ZTAPI();
//Register API methods
$myAPI->addMethod($testMethod);
$myAPI->run();
?>
@Nub
Copy link
Author

Nub commented Sep 29, 2011

and put this in the .htaccess for URL rewriting

<IfModule mod_rewrite.c>

RewriteEngine On

RewriteRule ^([^/])/([^/])/([^/]*)$ ZTAPI.php?APIKey=$1&Action=$2&Args=$3 [L]

</IfModule>

@GeForce
Copy link

GeForce commented Sep 29, 2011

You sir, are a fucking genius. Thanks so much

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment