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.
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 $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;
}
api.php
<?phpNow that everything is ready to use our API lets play with .htaccess to write pretty URLs.
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);
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