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 implement 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.
How to Build a REST API in PHP (With CRUD and Authorization Token)
Building a PHP REST API with authorization token and basic CRUD can be easily achieved in few steps as below:
- Create a
constants.phpfile to hold database constants. - Create a
db.phpwith database helper functions. - Create
api.phpfile to consume API requests and return responses. Handle authorization checks in this file. - Create
.htaccessfile to rewrite URLs for API endpoints. - Finally, test the REST API implementation.
Step 1: Add Database & REST API 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
Step 2: Create a Database Helper Functions
Create a file which will contain database functions to easily perform database SELECT, INSERT, UPDATE and DELETE queries with reusable functions for 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 $sql
* @param string $types
* @param array $params
* @return string|array
*/
function db_get(string $sql, string $types = '', array $params = []): array|string
{
global $db_connection;
if (!$stmt = mysqli_prepare($db_connection, $sql)) {
return mysqli_error($db_connection);
}
if (!empty($params)) {
mysqli_stmt_bind_param($stmt, $types, ...$params);
}
mysqli_stmt_execute($stmt);
if ($result = mysqli_stmt_get_result($stmt)) {
return mysqli_fetch_all($result, MYSQLI_ASSOC);
}
mysqli_stmt_close($stmt);
return mysqli_error($db_connection);
}
/**
* 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;
$columns = array_keys($data);
$sql = "INSERT INTO $table (" . implode(',', $columns) . ") VALUES (" . implode(',', array_fill(0, count($data), '?')) . ")";
if (!$stmt = mysqli_prepare($db_connection, $sql)) {
return mysqli_error($db_connection);
}
mysqli_stmt_bind_param($stmt, str_repeat('s', count($data)), ...array_values($data));
if (mysqli_stmt_execute($stmt)) {
return mysqli_insert_id($db_connection);
}
mysqli_stmt_close($stmt);
return mysqli_error($db_connection);
}
/**
* Function to update record in database table,
* @param string $table
* @param array $data
* @param string $where
* @param string $where_types
* @param array $where_params
* @return string|bool
*/
function db_update(string $table, array $data, string $where, string $where_types, array $where_params): string|bool
{
global $db_connection;
$bind = [];
foreach ($data as $key => $value) {
$bind[] = "$key = ?";
}
$sql = "UPDATE $table SET " . implode(', ', $bind) . " WHERE $where";
if (!$stmt = mysqli_prepare($db_connection, $sql)) {
return mysqli_error($db_connection);
}
mysqli_stmt_bind_param($stmt, str_repeat('s', count($data)) . $where_types, ...array_merge(array_values($data), $where_params));
$result = mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
return $result;
}
/**
* Function to delete record from database table,
* @param string $table
* @param string $where
* @param string $types
* @param array $params
* @return string|bool
*/
function db_delete(string $table, string $where, string $types, array $params): string|bool
{
global $db_connection;
$sql = "DELETE FROM $table WHERE $where";
if (!$stmt = mysqli_prepare($db_connection, $sql)) {
return mysqli_error($db_connection);
}
mysqli_stmt_bind_param($stmt, $types, ...$params);
$result = mysqli_stmt_execute($stmt);
mysqli_stmt_close($stmt);
return $result;
}
Step 3: 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. Following are the steps to create a simple REST API in PHP:
- Set HTTP headers to to
application/jsonand tell client server will send JSON response. - Set access control header to allow only
GET,POST,PUTandDELETEmethods. This tells the client API accepts only these HTTP methods. - Set access control to allow only
Content-Type,AuthorizationandX-Requested-Withheaders. - 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/jsonorapplication/x-www-form-urlencoded. If content type is not one of these then return error response. - Prepare an array of request data as
$inputvariable, 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) methods. 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
$input = [];
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;
}
$input = array_map('filter_var', $input);
switch ($request_method) {
case 'GET':
// If employee id was passed , Fetch record against that id only
if (isset($_GET['id'])) {
$employees = db_get('SELECT id,full_name,gender,email,designation FROM employees WHERE id = ?',
'i',
[intval($_GET['id'])]);
} else {
$employees = db_get("SELECT id,full_name,gender,email,designation FROM employees");
}
$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 cannot 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 cannot be empty'
];
$response_code = 400;
break;
}
$data['full_name'] = $input['full_name'];
$data['email'] = $input['email'];
$data['gender'] = $input['gender'];
$data['designation'] = $input['designation'];
db_update('employees', $data, 'id = ?', 'i', [intval($_GET['id'])]);
// Set json response after updating employee
$res = [
'success' => 1,
'message' => 'Employee has been updated'
];
$response_code = 200;
break;
case 'DELETE':
if (!isset($_GET['id'])) {
$res = [
'success' => 0,
'message' => 'Missing parameter id'
];
$response_code = 400;
break;
}
db_delete('employees', 'id = ?', 'i', [intval($_GET['id'])]);
// 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);
Step 4: Rewrite URLs with .htaccess
Now that everything is ready to test our API, There is one last step to rewrite URLs with .htaccess for pretty URLs structure.
DirectoryIndex api.phpThis will change our URL as
RewriteEngine On
## Replace Rewritebase to directory where you place downloaded files
RewriteBase /www/create-rest-api-in-php/
RewriteRule ^api/(\d+)$ api.php?id=$1 [L,NC,QSA]
RewriteRule ^api/?$ api.php [L,NC,QSA]
http://yourdomain.com/apifolder/api. Now open the postman application and test all methods one by one. Responses should match as in screenshots below:- GET / All Records
- GET / Single Record

- POST / Add New Record