Create a REST API in PHP

REST stands for Representational State Transfer. Which is only a stateless representation of information  among different resources. Where as API stands for Application Programming Interface which is an interface that allows different platforms to communicate.

Create a REST API in PHP

REST API in PHP is used to share information in a certain representation format using proper methods. Normally these interfaces use JSON format to exchange information. In this post we will be using our employees data which we have been using in previous posts. I will be using four basic and mostly used methods over http requests.

  • GET - To get a single or multiple records
  • POST - To add a new record
  • PUT - To update a record
  • DELELTE - To delete a single record

We will also implement a secure requests using an authorization token to authorize all requests. So lets start with our files structure we are going to need, define.php which will be containing all the constant values for database host, username, password and token etc. db.php will be playing the role of an abstraction layer for performing action as get, add, update, delete employees.

define.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


db.php

<?php
// Disable error reporting
error_reporting(0);
include('constants.php');
global $dbcon;

// Open database connection
$dbcon = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME) OR die(mysqli_connect_error());

/**
* Function to fetch records from table
* @param string $query
*/
function db_get(string $query): mixed
{
global $dbcon;

$rs = mysqli_query($dbcon, $query);

if($rs){
$result = mysqli_fetch_all($rs,MYSQLI_ASSOC);
}else{
$result = mysqli_error($dbcon);
}
return $result;
}

/**
* Function to add record to database table,
* @param string $table
* @param array $data
*/
function db_insert(string $table, string $data): mixed
{
global $dbcon;

$keys = array_keys($data);

// Escaping values before insert
$values = array_map(function($value){
global $dbcon;
return mysqli_real_escape_string($dbcon,$value);
}, array_values($data));

$query = "INSERT INTO $table (".implode(",",$keys).") VALUES ('".implode("','",$values)."')";
$rs = mysqli_query($dbcon,$query);

if($rs){
$result = mysqli_insert_id($dbcon);
}else{
$result = mysqli_error($dbcon);
}
return $result;
}

/**
* Function to update record in database table,
* @param string $table
* @param array $data
* @param ?string $where
*/
function db_update(string $table, array $data, ?string $where = ''): mixed
{
global $dbcon;

$bind = [];

foreach($data as $key => $value){
$value = mysqli_real_escape_string($dbcon,$value);
$bind[] = "$key = '$value'";
}

$query = "UPDATE $table SET ".implode(', ',$bind)." WHERE $where";
$rs = mysqli_query($dbcon,$query);

if($rs){
$result = true;
}else{
$result = mysqli_error($dbcon);
}

return $result;
}

/**
* Function to delete record from database table,
* @param string $table
* @param string $where
*/
function db_delete(string $table, string $where): mixed
{
global $dbcon;
$query = "DELETE FROM $table WHERE $where";
$rs = mysqli_query($dbcon,$query);

if($rs){
$result = true;
}else{
$result = mysqli_error($dbcon);
}

return $result;
}

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);


Now that everything is ready to use our API lets play with .htaccess to write pretty URLs.
DirectoryIndex api.php
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]
This 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:
  • GET / All Records

    Create a REST API in PHP
  • GET / Single Record

    Create a REST API in PHP
  • POST / Add New Record

    Create a REST API in PHP