Create a REST API in PHP
REST APIs allow applications to communicate with each other by enabling them to exchange data using simple HTTP Methods. Learn how to create a REST API in PHP with an authorization token.

REST APIs are used for stateless communication among different applications over the internet using HTTP methods. In this post, we will create a REST API in PHP and demonstrate how to use it for data exchange over the internet. We will also add an authorization token to authorize all API requests.
The files we are going to create for this post are:
- constants.php: Contains the constants for the database connection.
- db.php: 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 represents the current state of a data resource. 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. REST is used for stateless communication and each resource has a URL. Each request is independent and must contain all required data for the server to understand the request. This stateless communication takes place using HTTP methods like GET, POST, PUT, and DELETE.
Whereas 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 a PHP REST API interface in your application with a working demo and source code available for download.
HTTP Methods Used in REST
As explained, REST uses HTTP methods for communication and state transfer. The following are the 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, the following structure is used for different HTTP methods.
- GET /employees: Fetch all employee records.
- GET /employees/1: Fetch single employee record with id of 1.
- POST /employees: Add a new employee record to the 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 an understanding of what a REST API structure is, let's start with a practical implementation.
How to Build a REST API in PHP (With Authorization Token)
Building a PHP REST API with an authorization token and basic CRUD can be easily achieved in a few steps as follows:
- Create a
constants.phpfile to hold database constants. - Create a
db.phpwith database helper functions. - Create an
api.phpfile to consume API requests and return responses. Handle authorization checks in this file. - Create an
.htaccessfile to rewrite URLs for API endpoints. - Finally, test the REST API implementation.
Step 1: Add Database & REST API Constants
Add constants for the 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 that 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 the request method, and we also handle the API authorization with a token. The following are the steps to create a simple REST API in PHP:
- Set HTTP headers to
application/jsonand tell the server to send a JSON response. - Set the access control header to allow only
GET,POST,PUT, andDELETEmethods. This tells the client API accepts only these HTTP methods. - Set access control to allow only
Content-Type,Authorization, andX-Requested-Withheaders. - Set cache headers to not cache and store the API response.
- Check if the request headers contain the authorization header with the authorization token. If it is missing, set the HTTP response and return a JSON response with an appropriate error message.
- Check if the request headers contain the content type, either
application/jsonorapplication/x-www-form-urlencoded. If the content type is not one of these, return an error response. - Prepare an array of request data as the
$inputvariable, based on the content type the client sent in the header. - Handle each request for the request method provided using a switch statement. The request method can be one of these (GET, POST, PUT, DELETE) methods. Perform an action based on the request method in each switch case and set the response code.
- Finally, at the end, set the HTTP response code using the
http_response_code()method and return the 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 lowercase 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 a pretty URL structure.
DirectoryIndex api.phpThis will change our URL to
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 the screenshots below:- GET / All Records
- GET / Single Record

- POST / Add New Record