Create a REST API in PHP
REST APIs are used to exchange data using simple HTTP methods allowing different applications to communicate with each other over internet.

REST APIs are widely used for a stateless communication between client and server or different applications over internet most commonly using HTTP methods. In this post we are going Create a REST API in PHP and demonstrate how it is used to exchange data over internet. We will also use authorization token to authorize all requests.
The files we are going to create for this post are:
- constants.php: Contains the constants for database connection.
- db.php: Serves as a database abstraction layer containing reusable database functions.
- api.php: Contains the code for REST API requests and serves as an API endpoint.
What is a REST API?
REST stands for Representational State Transfer which means how current state or data of a resource is represented. A REST resource can be anything like an employee, a product or a book and the representation of its current state can be JSON or XML. In REST each resource has a different URL. REST is used for a stateless communication which means each request is independent and must contain all required data for server to understand the request. This stateless communication takes place using HTTP methods like (GET, POST, PUT, DELETE).
Where as API stands for Application Programming Interface which is an interface that allows different platforms to communicate. The code snippets provided in this post will help you to implement PHP REST API interface in your application with working demo and source code available for download.
HTTP Methods Used in REST
As mentioned REST uses HTTP methods for communication and state transfer. Following are most commonly used HTTP methods in REST.
- GET - To get a single or multiple records
- POST - To add a new record
- PUT - To update a record
- DELETE - To delete a single record
URL Structure Used in REST
The URLs in REST can be of any structure but as a standard following structure is used for different HTTP methods.
- GET /employees: Fetch all employees records.
- GET /employees/1: Fetch single employee record with id of 1.
- POST /employees: Add a new employee record to database.
- PUT /employees/1: Update a single employee record with the id 1.
- DELETE /employees/1: Delete a single employee record with the id 1.
Now that we have a understanding of what REST API structure is, Let's start with practical implementation and create PHP REST API.
Add Constants
Add constants for database connection and REST authorization token.
constants.php
<?php
define('DB_HOST', 'DATABASE_HOSTNAME'); // Your database host
define('DB_NAME', 'DATABASE_NAME'); // Your database name
define('DB_USER', 'DATABASE_USERNAME'); // Username for database
define('DB_PASSWORD', 'DATABASE_PASSWORD'); // Password for database
define('REST_AUTH_TOKEN', 'REST_AUTH_TOKEN'); // Authorization token
Create a Database Layer File
Create a file which will contain database functions to easily perform database transactions in our API endpoint file.
db.php
<?php
// Disable error reporting
error_reporting(0);
include 'constants.php';
global $db_connection;
// Open database connection
$db_connection = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME) OR die(mysqli_connect_error());
/**
* Function to fetch records from table
* @param string $query
* @return string|array
*/
function db_get(string $query): string|array
{
global $db_connection;
$rs = mysqli_query($db_connection, $query);
if($rs){
$result = mysqli_fetch_all($rs,MYSQLI_ASSOC);
}else{
$result = mysqli_error($db_connection);
}
return $result;
}
/**
* Function to add record to database table,
* @param string $table
* @param array $data
* @return string|int
*/
function db_insert(string $table, array $data): string|int
{
global $db_connection;
$keys = array_keys($data);
// Escaping values before insert
$values = array_map(function($value){
global $db_connection;
return mysqli_real_escape_string($db_connection,$value);
}, array_values($data));
$query = "INSERT INTO $table (".implode(",",$keys).") VALUES ('".implode("','",$values)."')";
$rs = mysqli_query($db_connection,$query);
if($rs){
$result = mysqli_insert_id($db_connection);
}else{
$result = mysqli_error($db_connection);
}
return $result;
}
/**
* Function to update record in database table,
* @param string $table
* @param array $data
* @param ?string $where
* @return string|bool
*/
function db_update(string $table, array $data, ?string $where = ''): string|bool
{
global $db_connection;
$bind = [];
foreach($data as $key => $value){
$value = mysqli_real_escape_string($db_connection,$value);
$bind[] = "$key = '$value'";
}
$query = "UPDATE $table SET ".implode(', ',$bind)." WHERE $where";
$rs = mysqli_query($db_connection,$query);
if($rs){
$result = true;
}else{
$result = mysqli_error($db_connection);
}
return $result;
}
/**
* Function to delete record from database table,
* @param string $table
* @param string $where
* @return string|bool
*/
function db_delete(string $table, string $where): string|bool
{
global $db_connection;
$query = "DELETE FROM $table WHERE $where";
$rs = mysqli_query($db_connection,$query);
if($rs){
$result = true;
}else{
$result = mysqli_error($db_connection);
}
return $result;
}
Create a REST API in PHP
Our api.php is basically our REST API endpoint and handles the client-server REST communication for requests. We return different responses based on request method and we also handle the API authorization with token.
- Set HTTP headers to to application/json and tell client server will send JSON response.
- Set access control header to allow only GET, POST, PUT and DELETE methods. This tells the client API accepts only these HTTP methods.
- Set access control to allow only Content-Type, Authorization and X-Requested-With headers.
- Set cache headers to not cache and store API response.
- Check if Authorization header in request has the authorization token. If it is missing set the HTTP response and return JSON response with appropriate error message.
- Check if request headers contain the content type either application/json or application/x-www-form-urlencoded. If content type is not one of these then return error response.
- Prepare an array of request data as $input variable for based on the content type client sent in header.
- Handle each request for request method provided using a switch statement. The request method can be one of these (GET, POST, PUT, DELETE). Perform action based on request method in each switch case and set the response code.
- Finally at the end set the HTTP response code using http_response_code() method and return response as JSON.
api.php
<?php
include 'db.php';
// SET application header, allowed methods & headers
header('Content-Type: application/json; charset=UTF-8');
header('Access-Control-Allow-Methods: GET,POST,PUT,DELETE');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
header('Cache-Control: no-cache,no-store,must-revalidate');
header('Pragma: no-cache');
// Get all request headers & and lower case header keys to handle case sensitivity
$request_headers = array_change_key_case(getallheaders(), CASE_LOWER);
// Set initial response code to current code
$response_code = http_response_code();
// Check if request contains authorization token
if(!isset($request_headers['authorization']) || ($request_headers['authorization'] !== REST_AUTH_TOKEN)){
$res = [
'success' => 0,
'message' => 'Unauthorized request'
];
http_response_code(401);
die(json_encode($res, JSON_PRETTY_PRINT));
}
// Check if request contains proper content type
if(!isset($request_headers['content-type'])
|| (($request_headers['content-type'] !== 'application/x-www-form-urlencoded')
&& ($request_headers['content-type'] !== 'application/json'))){
$res = [
'success' => 0,
'message' => 'Set content-type to application/x-www-form-urlencoded or application/json'
];
http_response_code(400);
die(json_encode($res, JSON_PRETTY_PRINT));
}
// Get the method used to call API
$request_method = $_SERVER['REQUEST_METHOD'];
// Raw input received in request
$input_raw = file_get_contents('php://input');
// Prepare input for both json/x-www-form-urlencoded
$input_json = json_decode($input_raw,true); // Decode input to json
parse_str($input_raw,$input_arr); // Parse x-www-form-urlencoded to arrays
if(is_array($input_json)){
// If input was json set this input to be used in script
$input = $input_json;
}elseif(is_array($input_arr)){
// If input was x-www-form-urlencoded set this input to be used in script
$input = $input_arr;
}
switch($request_method){
case 'GET':
$where = 'WHERE 1=1';
// If employee id was passed , Fetch record against that id only
if(intval($_GET['id'] ?? null)){
$where .= " AND id = '".intval($_GET['id'])."'";
}
$employees = db_get("SELECT id,full_name,gender,email,designation FROM demo_employees $where");
$total = count($employees);
// Set json response after getting employee record(s)
$res = [
'success' => 1,
'data' => $employees, 'total' => $total
];
$response_code = 200;
break;
case 'POST':
// Set json response if full name & email was empty
if(empty($input['full_name']) && empty($input['email'])){
$res = [
'success' => 0,
'message' => 'Employee name and email can not be empty'
];
$response_code = 400;
break;
}
$data = [];
$data['full_name'] = $input['full_name'];
$data['email'] = $input['email'];
$data['gender'] = $input['gender'];
$data['designation']= $input['designation'];
db_insert('employees', $data);
// Return json response after adding employee
$res = [
'success' => 1,
'message' => 'Employee has been added'
];
$response_code = 200;
break;
case 'PUT':
// Set json response if no employee id was provided to update against
if(!isset($_GET['id'])){
$res = [
'success' => 0,
'message' => 'Missing parameter id'
];
$response_code = 400;
break;
}
// Set json response if full name or email was provided empty
if(empty($input['full_name']) || empty($input['email']))
{
$res = [
'success' => 0,
'message' => 'Employee name and email can not be empty'
];
$response_code = 400;
break;
}
$where = "id = '".intval($_GET['id'])."'";
$data['full_name'] = $input['full_name'];
$data['email'] = $input['email'];
$data['gender'] = $input['gender'];
$data['designation']= $input['designation'];
db_update('employees', $data, $where);
// Set json response after updating employee
$res = [
'success' => 1,
'message' => 'Employee has been updated'
];
$response_code = 200;
break;
case 'DELETE':
if(!isset($input['id'])){
$res = [
'success' => 0,
'message' => 'Missing parameter id'
];
$response_code = 400;
break;
}
$where = "id = '".intval($input['id'])."'";
db_delete('employees', $where);
// Set json response after deleting employee
$res = [
'success' => 1,
'message' => 'Employee has been deleted'
];
$response_code = 200;
break;
default:
// If requested method was other than GET,POST,PUT,DELETE, return an error message
$res = [
'success' => 0,
'message' => 'Invalid request'
];
$response_code = 400;
break;
}
// Set response status code
http_response_code($response_code);
// Return final json response
echo json_encode($res);
Rewrite URLs with .htaccess
Now that everything is ready to use our API lets play with .htaccess to write pretty URLs.
DirectoryIndex api.phpThis will change our URL as http://yourdomain.com/apifolder/api. Now open up postman and try all methods one by one. Responses should match as in screenshots below:
RewriteEngine On
## Replace Rewritebase to directory where you place downloaded files
RewriteBase /downloads/create-rest-api-in-php/
RewriteRule ^api/(\d+)$ api.php?id=$1 [L,NC,QSA]
RewriteRule ^api/?$ api.php [L,NC,QSA]
- GET / All Records
- GET / Single Record
- POST / Add New Record