Part 1 of a three-part series to help you learn RESTful web services using PHP. These tutorials will be comprehensive, by following them through you can build your own web services easily and consume external services.
In this tutorial, we will see how to create a PHP RESTful web service without using any framework. Most of the time I do prefer to write custom code without depending on frameworks since this approach has a lot of advantages. Mainly, this will take you deeper in learning the concepts and you can keep things sleek and effective.
REST or Representational State Transfer is one of the popular architectural styles used to develop web services. This style of architecture contains constraints or rules to design web services that can be accessed from external apps or web applications.
The objective is to build a RESTful web service in PHP to provide resource data based on the request with the network call by the external clients. Also, the following list of steps is implemented while customizing this example without depending on any framework.
An array of mobile brand names are the resource data that will be targeted by the REST clients. I have this resource in a domain class of this PHP RESTful example.
For accessing these data via this web service, the client will send the request by setting URI, parameters with the selected method, and more information.
The resource handlers of the web service will prepare the response in JSON, XML or HTML format based on the request. Then, the response will be sent to the client.
On the Internet, I have seen web services tutorials and most of the time they all turn out to be error-prone or incomplete. I tested those RESTful services using a REST client and mostly they fail.
REST stands for Representational State Transfer and it is an architectural style that enables the communication between systems. The term REST was first coined by Roy T. Fielding in his PhD. dissertation.
The concept of REST is defined by certain rules, constraints or principles. The system, application, services or whatever satisfies these REST principles are called RESTful.
Web services that follow the RESTful principles are RESTful services. The URI is used to access RESTful services to get the resources.
In the RESTful glossary, the resources are nothing but the data and functions. So eventually we will call the web services via URI to access functions and thereby get the resource data.
The following constraints define the RESTfulness of an application or service.
The following table shows the comparison of RESTful and RPC-style web services. This comparison is made by factors like service request URI, request methods, data transmission, service handlers and more.
RESTful-Style | RPC-Style | |
---|---|---|
Request URI | The request URI will differ based on the resource. | Same URI for all resources. |
Request methods | The service request parameters can be sent via GET, PUT, and POST request methods. | Supports only the POST method. |
Service methods or handlers | Same method for all resources. | Methods and parameters are posted on request. |
Target on | The service request using this style targets resources. | The target is methods. |
Response data transmission | Over HTTP | wrapped with the requested methods and parameters. |
The following diagram shows a RESTful web service architecture. In this diagram, the request-response flow among the client-server is represented.
In this diagram, the database is shown as a resource. Based on the web service the resource can be XML feed, JSON data extracted from the file system or any.
RESTful API provides services to access resources from external applications or REST clients. Some of the predominant uses of the RESTful API are listed below.
In the PHP RESTful web service example, the following domain class contains the resource data array and service handlers. These handlers are called based on the request sent by the REST client or external apps.
In the next section, we can see all the file structures and the purpose of each file of this example.
<?php
/*
* A domain Class to demonstrate RESTful web services
*/
class Mobile
{
private $mobiles = array(
1 => 'Apple iPhone 6S',
2 => 'Samsung Galaxy S6',
3 => 'Apple iPhone 6S Plus',
4 => 'LG G4',
5 => 'Samsung Galaxy S6 edge',
6 => 'OnePlus 2'
);
/*
* you should hookup the DAO here
*/
public function getAllMobile()
{
return $this->mobiles;
}
public function getMobile($id)
{
$mobile = array(
$id => ($this->mobiles[$id]) ? $this->mobiles[$id] : $this->mobiles[1]
);
return $mobile;
}
}
?>
The below file structure shows the simplicity of creating a RESTful web service example.
As discussed above Mobile.php is the domain class which is having resource array and handlers to get the resource.
The .htaccess file is used for mapping the request URI to the REST service endpoint.
In the following sections, we will see how the URI is mapped, and how the service handler is invoked to get resource data from the domain. – URI RFC 3986
Every resource is identified via a URI (Uniform Resource Identifier).
A Uniform Resource Identifier (URI) is a compact sequence of characters that identifies an abstract or physical resource.
RestController.php shown in the above file structure is the PHP endpoint to which the request is to be forwarded.
I provide two URIs for accessing this web service from external applications or REST clients in this example. One URI will be used to get the complete array of mobile names in a JSON format and the other is to get a particular mobile name based on the ident passed via the request URI.
URI | Method | Type | Description |
---|---|---|---|
http://localhost/restexample/mobile/list/ | GET | JSON | To get the list of mobile brand names in a JSON array. |
http://localhost/restexample/mobile/list/{id}/ | GET | JSON | To get a single mobile data array by ident passed via URL. |
The following URIs are mapped to the real file via the .htaccess file.
URI to get the list of all mobiles:
http://localhost/restexample/mobile/list/
URI to get a particular mobile’s detail using its id:
In the below URI the number ‘2’ is the id of a mobile. The resource domain class can get the particular data with the reference of this id parameter.
http://localhost/restexample/mobile/list/2/
The below code, snippet shows the complete rules and URL mappings created for this PHP RESTful web service example in its .htaccess
file.
# Turn rewrite engine on
Options +FollowSymlinks
RewriteEngine on
# map neat URL to internal URL
RewriteRule ^mobile/list/$ RestController.php?view=all [nc,qsa]
RewriteRule ^mobile/list/([0-9]+)/$ RestController.php?view=single&id=$1 [nc,qsa]
In the.htaccess
file, we are forwarding all the requests to the RestController.php file.
While forwarding the request the parameters are sent to execute a required part of the REST controller. This parameter is the key named ‘view’.
The value of the key parameter can be either “all” or “single” based on the request URI.
Following is the RestController.php file that receives the request and gets the view parameter. Based on this parameter value, the appropriate control case will be executed.
In the controller cases, the request is dispatched to respective methods created in the REST handler class.
<?php
require_once ("MobileRestHandler.php");
$view = "";
if (isset($_GET["view"]))
$view = $_GET["view"];
/*
* controls the RESTful services
* URL mapping
*/
switch ($view) {
case "all":
// to handle REST Url /mobile/list/
$mobileRestHandler = new MobileRestHandler();
$mobileRestHandler->getAllMobiles();
break;
case "single":
// to handle REST Url /mobile/show/<id>/
$mobileRestHandler = new MobileRestHandler();
$mobileRestHandler->getMobile($_GET["id"]);
break;
case "":
// 404 - not found;
break;
}
?>
The following class has a couple of methods that can be commonly used for the RESTful service handlers.
The getHttpStatusMessage() method is used to get the HTTP status message to construct the response. It contains the HTTP status code and message mapping array.
By receiving the status code, it returns the appropriate header response message. If the invalid status code is passed to this function or no such code is found in the mapping array, then the “Invalid Server Error” will be returned in the response.
These methods can be commonly used in the base class of simple PHP RESTful web services.
<?php
/*
* A simple RESTful web service base class
* Use this as a template and build upon it
*/
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] : $httpStatus[500];
}
}
?>
This is the service class of this PHP example that handles the REST request dispatched from the controller.
First, we have to decide about the response format in which the resource data has to be prepared. It is based on the request header parameters.
In the request header, the “Accept” parameter will have the specification about the response content format or type.
The protocol here is, that when the request is sent, it should set the Request header parameter “Accept” and send it. The values can be like “application/json” or “application/xml” or “text/html”.
Based on these values the response data will be ready by invoking appropriate methods encodeJson(), encodeXML(), encodeHTML() shown below.
Then, the status code has to be returned to the client with the response data. On success, the status code will be 200.
Similarly, there are different status codes available and they should be used accordingly to set the response header as we discussed in the above section.
<?php
require_once ("SimpleRest.php");
require_once ("Mobile.php");
class MobileRestHandler extends SimpleRest
{
function getAllMobiles()
{
$mobile = new Mobile();
$rawData = $mobile->getAllMobile();
if (empty($rawData)) {
$statusCode = 404;
$rawData = array(
'error' => 'No mobiles 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)
{
// creating object of SimpleXMLElement
$xml = new SimpleXMLElement('<?xml version="1.0"?><mobile></mobile>');
foreach ($responseData as $key => $value) {
$xml->addChild($key, $value);
}
return $xml->asXML();
}
public function getMobile($id)
{
$mobile = new Mobile();
$rawData = $mobile->getMobile($id);
if (empty($rawData)) {
$statusCode = 404;
$rawData = array(
'error' => 'No mobiles 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;
}
}
}
?>
There are various stand-alone REST clients available in the market. These client interfaces are used to test a RESTful web service.
The Advanced Rest Client extension can be added to the Chrome installed on your machine.
We can also write our own custom client to test a RESTful web service.
I used this Google Chrome extension REST client for testing this PHP RESTful web service example.
The below screenshot shows how to call RESTful web service. In this screenshot, the circled sections highlight the request URI, the selected request method, Header’s Accept param, and more details.
By clicking the send button, the response will be returned from the PHP RESTful web service.
XML Response
I set the application/xml as the response type. So the resultant resource data is prepared in the requested format as shown in the response section of the below screenshot.
PHP RESTful web service JSON response
In this three-part tutorial series on RESTful web services using PHP, you will learn the RESTful implementation in detail using this comprehensive material. This first part has given you a complete introduction to the concepts with step-by-step examples.
With the knowledge that you have acquired from this tutorial, about the rules and principles of RESTfulness, you can build a RESTful API easily. Though there are frameworks for developing RESTful API, it can be done by using plain core PHP which will be effective and provide good performance.
In the coming part, you will be seeing about all aspects of developing a CRUD RESTful web services API using PHP for an entity.
Very good example.
Thank you Emanuele.
iTS BEAUTIFUL EXAMPLE, THANKS
Welcome Jonathan.
Hi
it was good
thank you
Welcome Mahmoud.
Thank you but where are the part 2 and 3 ?
Welcome Claude. It will be updated in a month.
Ohh I hope it will come soon :) Thanks for the first part!
thank you. ms. vincy your blog is very nice and with very simple example which help me in most of the project. after learning basic from here I am easily able to apply on my required logic… thank you once again.
Welcome, Rajendra for the nice words. It made my day! Thank you.
Hello Vincy, thank you for your tutorial, I think it’s a fantastic material. I look forward to seeing the other two parts.
A greeting from Spain ;)
Hey Anarbona, thank you so much. I will get the other two parts soon.
Very easy and understandable example .. Thanks a lot
Welcome, Anuj.
Hi Vincy
Thank you for your awesome tutorial.. It is so helpful..
I changed some lines;
MobileRestHandler.php:30
added else{}
SimpleRest.php:61
return ($httpStatus[$statusCode]) ? $httpStatus[$statusCode] : $httpStatus[500];
Welcome, Huseyin. Thanks for sharing the updated code snippet.
Thank you so much for adding value. When you do such things, the Internet becomes a beautiful place. Thank you for your time.
Example was good. But still where are the next tutorial. I have been eagerly waiting !!
Thanks Rakesh. Coming soon!
Very well explained. But you missed out in the SQL for creating the tbl_mobile table. Please include it for the readers and learners.
Thank you Nadeem, sure I will update the article with that.
This is a helpful tutorial. Thank-you for creating and sharing it.
A slight modification to the rewrite rules in the .htaccess file will allow the trailing forward slash to be optional when the user enters a URL in the browser. When I first tested out this example I put http:/localhost/restexample/mobile/list into the browser’s address bar. This returned a 404 error. Initially I thought my Apache configuration was not set up correctly to allow overrides by .htaccess but that was not the case. The problem was that I hadn’t put a trailing forward slash at the end of the URL and the original rewrite rules were written such that the trailing forward slash was mandatory.
Here is how I modified the rewrite rules to make the trailing forward slash optional:
RewriteRule ^mobile/list/?$ RestController.php?view=all [nc,qsa]
RewriteRule ^mobile/show/([0-9]+)/?$ RestController.php?view=single&id=$1 [nc,qsa]
Hi Heather,
Thank you for the updated code. Appreciate it. Thank you so much for adding value to the article and discussion.
Hi Heather,
thank you for your comment. I’m searching several hours for the problem.
greets
Demiurge
Described very well, Never found article about REST before.
Thank you Jignesh.
Wow! Excellent work Ms. Vincy… Since the time i came across your succinct tutorial, i completely feel at rest! I am following your great work here with great desire and i found it very helpful. Your assistance is greatly appreciated and very commendable!!! Keep it up
Thank you Abdul.
good
Thank you Dixit.
Very good approach!!!
It would be very useful if an example with POST could be given.
Great job.
Thank you Konstantinos. Sure I will add it soon.
Thank you for sharing your knowledge.
Greetings from Guatemala!
Welcome Edgar.
Really useful example – has really help speed up my learning
Thank you
Welcome Milan.
Hi Vinci, thank you very much for your example. It’s a excellent start for my project :)
Welcome Juan.
Hey, I’ve just got back into development after a long break, some of the concepts I’m finding have a very steep learning curve.
You have at least made this one simple for me.
I’m guessing you have finished the parts of the tutorial, can you email me some links
Thank you Roy. I will post them here.
Thank you Vincy. It was so helpful.
Welcome Qasem.
Very good tutorial. Thank you.
Thank you Amnat.
Awesome article.. just copy pasted its working great. Thanks.
Welcome Bhaskar.
Such a blessing from tutorial from you… Live long helping amateurs
Thank you Amos.
Just amazing. I was building similar kinds of stuff, and I found the solution in .htaccess file
Thanks a lot :)
Welcome Pankaj.
Perfect you saved a lot of my time. i appreciate your efforts. Image passing with rest post request will be more help…
Welcome Muhammad.
Sure I will write a separate article with image passing in REST.
Thank you Vincy.
Welcome UA :-)
Hello Vince, It’s a awesome tutorial, explained very clearly and easy to understand.
I wanted to implement it for external application, but how to overcome cross domain access authentication and issues?
Thank you Sowjanya.
Cross domain authentication is a topic by itself. I will try to write an article on it soon.
I found this really useful and built a working POC for a project.
Thank you Ken.
You give code but you don’t give the name of the files. Please add the name of the files for each code piece.
Sure Joe noted.
The complete code is available in the download as a zip. I would recommend you to use that.
Hi, Cant get a valid response. Header response returns as undefined.
Hi Matt,
Can you post the complete trace?
Great article but a question:
Under the sample code for “A simple RESTful base class”, should:
return ($httpStatus[$statusCode]) ? $httpStatus[$statusCode] : $status[500];
be:
return ($httpStatus[$statusCode]) ? $httpStatus[$statusCode] : $httpStatus[500];
Thanks, just what I was looking for!
Thank you Jim. Now I have updated the code.
Hi Vincy. It seems everyone who posts an article about creating REST Web Services always employs other technology to get the project started. Bootstrap, Eclipse, Java… It really takes away from understanding the underlying REST nuts and bolts.
I love your article because it explains the basis of it all from the ground up. No special glue. Just the developer and a text editor. Wonderful!!
It’s now 2022 and I don’t see links to the subsequent articles. Are they available somewhere?
Thank you Vince. Yet to post the other parts :-(