Il terzo passo per implementare un server REST utilizzando lo stack LAMP (Linux Apache MySQL PHP) è quello di creare il codice PHP.
Dobbiamo creare una classe astratta il cui compito principale sarà quello di mappare i metodi della classe concreta con gli URL delle nostre API. In pratica se abbiamo un URL come
http://api.test/api/auth, la classe concreta dovrà avere un metodo pubblico chiamato auth()
:
<?php
abstract class API
{
protected $_method = '';
protected $_endpoint = '';
protected $_verb = '';
protected $_args = array();
protected $_file = null;
public function __construct()
{
$this->_args = explode('/', rtrim($_REQUEST['request'], '/'));
$this->_endpoint = array_shift($this->_args);
if (array_key_exists(0, $this->_args) && !is_numeric($this->_args[0])) {
$this->_verb = array_shift($this->_args);
}
$this->_method = $_SERVER['REQUEST_METHOD'];
switch($this->_method) {
case 'DELETE':
case 'POST':
$this->request = $this->_cleanInputs($_POST);
break;
case 'GET':
$this->request = $this->_cleanInputs($_GET);
break;
case 'PUT':
$this->request = $this->_cleanInputs($_GET);
$this->_file = file_get_contents('php://input');
break;
default:
$this->_response('Invalid Method', 405);
break;
}
}
public function processAPI()
{
if (method_exists($this, $this->_endpoint)) {
return $this->_response($this->{$this->_endpoint}($this->_args));
}
return $this->_response("No Endpoint: $this->_endpoint", 404);
}
protected function _sendHeaders()
{
header('Access-Control-Allow-Methods: *');
}
protected function _response($data, $status = 200)
{
$output = array();
$stat = (string) $status;
$output[$stat] = $data;
return json_encode($output);
}
private function _cleanInputs($data)
{
$cleanInput = array();
if (is_array($data)) {
foreach ($data as $k => $v) {
$cleanIinput[$k] = $this->_cleanInputs($v);
}
} else {
$cleanIinput = trim(strip_tags($data));
}
return $cleanInput;
}
private function _requestStatus($code)
{
$status = array(
200 => 'OK',
404 => 'Not Found',
405 => 'Method Not Allowed',
500 => 'Internal Server Error',
);
return ($status[$code]) ? $status[$code] : $status[500];
}
}
Ecco un esempio di classe concreta:
<?php
require_once('API.php');
class Test extends API
{
public function __construct()
{
parent::__construct();
}
public function auth()
// http://api.test/api/auth
{
// Accettiamo solo richieste POST
if($this->_method == 'POST') {
$username = trim($_REQUEST['username']);
$password = base64_decode(trim($_REQUEST['password']));
$output = array();
// Se l'autenticazione ha successo
$output['authenticated'] = '1';
echo json_encode($output);
} else {
echo $this->_response('Invalid Method', 405);
}
}
}
Infine nel nostro file index.php avremo:
<?php
header('Content-Type: application/json');
require_once('Test.php');
$test = new Test();
$test->processAPI();