PHP RESTful
REST (Representational State Transfer) refers to a set of architectural constraints and principles.
A Web API that conforms to the REST architectural style is called a RESTful API. It defines resources in the following three aspects:
Intuitive and short resource addresses: URIs, such as
http://example.com/resources/
.Transmitted resources: Internet media types accepted and returned by the web service, such as JSON, XML, YAML, etc.
Operations on resources: A set of request methods supported by the web service on the resource (e.g., POST, GET, PUT, or DELETE).
In this tutorial, we will create a RESTful web service using PHP (without frameworks). At the end of the article, you can download the code used in this section.
Through this tutorial, you will learn the following:
Creating a RESTful Webservice.
Using native PHP, without relying on any framework.
URI patterns need to follow REST rules.
RESTful service accepts and returns formats such as JSON, XML, etc.
Responding with appropriate HTTP status codes based on different scenarios.
Demonstrating the use of request headers.
Using a REST client to test the RESTful web service.
RESTful Webservice Example
The following code is the RESTful service class Site.php:
Example
<?php
/*
* tutorialpro.org RESTful demo example
* RESTful service class
*/
Class Site {
private $sites = array(
1 => 'TaoBao',
2 => 'Google',
3 => 'tutorialpro',
4 => 'Baidu',
5 => 'Weibo',
6 => 'Sina'
);
public function getAllSite(){
return $this->sites;
}
public function getSite($id){
$site = array($id => ($this->sites[$id]) ? $this->sites[$id] : $this->sites[1]);
return $site;
}
}
?>
RESTful Services URI Mapping
RESTful Services URIs should be set as intuitive and short resource addresses. The Apache server's .htaccess should be configured with the corresponding Rewrite rules.
In this example, we will use two URI rules:
Get all site lists:
http://localhost/restexample/site/list/
Get a specified site using its id, the following URI is for the site with id 3:
http://localhost/restexample/site/list/3/
The project's .htaccess file configuration rules are as follows:
# Enable rewrite functionality
Options +FollowSymlinks
RewriteEngine on
# Rewrite rules
RewriteRule ^site/list/$ RestController.php?view=all [nc,qsa]
RewriteRule ^site/list/([0-9]+)/$ RestController.php?view=single&id=$1 [nc,qsa]
RESTful Web Service Controller
In the .htaccess file, we retrieve the corresponding request in the RestController.php file by setting the 'view' parameter, and dispatch to different methods based on the 'view' parameter. The RestController.php file code is as follows:
Example
<?php
require_once("SiteRestHandler.php");
$view = "";
if(isset($_GET["view"]))
$view = $_GET["view"];
/*
* RESTful service controller
* URL mapping
*/
switch($view){
case "all":
// Handle the request for all sites
break;
case "single":
// Handle the request for a single site
break;
case "":
// No specific view requested
// Handle the default case
break;
}
?>
// Handle REST URL /site/list/
$siteRestHandler = new SiteRestHandler();
$siteRestHandler->getAllSites();
break;
case "single":
// Handle REST URL /site/show/<id>/
$siteRestHandler = new SiteRestHandler();
$siteRestHandler->getSite($_GET["id"]);
break;
case "" :
// 404 - not found;
break;
}
?>
Simple RESTful Base Class
Below is a base class for RESTful services, which handles HTTP status codes for response requests. The SimpleRest.php file code is as follows:
Example
<?php
/*
* A simple RESTful web services base class
* We can extend this class based on our requirements
*/
class SimpleRest {
private $httpVersion = "HTTP/1.1";
public function setHttpHeaders($contentType, $statusCode){
$statusMessage = $this -> getHttpStatusMessage($statusCode);
header($this->httpVersion. " ". $statusCode ." ". $statusMessage);
header("Content-Type:". $contentType);
}
public function getHttpStatusMessage($statusCode){
$httpStatus = array(
100 => 'Continue',
101 => 'Switching Protocols',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
306 => '(Unused)',
307 => 'Temporary Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported');
return ($httpStatus[$statusCode]) ? $httpStatus[$statusCode] : $status[500];
}
}
?>
RESTful Web Service Handler Class
Below is a RESTful Web Service handler class SiteRestHandler.php, which inherits from the RESTful base class we provided above. The class determines the HTTP status code and data format to be returned by checking the request parameters. In this example, we provide three data formats: "application/json", "application/xml", or "text/html":
SiteRestHandler.php file code as follows:
Example
<?php
require_once("SimpleRest.php");
require_once("Site.php");
class SiteRestHandler extends SimpleRest {
function getAllSites() {
$site = new Site();
$rawData = $site->getAllSite();
if(empty($rawData)) {
$statusCode = 404;
$rawData = array('error' => 'No sites found!');
} else {
$statusCode = 200;
}
$requestContentType = $_SERVER['HTTP_ACCEPT'];
$this ->setHttpHeaders($requestContentType, $statusCode);
if(strpos($requestContentType,'application/json') !== false){
$response = $this->encodeJson($rawData);
echo $response;
} else if(strpos($requestContentType,'text/html') !== false){
$response = $this->encodeHtml($rawData);
echo $response;
} else if(strpos($requestContentType,'application/xml') !== false){
$response = $this->encodeXml($rawData);
echo $response;
}
}
public function encodeHtml($responseData) {
$htmlResponse = "<table border='1'>";
foreach($responseData as $key=>$value) {
$htmlResponse .= "<tr><td>". $key. "</td><td>". $value. "</td></tr>";
}
$htmlResponse .= "</table>";
return $htmlResponse;
}
public function encodeJson($responseData) {
$jsonResponse = json_encode($responseData);
return $jsonResponse;
}
public function encodeXml($responseData) {
// Create SimpleXMLElement object
$xml = new SimpleXMLElement('<?xml version="1.0"?><site></site>');
foreach($responseData as $key=>$value) {
$xml->addChild($key, $value);
}
return $xml->asXML();
}
public function getSite($id) {
$site = new Site();
$rawData = $site->getSite($id);
if(empty($rawData)) {
$statusCode = 404;
$rawData = array('error' => 'No sites found!');
} else {
$statusCode = 200;
}
$requestContentType = $_SERVER['HTTP_ACCEPT'];
$this ->setHttpHeaders($requestContentType, $statusCode);
if(strpos($requestContentType,'application/json') !== false){
$response = $this->encodeJson($rawData);
echo $response;
} else if(strpos($requestContentType,'text/html') !== false){
$response = $this->encodeHtml($rawData);
echo $response;
} else if(strpos($requestContentType,'application/xml') !== false){
$response = $this->encodeXml($rawData);
echo $response;
}
}
}
?>
Next, we access it via http://localhost/restexample/site/list/ and the output is as follows:
RESTful Web Service Client
Next, we can use the "Advance Rest Client" in Google Chrome as a RESTful Web Service client to request our service.
In the example, we request the address http://localhost/restexample/site/list/ with the data type Accept: application/json.
To request the site with id 3, tutorialpro(tutorialpro.org), the address is http://localhost/restexample/site/list/3/.
Source Code Download
The code used in the example can be downloaded by clicking the button below: